Вы делаете несколько вещей неправильно.
первая вещь, которую вы делаете неправильно, объявляет заголовок радиоленты как структуру с большим количеством полей, чем it_version
, it_pad
, it_len
и it_present
. абсолютно не гарантирует , что в произвольном заголовке радиоленты будет, например, 64-битное поле MAC_timestamp
, следующее за полем it_present
. Вы должны посмотреть на поле it_present
, чтобы увидеть, какие из полей в заголовке действительно присутствуют. См. веб-сайт радиоленты для получения подробной информации о том, как обрабатывать заголовок радиоленты.
Сравнение значений полей с 0 (или NULL
) работает не работает - если поле отсутствует, оно просто не существует .
Ваш код может работать с определенными версиями драйверов для определенных сетевых адаптеров в определенных ОС, но он может не работать, если драйвер был изменен или вы работаете на машине с адаптером другого типа (например, Atheros vs Адаптеры Broadcom на компьютерах Mac) или если вы попытаетесь запустить его в другой операционной системе (например, в Linux).
Если вы ожидаете, что этот код будет выполняться на машине с прямым порядком байтов, вам также нужно будет более осторожно извлекать поля из заголовка радиоленты, поскольку они все с прямым порядком байтов. (#define
в вашем коде не достаточно для этого.)
За исключением проблемы порядка байтов, которая будет отображаться на Mac, только если вы работаете на PowerPC Mac, вы правильно пропускают мимо заголовка радиоленты, так что это не проблема.
Кроме того, временная метка MAC-адреса представляет собой 64-разрядное целое число, и на 32-разрядном компьютере она должна быть напечатана с %llu
вместо %u
.
Вы также должны проверять наличие ошибок. pcap_create()
и pcap_activate()
, по-видимому, не дают сбоя, если вы видите пакеты, так что это, вероятно, не является непосредственной проблемой, но вам все равно следует проверять наличие ошибок. Процедуры pcap_set_
также, вероятно, не выходят из строя, по крайней мере, не на устройствах Wi-Fi, но вы должны проверить в любом случае.
Если вы предполагаете, что пакеты являются пакетами радиолента 802.11 +, вам, вероятно, следует хотя бы проверить, чтобы возвращаемое значение pcap_datalink()
было DLT_IEEE802_11_RADIO
, и потерпеть неудачу, если это не так. Пока вы это делаете, добавьте новую строку в конец сообщения, напечатанного для типа канального слоя.
Но main считает, что вы делаете неправильно, захватывает не более 30 байтов каждого пакета! Когда вы делаете pcap_set_snaplen(descr,30);
, вы говорите «не захватывайте больше 30 байтов»; заголовок радиоленты, вероятно, длиннее этого, так что вы даже не получите весь заголовок радиоленты, а тем более заголовок 802.11.
Если вы хотите захватить весь пакет , просто оставьте вызов pcap_set_snaplen()
.
О, и если вы хотите быть действительно осторожным, убедитесь, что, глядя на радиоленту и заголовок 802.11, вы не прошли pkthdr->caplen
.
Это также означает, что ваш цикл, который проверяет pkthdr->len
, должен проверять pkthdr->caplen
И должен либо начинаться с пакета [0], либо вычитать rh->it_len
из pkthdr->caplen
(как вы должны были проверить убедитесь, что rh->it_len
больше или равно pkthdr->caplen
во время или до того, как вы проанализировали заголовок радиоленты, результат этого вычитания будет положительным). Длина снимка включает все псевдоголовки, такие как заголовок радиоленты.