这是一个关于Linux C编程原始套接字的快速问题。如果我只想使用原始套接字来监听任何接口,我是否必须绑定到IP地址或接口以便监听流量? 据我所知,我应该只需调用sock();然后开始recvfrom()流量。也许我错了,但我看到一些程序没有使用它。
这是一个关于Linux C编程原始套接字的快速问题。如果我只想使用原始套接字来监听任何接口,我是否必须绑定到IP地址或接口以便监听流量? 据我所知,我应该只需调用sock();然后开始recvfrom()流量。也许我错了,但我看到一些程序没有使用它。
你是正确的,唯一需要做的就是调用socket()
,然后调用recvfrom()
。但要注意使用SOCK_RAW
进行监听存在一些限制。
如果您没有在“发送并忘记”的基础上使用原始套接字,则会对您的原始数据包的回复数据包感兴趣。判断将数据包传递到原始套接字的逻辑可以枚举如下:
TCP和UDP数据包永远不会传递到原始套接字中,它们总是由内核协议栈处理。
ICMP数据包的副本将传递到匹配的原始套接字中。对于某些ICMP类型(ICMP请求回显、ICMP时间戳请求、掩码请求),内核可能同时希望进行一些处理并生成回复。
所有IGMP数据包都会传递到原始套接字中:例如OSPF数据包。
所有其他目标为未由内核子系统处理的协议的数据包都会传递到原始套接字中。
您正在处理的协议所涉及到的回复数据包被传递到您的原始套接字中并不意味着您一定会收到回复数据包。对此,您还需要考虑以下几点:
在通过socket(2)系统调用创建套接字时相应地设置协议。例如,如果您发送一个ICMP请求回显数据包,并希望接收ICMP请求回复数据包,则可以将协议参数(第三个参数)设置为IPPROTO_ICMP。
在socket(2)中将协议参数设置为0,以便在接收到的数据包头中匹配任何协议号。
为套接字定义本地地址(例如通过bind(2)),因此如果目标地址与套接字的本地地址匹配,则也将传递给您的应用程序。
要了解更多细节,您可以阅读例如这篇文章。
如果您想捕获接口上的流量,可以使用libpcap。