欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    Linux网络编程原始套接字的魔力【下】.pdf

    • 资源ID:70006660       资源大小:944.81KB        全文页数:6页
    • 资源格式: PDF        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    Linux网络编程原始套接字的魔力【下】.pdf

    Linux网络编程:原始套接字的魔力【下】星期四,8月 23 2012,10:47 下午可以接收链路层MAC帧的原始套接字 前面我们介绍过了通过原始套接字socket(AF_INET,SOCK_RAW,protocol)我们可以直接实现自行构造整个IP报文,然后对其收发。提醒一点,在用这种方式构造原始IP报文时,第三个参数protocol不能用IPPROTO_IP,这样会让系统疑惑,不知道该用什么协议来伺候你了。今天我们介绍原始套接字的另一种用法:直接从链路层收发数据帧,听起来好像很神奇的样子。在Linux系统中要从链路层(MAC)直接收发数帧,比较普遍的做法就是用libpcap和libnet两个动态库来实现。但今天我们就要用原始套接字来实现这个功能。这里的2字节帧类型用来指示该数据帧所承载的上层协议是IP、ARP或其他。为了实现直接从链路层收发数据帧,我们要用到原始套接字的如下形式:socket(PF_PACKET,type,protocol)1、其中type字段可取SOCK_RAW或SOCK_DGRAM。它们两个都使用一种与设备无关的标准物理层地址结构struct sockaddr_ll,但具体操作的报文格式不同:SOCK_RAW:直接向网络硬件驱动程序发送(或从网络硬件驱动程序接收)没有任何处理的完整数据报文(包括物理帧的帧头),这就要求我们必须了解对应设备的物理帧帧头结构,才能正确地装载和分析报文。也就是说我们用这种套接字从网卡驱动上收上来的报文包含了MAC头部,如果我们要用这种形式的套接字直接向网卡发送数据帧,那么我们必须自己组装我们MAC头部。这正符合我们的需求。SOCK_DGRAM:这种类型的套接字对于收到的数据报文的物理帧帧头会被系统自动去掉,然后再将其往协议栈上层传递;同样地,在发送时数据时,系统将会根据sockaddr_ll结构中的目的地址信息为数据报文添加一个合适的MAC帧头。2、protocol字段,常见的,一般情况下该字段取ETH_P_IP,ETH_P_ARP,ETH_P_RARP或ETH_P_ALL,当然链路层协议很多,肯定不止我们说的这几个,但我们一般只关心这几个就够我们用了。这里简单提一下网络数据收发的一点基础。协议栈在组织数据收发流程时需要处理好两个方面的问题:“从上倒下”,即数据发送的任务;“从下到上”,即数据接收的任务。数据发送相对接收来说要容易些,因为对于数据接收而言,网卡驱动还要明确什么样的数据该接收、什么样的不该接收等问题。protocol字段可选的四个值及其意义如下:protocol值作用ETH_P_IP0X0800只接收发往目的MAC是本机的IP类型的数据帧ETH_P_ARP0X0806只接收发往目的MAC是本机的ARP类型的数据帧ETH_P_RARP0X8035只接受发往目的MAC是本机的RARP类型的数据帧ETH_P_ALL0X0003接收发往目的MAC是本机的所有类型(ip,arp,rarp)的数据帧,同时还可以接收从本机发出去的所有数据帧。在混杂模式打开的情况下,还会接收到发往目的MAC为非本地硬件地址的数据帧。protocol字段可取的所有协议参见/usr/include/linux/if_ether.h头文件里的定义。最后,格外需要留心一点的就是,发送数据的时候需要自己组织整个以太网数据帧。和地址相关的结构体就不能再用前面的struct sockaddr_in了,而是structsockaddr_ll,如下:点击(此处)折叠或打开1.struct sockaddr_ll 2.unsigned short sll_family;/*总是 AF_PACKET*/3.unsigned short sll_protocol;/*物理层的协议*/4.int sll_ifindex;/*接口号*/5.unsigned short sll_hatype;/*报头类型*/6.unsigned char sll_pkttype;/*分组类型*/7.unsigned char sll_halen;/*地址长度*/8.unsigned char sll_addr8;/*物理层地址*/9.;sll_protocoll:取值在linux/if_ether.h中,可以指定我们所感兴趣的二层协议;sll_ifindex:置为0表示处理所有接口,对于单网卡的机器就不存在“所有”的概念了。如果你有多网卡,该字段的值一般通过ioctl来搞定,模板代码如下,如果我们要获取eth0接口的序号,可以使用如下代码来获取:点击(此处)折叠或打开1.struct sockaddr_ll sll;2.struct ifreq ifr;3.4.strcpy(ifr.ifr_name,eth0);5.ioctl(sockfd,SIOCGIFINDEX,&ifr);6.sll.sll_ifindex=ifr.ifr_ifindex;sll_hatype:ARP硬件地址类型,定义在 linux/if_arp.h中。取ARPHRD_ETHER时表示为以太网。sll_pkttype:包含分组类型。目前,有效的分组类型有:目标地址是本地主机的分组用的 PACKET_HOST,物理层广播分组用的 PACKET_BROADCAST,发送到一个物理层多路广播地址的分组用的 PACKET_MULTICAST,在混杂(promiscuous)模式下的设备驱动器发向其他主机的分组用的PACKET_OTHERHOST,源于本地主机的分组被环回到分组套接口用的PACKET_OUTGOING。这些类型只对接收到的分组有意义。sll_addr和sll_halen指示物理层(如以太网,802.3,802.4或802.5等)地址及其长度,严格依赖于具体的硬件设备。类似于获取接口索引sll_ifindex,要获取接口的物理地址,可以采用如下代码:点击(此处)折叠或打开1.struct ifreq ifr;2.3.strcpy(ifr.ifr_name,eth0);4.ioctl(sockfd,SIOCGIFHWADDR,&ifr);缺省情况下,从任何接口收到的符合指定协议的所有数据报文都会被传送到原始PACKET套接字口,而使用bind系统调用并以一个sochddr_ll结构体对象将PACKET套接字与某个网络接口相绑定,就可使我们的PACKET原始套接字只接收指定接口的数据报文。接下来我们简单介绍一下网卡是怎么收报的,如果你对这部分已经很了解可以跳过这部分内容。网卡从线路上收到信号流,网卡的驱动程序会去检查数据帧开始的前6个字节,即目的主机的MAC地址,如果和自己的网卡地址一致它才会接收这个帧,不符合的一般都是直接无视。然后该数据帧会被网络驱动程序分解,IP报文将通过网络协议栈,最后传送到应用程序那里。往上层传递的过程就是一个校验和“剥头”的过程,由协议栈各层去实现。接下来我们来写个简单的抓包程序,将那些发给本机的IPv4报文全打印出来:点击(此处)折叠或打开#include 1.#include 2.#include 3.#include 4.#include 5.#include 6.#include 7.#include 8.#include 9.#include 1 0.1 1.int main(int argc,char*argv)1 2.int sock,n;1 3.char buffer2048;1 4.struct ethhdr*eth;1 5.struct iphdr*iph;1 6.1 7.if(0(sock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP)1 8.perror(socket);1 9.exit(1);2 0.2 1.2 2.while(1)2 3.printf(=n);2 4./注意:在这之前我没有调用bind函数,原因是什么呢?2 5.n=recvfrom(sock,buffer,2048,0,NULL,NULL);2 6.printf(%d bytes readn,n);2 7.2 8./接收到的数据帧头6字节是目的MAC地址,紧接着6字节是源MAC地址。2 9.eth=(struct ethhdr*)buffer;3 0.printf(Dest MAC addr:%02x:%02x:%02x:%02x:%02x:%02xn,eth-h_dest0,eth-h_dest1,eth-h_dest2,eth-h_dest3,eth-h_dest4,eth-h_dest5);3 1.printf(Source MAC addr:%02x:%02x:%02x:%02x:%02x:%02xn,eth-h_source0,eth-h_source1,eth-h_source2,eth-h_source3,eth-h_source4,eth-h_source5);3 2.3 3.iph=(struct iphdr*)(buffer+sizeof(struct ethhdr);3 4./我们只对IPV4且没有选项字段的IPv4报文感兴趣3 5.if(iph-version=4&iph-ihl=5)3 6.printf(Source host:%sn,inet_ntoa(iph-saddr);3 7.printf(Dest host:%sn,inet_ntoa(iph-daddr);3 8.3 9.4 0.编译,然后运行,要以root身份才可以运行该程序:正如我们前面看到的,网卡丢弃所有不含有主机MAC地址00:0C:29:BA:CB:61的数据包,这是因为网卡处于非混杂模式,即每个网卡只处理源地址是它自己的帧!这里有三个例外的情况:1、如果一个帧的目的MAC地址是一个受限的广播地址(255.255.255.255)那么它将被所有的网卡接收。2、如果一个帧的目的地址是组播地址,那么它将被那些打开组播接收功能的网卡所接收。3、网卡如被设置成混杂模式,那么它将接收所有流经它的数据包。前面我们刚好提到过网卡的混杂模式,现在我们就来迫不及待的实践一哈看看混杂模式是否可以让我们抓到所有数据包,只要在while循环前加上如下代码就OK了:点击(此处)折叠或打开1.struct ifreq ethreq;2.3.strncpy(ethreq.ifr_name,eth0,IFNAMSIZ);4.if(-1=ioctl(sock,SIOCGIFFLAGS,&ethreq)5.perror(ioctl);6.close(sock);7.exit(1);8.9.ethreq.ifr_flags|=IFF_PROMISC;1 0.if(-1=ioctl(sock,SIOCGIFFLAGS,&ethreq)1 1.perror(ioctl);1 2.close(sock);1 3.exit(1);1 4.1 5.while(1)1 6.1 7.至此,我们一个网络抓包工具的雏形就出现了。大家可以基于此做更多的练习,加上多线程机制,对收到的不同类型的数据包做不同处理等等,反正由你发挥的空间是相当滴大,“狐狸未成精,只因太年轻”。把这块吃透了,后面理解协议栈就会相当轻松。

    注意事项

    本文(Linux网络编程原始套接字的魔力【下】.pdf)为本站会员(qwe****56)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开