2014-09-06 40 views
1

我正在写简单的程序,发送icmp回应请求。我使用ping套接字(为了能够发送没有suid)。使用icmp套接字时,我应该写id到icmphdr id字段吗?

我这是怎么打开插座:

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保留(“让 内核选择一个空闲号码”)。没有远程端口的概念,用户提供的端口号(例如,在连接()中)的远程 被忽略。

这并不明确。 那么请你能告诉我,如果我应该填补这个问题吗?

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

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

它说明我的问题,在代码ID设置为12(只是一个随机数,尝试了许多人),但在转储ICMP报文头有编号为4

回答

0

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

1

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

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

但最终,发件人似乎决定如何使用这些字段。你也许可以在其中添加一些其他有意义的数据,并且如果你愿意的话可以回显给你。

+0

对不起,我贴错代码。我了解序列领域。所以,我有这样的: 'req.un.echo.id = htons(12); req.un.echo.sequence = htons(1);'它不起作用。在tcpdump中他的id字段不是12.请看我的代码[pastebin code](http://pastebin.com/uX6unXE3)和tcpdump输出[pastebin tcpdump](http://pastebin.com/Y22g0Riw)。 ID字段被其他内容覆盖(内核?) – cereal 2014-09-06 13:16:02

相关问题