在看网络编程书的时候却发现这样一条讲解:
接收到的UDP分组和TCP分组绝不传递到任何原始套接口。如果一个进程想要读取含有UDP分组或TCP分组的IP数据报,它就必须在数据链路层读取这些分组。
这句讲解让人很疑惑,按理说是能够通过raw socket接口编写tcp syn数据包进行syn探测的,如果不能接收tcp分组就不能对回应的数据包进行判断。因此,写了几个小程序进行了一下测试。
测试结果如下:
对于通过socket(PF_INET,SOCK_RAW,IPPROTO_XX)创建的raw 套接字能够接收所有L4层协议类型为指定IPPROTO_XX的数据包,而不会区分所接收数据包的五元组(源地址、目的地址、源端口、目的端口),所有指定协议的数据报文都能被接收,所以,如何区分是需要应用层去做的,比如对于icmp报文可以通过id、seq进行判断,对于tcp、udp则可以通过源地址及端口进行判断。
正是因为如此,raw socket经常用于icmp这类便于区分的类型,而tcp、udp则可能被对端发来数据包所欺骗。
其中,IPPROTO_XX的范围从0到255,其中协议号为0,即IPPROTO_IP,不能创建套接字;而协议号255,即IPPROTO_RAW,为默认开启IP_HDRINCL套接口选项,此时能够构造全部L4,L3报文部分完成发送,但通过此套接字不能够接收到IP报文。即对此套接字进行recvfrom不能获取到数据。
若想接收IP报文,则必须通过创建另一种套接字socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP)),此时才能够从链路层直接获取整个IP数据报文。
在通过raw socket进行编程时,创建出的套接字选项与sockaddr并不关联,也就是说在完成数据发送后,可以通过创建同种类型的另一套接字进行接收,只要协议类型符合即可。
这样看来,跟书上那句话应该是相冲突的,也许是linux内核实现不同,也许还没理解这句话的真正含义。。。
阅读(1963) | 评论(0) | 转发(0) |