2014-09-06 56 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