墙外查资料神器,红杏一支:http://honx.in/i/VLiJPuz5NEXSBXSY
///
今天中午看了一下socket()中各参数的意思,以及各种组合的相关含义,现归纳一些raw_socket使用组合,以备查阅:
(1)当socket()中第一个参数为AF_INET(等价于PF_INET)时,表示的是获取从网络层开始的数据:
socket(PF_INET,SOCK_RAW,......):
当接收包时,表示用户获得是完整的包含IP报头的数据包,即数据从IP头开始算起;
当发送包时,用户只能发送包含UDP报头或TCP报头或其他传输层协议的报文,IP报头以及以太网帧头则由内核自动加封
(除非是设置了IP_HDRINCL的socket选项)。
例如:socket(PF_INET,SOCK_RAW,IPPROTO_TCP)表示接受的数据为IP报头+TCP报头+数据。其他类似。
而socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)表示进程接受的数据直接为应用层数据。
同理socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)也是。
(2)当socket()中第一个参数为PF_PACKET时,表示获取的是从数据链路层开始的数据:
socket(PF_PACKET,SOCK_RAW,htos(ETH_P_IP)):表示获得IPV4的数据链路层帧,即数据包含以太网帧头。
(3)socket(PF_INET,SOCK_RAW,IPPROTO_RAW)只能发包不能收包,且发包时用户可以自己编写各层的报头,且
内核为你自动加封以太网帧头,用户不用管。(IP_HDRINCL选项晚于IPPROTO_RAW协议字段)
总结:
原始套接口的输入:无论何时往一个原始IPV4套接口传递一个接收到的数据,传递到该套接口所在进程的都是包括IP头部在内
的完整的数据报。而对于原始的IPV6套接口,传递的只是扣除了IPV6头部和所有扩展头部的净荷。
原始套接口的输出:如果IP_HDRINCL套接口选项未开启,那么由进程让内核发送的数据的起始地址指向IP头部之后的第一个
字节,因为内核将构造IP头部。内核把所构造的IPV4头部协议字段设置成来自socket调用的第3个参数。
如果IP_HDRINCL选项已开启,那么进程发送数据的起始地址为IP头部的第一个字节,进程调用输出函数写出的数据量必须包
括IP头部的大小。整个IP 头部由进程构造,不过:(1)IPV4标识字段可置为0,从而告知内核设置该值;(2)IPV4头部校验和
字段总是由内核计算并存储;(3)IPV4选项字段是可选的。
-----------To my love NN