关于原始套接字的两个小问题

Posted 笛在月明楼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于原始套接字的两个小问题相关的知识,希望对你有一定的参考价值。

1、原始套接字的协议是否可以设置为IPPRORO_TCP?UDP和TCP分组没有对应的套接字,此时会不会将其传递到原始套接口?

答:

(1) 可以。对于socket()函数,在流式套接字编程中第二个参数是SOCK_STREAM,而对于数据报套接字编程,第二个参数是SOCK_DGRAM,在这两种情况下,第三个参数可以填0,这样系统会自动匹配相应的协议。

而原始套接字编程中,第二个参数是SOCK_RAW,在这种情况下,第三个参数必须指明相应的协议,协议类型的常用取值有 IPPROTO_IP、IPPROTO_ICMP、IPPROTO_TCP、IPPROTO和IPPROTO_RAW。

(2) 不会。接收到的UDP或者TCP分组绝不传递到任何原始套接字,如果一个进程想要读取含有UDP分组或TCP分组的IP数据报,它就必须在数据链路层读取这些分组(即使用IPPROTO_IP选项读取整个IP包)。

使用 IPPROTO_TCP 和 IPPROTO_UDP选项的原始套接字时,只能发TCP或者UDP数据包(是否需要对IP头部的操作由 IP_HDRINCL 决定),而不能接收TCP或者UDP协议的数据包,因为TCP和UDP数据包由内核进行协议的判断,并查找IP地址和端口号相匹配的socket连接来递交数据包,而原始套接字没有端口的概念,因此不能接收TCP或者UDP的数据包。原始套接字只能通过IPPROTO_IP来获得整个IP数据包,然后从中提取TCP和UDP的数据。

2、原始套接字构造IP头的情况下,用send,还是sendto?如果是sendto的话,参数to和构造的首部中的IP地址不一致,或者connect、bind的IP地址与构造的首部中的IP不一致,如何处理?

答:

(1) 原始套接口发送数据通常用sendto,在第五个参数to中指定要发送的目的地址。如果调用过connect,目的地址已经设定,发送数据时,可以直接调用send,当然也可以用sendto,并且第五个参数to设置为NULL。当to不为NULL时,系统会把数据发送到to所指定的目的地址

(2) 会失败,错误码为WSAEINTR。目的是限制恶意的代码去做拒绝服务攻击或者不允许发送带有假IP地址的欺骗数据报。

以上是关于关于原始套接字的两个小问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中使用原始套接字?

原始套接字

关于socket(AF_INET, SOCK_RAW,...)这个原始套接字

网络骇客初级之原始套接字(SOCK_RAW)

原始套接字的问题

Linux基础(11)原始套接字