【问题标题】:Should I write id to icmphdr id field when using icmp sockets?使用 icmp 套接字时,我应该将 id 写入 icmphdr id 字段吗?
【发布时间】:2014-10-31 05:28:01
【问题描述】:

我正在编写发送 icmp 回显请求的简单程序。我正在使用 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: add IPPROTO_ICMP

消息标识符(ICMP 标头的八位字节 4-5)被解释为本地 港口。地址存储在 struct sockaddr_in 中。没有端口号 为特权进程保留,端口 0 为 API 保留(“让 内核选择一个空闲号码”)。没有远程端口的概念,远程 用户提供的端口号(例如在 connect() 中)被忽略。

我不清楚。 那么请告诉我,我是否应该填写这个文件?

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

这里是整个代码和 tcpdump 输出:code and dump

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

【问题讨论】:

    标签: c sockets unix ping icmp


    【解决方案1】:

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

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

    但最终,您(发件人)似乎要决定如何使用这些字段。如果需要,您可能可以将一些其他有意义的数据放入其中,然后将其回显给您。

    【讨论】:

    • 对不起,我发布了错误的代码。我知道序列字段。所以,我有类似的东西:req.un.echo.id=htons(12); req.un.echo.sequence=htons(1); 它不起作用。在 tcpdump 中,他的 id 字段不是 12。请查看我的代码 pastebin code 和 tcpdump 输出 pastebin tcpdump。提交的 id 被其他东西覆盖(内核?)
    【解决方案2】:

    您应该绑定到要用作 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-22
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多