socket()参数详解

socket()参数详解

2023年7月15日发(作者:)

socket()参数详解原⽂链接:sock_raw(注意⼀定要在root下使⽤)原始套接字编程可以接收到本机⽹卡上的数据帧或者数据包,对与监听⽹络的流量和分析是很有作⽤的.⼀共可以有3种⽅式创建这种socket

(AF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)发送接收ip数据包,不能⽤IPPROTO_IP,因为如果是⽤了IPPROTO_IP,系统根本就不知道该⽤什么协议。(PF_PACKET, SOCK_RAW, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))发送接收以太⽹数据帧(AF_INET, SOCK_PACKET, htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))过时了,不要⽤啊

理解⼀下SOCK_RAW的原理, ⽐如⽹卡收到了⼀个 14+20+8+100+4(以太⽹头+ip头+udp头+数据+crc) 的udp的以太⽹数据帧.

⾸先,⽹卡对该数据帧进⾏硬过滤(根据⽹卡的模式不同会有不同的动作,如果设置了promisc混杂模式的话,则不做任何过滤直接交给下⼀层输⼊例程,否则⾮本机mac或者⼴播mac会被直接丢弃).按照上⾯的例⼦,如果成功的话,会进⼊ip输⼊例程.但是在进⼊ip输⼊例程之前,系统会检查系 统中是否有通过socket(AF_PACKET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例⼦中就是需要ETH_P_IP或者ETH_P_ALL类型.系统就给每个这样的socket接收缓 冲区发送⼀个数据帧拷贝.然后进⼊下⼀步.

其次,进⼊了ip输⼊例程(ip层会对该数据包进⾏软过滤,就是检查校验或者丢弃⾮本机ip或者⼴播ip的数据包等,具体要参考源代码),例⼦ 中就是如果成功的话会进⼊udp输⼊例程.但是在交给udp输⼊例程之前,系统会检查系统中是否有通过socket(AF_INET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例⼦中就是需要IPPROTO_UDP类型.系统就给每个这样的socket接收缓冲区发送⼀个数据 帧拷贝.然后进⼊下⼀步.

最后,进⼊udp输⼊例程 ...

ps:如果校验和出错的话,内核会直接丢弃该数据包的.⽽不会拷贝给sock_raw的套接字,因为校验和都出错了,数据肯定有问题的包括所有信息都没有意义了.

进⼀步分析他们的能⼒.1. socket(AF_INET, SOCK_RAW, IPPROTO_UDP);能:该套接字可以接收协议类型为(tcp udp icmp等)发往本机的ip数据包,从上⾯看的就是20+8+100.不能:不能收到⾮发往本地ip的数据包(ip软过滤会丢弃这些不是发往本机ip的数据包).不能:不能收到从本机发送出去的数据包.发送的话需要⾃⼰组织tcp udp icmp等头部.可以setsockopt来⾃⼰包装ip头部这种套接字⽤来写个ping程序⽐较适合

2. socket(PF_PACKET, SOCK_RAW, htons(x));

这个套接字⽐较强⼤,创建这种套接字可以监听⽹卡上的所有数据帧.从上⾯看就是20+20+8+100.最后⼀个以太⽹crc从来都不算进来的,因为内核已经判断过了,对程序来说没有任何意义了.能: 接收发往本地mac的数据帧能: 接收从本机发送出去的数据帧(第3个参数需要设置为ETH_P_ALL)能: 接收⾮发往本地mac的数据帧(⽹卡需要设置为promisc混杂模式)协议类型⼀共有四个ETH_P_IP 0x800 只接收发往本机mac的ip类型的数据帧ETH_P_ARP 0x806 只接受发往本机mac的arp类型的数据帧ETH_P_ARP 0x8035 只接受发往本机mac的rarp类型的数据帧ETH_P_ALL 0x3 接收发往本机mac的所有类型ip arp rarp的数据帧, 接收从本机发出的所有类型的数据帧.(混杂模式打开的情况下,会接收到⾮发往本地mac的数据帧)

发送的时候需要⾃⼰组织整个以太⽹数据帧.所有相关的地址使⽤struct sockaddr_ll ⽽不是struct sockaddr_in(因为协议簇是PF_PACKET不是AF_INET了),⽐如发送给某个机器,对⽅的地址需要使⽤struct sockaddr_ll.

在使⽤SOCK_RAW, SOCK_DGRAM和SOCK_PACKET的区别(详请参考 )

在socket的第⼀个参数使⽤PF_PACKET的时候,上述三种socket的类型都可以使⽤。但是有区别。

(1)使⽤SOCK_RAW发送的数据必须包含链路层的协议头,接受得到的数据包,包含链路层协议头。⽽使⽤SOCK_DGRAM则都不含链路层的协议头。 (2)SOCK_PACKET也是可以使⽤的,但是已经废弃,以后不保证还能⽀持,不推荐使⽤。

(3)在使⽤SOCK_RAW或SOCK_DGRAM和SOCK_PACKET时,在sendto和recvfrom中使⽤的地址类型不同,前两者使⽤sockaddr_ll类型的地址,⽽后者使⽤sockaddr类型的地址。

(4)如socket的第⼀个参数使⽤PF_INET,第⼆个参数使⽤SOCK_RAW,则可以得到原始的IP包。这种socket⼤⼩通吃,强悍

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1689408350a243269.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信