2011-04-15 51 views
2

我的Python程序正在從原始套接字接收ICMP目標不可達消息。使用以下代碼創建套接字:從Python原始套接字接收的數據包中交換了兩個字節

socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) 

ICMP目標不可達消息包含原始數據包的一部分的副本。我遇到的問題是嵌入式IPv4頭中的2字節總長度字段在從套接字接收到字節時會交換字節。因爲這是我的程序中的校驗和檢查失敗。數據包收到以下代碼:

packet, sockaddr = socket_.recvfrom(bufsize) 

當我發現校驗和測試失敗時,我用tcpdump檢查了數據包。這裏是一個例子:

11:54:36.377352 IP (tos 0xc0, ttl 64, id 36894, offset 0, flags [none], proto ICMP (1), length 112) 
    10.200.200.200 > 10.175.211.104: ICMP host 10.175.211.13 unreachable, length 92 
    IP (tos 0x0, ttl 63, id 49898, offset 0, flags [none], proto ICMP (1), length 84) 
    10.175.211.104 > 10.175.211.13: ICMP echo request, id 29449, seq 6, length 64 
    0x0000: 45c0 0070 901e 0000 4001 3807 0ac8 c8c8 
    0x0010: 0aaf d368 0301 fcfe 0000 0000 4500 0054 
    0x0020: c2ea 0000 3f01 fcea 0aaf d368 0aaf d30d 
    0x0030: 0800 403f 7309 0006 9b43 7718 e292 a89a 
    0x0040: 28cf 5283 dc65 8219 2778 837b 6c54 92f4 
    0x0050: 5092 e976 568c 6681 2afc 2b82 628d d0f6 
    0x0060: 2fa7 3493 1f48 9fdb ed98 2f53 da0e 87a6 

然後我從我的Python代碼打印出數據包。下面是從tcpdump的例子相同的分組:

45,c0,5c,0,90,1e,0,0,40,1,38,7,a,c8,c8,c8, 
a,af,d3,68,3,1,fc,fe,0,0,0,0,45,0,54,0, 
c2,ea,0,0,3f,1,fc,ea,a,af,d3,68,a,af,d3,d, 
8,0,40,3f,73,9,0,6,9b,43,77,18,e2,92,a8,9a, 
28,cf,52,83,dc,65,82,19,27,78,83,7b,6c,54,92,f4, 
50,92,e9,76,56,8c,66,81,2a,fc,2b,82,62,8d,d0,f6, 
2f,a7,34,93,1f,48,9f,db,ed,98,2f,53,da,e,87,a6, 

嵌入報頭的總長度字段是關於第二行的最後兩個字節。 0054從tcpdump和5400從我的程序。外部IP標頭的總長度字段也是錯誤的(5c00與tcpdump中的0070相比)。

我正在......

的Python 2.6.1(R261:67515,2010年6月24日,21點47分49秒) [GCC 4.2.1(蘋果公司建立5646)對達爾文

來自tcpdump的ICMP目標不可達數據包中的校驗和字段是正確的。它具有fcfe的值。這是沒有out IP頭的數據包。

0x0010:   0301 fcfe 0000 0000 4500 0054 
0x0020: c2ea 0000 3f01 fcea 0aaf d368 0aaf d30d 
0x0030: 0800 403f 7309 0006 9b43 7718 e292 a89a 
0x0040: 28cf 5283 dc65 8219 2778 837b 6c54 92f4 
0x0050: 5092 e976 568c 6681 2afc 2b82 628d d0f6 
0x0060: 2fa7 3493 1f48 9fdb ed98 2f53 da0e 87a6 

讓我感到困惑的是,只有總長度字段纔會針對網絡字節順序進行更正。其他多字節字段不會更改,並且會像我的Python程序一樣打印出來。例如,在tcpdump和我的打印輸出中,總長度後的兩個字節組成了標識字段,其值爲c2ea。我怎樣才能確定爲了檢查校驗和而應該交換哪些字段?

+0

這不是關於校驗和的問題。這是一個關於爲什麼兩個字節在從套接字讀取時被交換的問題。也許你應該編輯你的問題標題和身體來反映這一點! – 2011-04-15 23:09:13

回答

3

這些字段可能是網絡字節順序(即big-endian),並且您使用的是小端機。所以,需要字節交換。內置於Python中的struct library應該可以幫助您處理這些消息的deserialization。請參考7.3.2.1. Byte Order, Size, and Alignment

我建議參考RFC文檔中的每個協議(例如,RFC 791RFC 792)來獲取有關字段序列化的進一步知識。

+0

謝謝!我玩弄了struct.unpack,這讓我質疑爲什麼總長度是唯一由tcpdump交換的多字節字段,並且是唯一需要交換來計算校驗和的字段。我在最初的帖子中添加了更多信息。 – 2011-04-18 18:24:38

+0

@Brian A校驗和通常按字節放置在線上的順序進行計算。在計算校驗和之前,您不必進行字節交換。 – 2011-04-18 21:37:24