Разбор пакетов ppi pcap
У меня возникли проблемы с анализом пакетов в формате кадра PPI. Мне нужно поле 802.11+mac+phy, после общего поля кажется, что у меня ошибка в смещении. Вот мой код:
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
int offset = 0;
const struct ppi_packetheader *ppi_header = (struct ppi_packetheader *)(packet + offset);
offset += 8;
const struct ppi_fieldheader *ppi_80211_common = (struct ppi_fieldheader *)(packet + offset);
printf("common type: %d | len: %d\n", ppi_80211_common->pfh_type, ppi_80211_common->pfh_datalen);
offset += 4 + 20;
const struct ppi_fieldheader *ppi_80211_mac = (struct ppi_fieldheader *)(packet + offset);
printf("mac type: %d | len: %d\n", ppi_80211_mac->pfh_type, ppi_80211_mac->pfh_datalen);
offset += 4 + 27;
const struct ppi_fieldheader *ppi_80211_mac_phy = (struct ppi_fieldheader *)(packet + offset);
printf("mac+phy type: %d | len: %d\n", ppi_80211_mac_phy->pfh_type, ppi_80211_mac_phy->pfh_datalen);
}
Вывод для общего поля правильный, он говорит type: 2, len: 20. Но другие значения неверны, как сказано для типа поля mac: 64, len: 0 (mac+phy выглядит аналогично). Это проблема с маленьким / большим порядком байтов или где моя ошибка? Я смотрел на реализацию Wireshark, но они используют функцию tvb_get_letohs() для смещения, и это довольно сложно... Надеюсь, кто-то может помочь.
1 ответ
Прежде всего, вы не смотрите на бит выравнивания в pph_flags
- если оно установлено, то каждое поле выравнивается по 4-байтовой границе, и, если оно ясно, поля не обязательно выравниваются по 4-байтовым границам. Однако длина поля 802.11-Common кратна 4, равно как и длина заголовка поля, поэтому, хотя вы должны смотреть на этот бит, это не вызовет этой конкретной проблемы.
И, да, "многобайтовые целые числа в заголовке пакета и заголовках полей ДОЛЖНЫ храниться как little-endian.", Поэтому может возникнуть проблема с порядком байтов. Однако это относится к pfh_type
а также pfh_datalen
Таким образом, в то время как вы должны поменять эти значения байтами, если вы находитесь на машине с прямым порядком байтов (вот что tvb_get_letohs()
выполняет - получает из буфера Wireshark, который выполняет проверку границ, значение Little Endian, Short (16-bit) и преобразует его в байтовый порядок хоста; это также работает независимо от того, выровнено ли поле по "естественной" границе байта), вы, очевидно, работаете на машине с прямым порядком байтов (если это ПК на базе x86- который включает в себя все Mac на базе Intel - вы работает на машине с прямым порядком байтов), поскольку вывод для общего поля является правильным, так что это, вероятно, не вызывает этой конкретной проблемы.
В-третьих, однако, вы не смотрите на ppi_header->pph_len
! Нет никакой гарантии, что какие-либо конкретные поля присутствуют в заголовке PPI - вы должны проверить, для каждого поля, присутствует ли оно, проследив, прошли ли вы длину заголовка PPI.
Когда я записал на свой Retina MBP в Mountain Lion с заголовками PPI, длина заголовка составляла 32 байта, и единственным присутствующим полем было поле 802.11-Common - поле расширений 802.11n MAC + PHY не было (и наш сеть является сетью 802.11n). Когда ваш код думает, что смотрит на поле MAC+PHY Extensions 802.11n, он на самом деле может смотреть на заголовок MAC 802.11 из пакета 802.11.