Для разбора рамы я поднял голову this page.
Теперь на Perl ...
my $l3protlen = ord substr $raw_bytes, 14, 1;
Извлечение 15 байт (символов) с $raw_bytes
, и преобразовать его порядкового значения (например, символ «A» будет преобразовано в целое число 65 (0x41), предполагая, что набор символов - ASCII). Так Perl может обрабатывать двоичные данные, как если бы они были строкой (например, передавали ее substr
), но затем вы можете вернуть двоичные значения и обрабатывать их как числа. (Но помните TMTOWTDI.)
В кадре IPv4 первые 14 байтов представляют собой заголовок MAC (по 6 байт для адресата и MAC-адреса источника, а затем 2-байтовый Ethertype, который, вероятно, 0x8000 - вы могли бы проверить это). После этого 15-й байт является началом полезной нагрузки данных Ethernet: первый байт содержит версию (верхние 4 байта) и длину заголовка в DWORD (более низкие 4 байта).
Теперь мне кажется, что в следующей строке этого примера кода есть ошибка, но, возможно, это нормально работает на случайности!
my $l3prot = $l3protlen & 0xf0 >> 2; # the protocol part
В Perl >>
имеет более высокий приоритет, чем &
, так что это будет эквивалентно
my $l3prot = $l3protlen & (0xf0 >> 2);
или, если вы предпочитаете
my $l3prot = $l3protlen & 0x3c;
Итак, извлекает биты 2 - 5 из $l3prot
Значение: значение маски 0x3c равно 0011 1100 в двоичном формате. Так, например, значение 0x86 (в двоичном выражении, 1000 0110) станет 0x04 (двоичное 0000 0100). Фактически, «нормальное» значение IPv4 равно 0x45, то есть тип протокола 4, длина заголовка 5 слов. Маска, которая с 0x3c и вы получите ... 4! Но только от fluke: вы проверили верхние 2 бита длины, а не тип протокола!
Эта линия должна быть, конечно,
my $l3prot = ($l3protlen & 0xf0) >> 4;
(примечание кронштейны для старшинства и сдвиг 4 бита, а не 2). (Я нашел эту же ошибку в CPAN documentation, так что я предполагаю, что это, вероятно, довольно широко распространено.)
return unless $l3prot == 4; # return unless IPv4
Для IPv4, мы ожидаем, что это значение будет 4 - если это не так, выскочить из функции сразу. (Таким образом, неверный код выше, дает результат, который позволяет это можно интерпретировать как пакеты IPv4, но только по счастливой случайности.)
my $l4prot = ord substr $packet, 23, 1;
Теперь извлечь 24-й байт и преобразовать в значение порядкового таким же образом.Это протокол байт из заголовка IP:
return unless $l4prot == '7';
Мы ожидаем, что это будет 7 - если он не выскочит из функции сразу. (Согласно IANA, 7 - «Основы на основе ядра» ... но я думаю, вы знаете, какие протоколы вам интересны!)
Очень хорошо объяснено. Да, я смотрел специально для udp, поэтому 7. – nohup
@nohup - Спасибо! но UDP - 17, а не 7 ... Также вы пробовали это с моей предложенной коррекцией к строке '' & 0xf0'? – AAT
Отлично и хорошо объяснено. Хорошая работа, определяющая эти ошибки –