два байта поменялись местами в пакете, полученном от необработанного сокета Python - PullRequest
2 голосов
/ 16 апреля 2011

Моя программа на 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.Как определить, какие поля следует поменять местами для проверки контрольной суммы?

1 Ответ

3 голосов
/ 18 апреля 2011

Эти поля, вероятно, имеют сетевой порядок байтов (т. Е. big-endian ), и вы используете машину с прямым порядком байтов.Итак, замена байтов необходима.Встроенная в Python библиотека struct должна помочь вам десериализации этих сообщений.Пожалуйста, обратитесь к разделу 7.3.2.1.Порядок, размер и выравнивание байтов .

Я бы рекомендовал обратиться к документу RFC для каждого протокола (например, RFC 791 и RFC792 ) используется для получения дополнительных знаний о том, как поля сериализуются.

...