Моя программа на Python получает ICMP-сообщения о недоступности получателя из необработанного сокета.Сокет создается с помощью следующего кода:
socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
ICMP-сообщения о недоступности получателя включают копию части исходного пакета.Проблема, с которой я сталкиваюсь, заключается в том, что в 2-байтовом поле общей длины во встроенном заголовке IPv4 байты меняются местами при получении из сокета.Из-за этого не проходит проверку контрольной суммы в моей программе.Пакет получен со следующим кодом:
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,
Поле общей длины встроенного заголовка - это последние два байта во 2-й строке.0054 из tcpdump и 5400 из моей программы.Поле общей длины внешнего IP-заголовка также неверно (5c00 против 0070 из tcpdump).
Я работаю ...
Python 2.6.1 (r261: 67515, 24 июня2010, 21:47:49) [GCC 4.2.1 (сборка Apple Inc., 5646)] на darwin
Поле контрольной суммы в недоступном для ICMP целевом пакете из tcpdump является правильным.Это имеет значение 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.Например, два байта после общей длины составляют поле идентификации со значением c2ea в tcpdump и my print out.Как определить, какие поля следует поменять местами для проверки контрольной суммы?