从Python原始套接字收到的数据包中交换了两个字节

| 我的Python程序正在从原始套接字接收ICMP目标不可达消息。使用以下代码创建套接字:
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,
嵌入式标头的总长度字段是第二行的最后两个字节。来自tcpdump的0054和来自我的程序的5400。外部IP标头的总长度字段也不正确(5c00与tcpdump中的0070)。 我在跑步... Python 2.6.1(r261:67515,2010年6月24日,21:47:49) 达尔文[GCC 4.2.1(Apple Inc. build 5646)] 来自tcpdump的ICMP目标不可达数据包中的校验和字段正确。它的值是fcfe。这是没有输出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。如何确定为检查校验和而应交换的字段?     
已邀请:
这些字段可能采用网络字节顺序(即big-endian),并且您使用的是little-endian机器。因此,需要字节交换。 Python内置的struct库应该可以帮助您反序列化这些消息。请参考7.3.2.1。字节顺序,大小和对齐方式。 我建议您参考所使用的​​每种协议的RFC文档(例如RFC 791和RFC 792),以进一步了解如何对字段进行序列化。     

要回复问题请先登录注册