c-使用icmp套接字时,是否应该将id写入icmphdr id字段



我正在编写一个简单的程序,用于发送icmp echo请求。我正在使用ping套接字(以便能够在没有suid的情况下发送)。

这就是我打开插座的方式:

int fd=socket(PF_INET,SOCK_DGRAM,IPPROTO_ICMP);

这就是我构建icmp数据报的方式:

struct icmphdr req;
req.type=8;
req.code=0;
req.checksum=0;
req.un.echo.id=htons(12);
req.un.echo.sequence=htons(1);

我用sendto()发送数据包,它运行得很好,我的意思是目标主机接收请求,发送响应,我可以在我的程序中接收这个响应。

然而,我不确定un.echo.id字段的含义。在网上的许多示例中,这个字段都填充了rand()等内容。但后来它被覆盖了,我可以在tcpdump中清楚地看到它。

我发现了这样的描述:LWN.net net:ipv4:添加IPPROTO_IICMP

消息标识符(ICMP报头的八位字节4-5)被解释为本地端口。地址存储在结构体sockaddr_in中。没有端口号为特权进程保留,端口0为API保留("让kernel pick a free number")用户提供的端口号(例如,在connect()中)将被忽略。

我不清楚。所以,请你告诉我,我是否应该填写这个档案?

更新:多亏了John的Zwinck anwer,我意识到我发布了错误的代码示例,现在它是正确的。

以下是完整的代码和tcpdump输出:代码和转储

它说明了我的问题,在代码中,id设置为12(只是一个随机数,尝试了许多其他数字),但dump中的icmp标头的id设置为4。

id字段可用于区分发送消息的程序。因此,您可以使用类似PID或其他时间上唯一的数字标识符(甚至是随机数,只要它是作为一个操作发送的所有消息的相同随机数)。

sequence字段应该是一个连续的递增数字,而不是像现在这样的随机数字。

但最终,似乎由你,发送者,来决定如何使用这些字段。如果你愿意的话,你可能会在它们中放入一些其他有意义的数据,并将其反馈给你。

您应该绑定到要用作icmp id的端口。添加

struct sockaddr_in sa;
sa.sin_family = PF_INET;
sa.sin_port = htons(12);
sa.sin_addr.s_addr = htonl(INADDR_ANY);

socket() 之后

if (bind(fd,  (struct sockaddr *) &sa, sizeof(sa)) < 0)
        return -1;

这将导致id成为您想要的。您可以将req.un.echo.id字段设置为0。id为12:的示例运行

ICMP回复,id=0xc00,序列=0x100

最新更新