Вызов pcap_next заполняет pcap_pkthdr с len равным нулю
Я использую libpcap версии 1.1.1, собранный как статическая библиотека (libpcap.a). Когда я пытаюсь выполнить следующий блок кода на 64-битном RHEL 6 (сам исполняемый модуль построен как 32-битный образ ELF), я получаю ошибку сегментации:
const unsigned char* packet;
pcap_pkthdr pcap_header = {0};
unsigned short ether_type = 0;
while ( ether_type != ntohs( 0x800 ) )
{
packet = pcap_next ( m_pcap_handle, &pcap_header );
if (packet != NULL)
{
memcpy ( ðer_type, &( packet[ 12 ] ), 2 );
}
else
{
/*Sleep call goes here*/
}
}
if ( raw_buff ->data_len >= pcap_header.caplen )
{
memcpy ( raw_buff->data, &(packet[14]), pcap_header.len -14 );
raw_buff->data_len = pcap_header.len -14;
raw_buff->timestamp = pcap_header.ts;
}
Небольшое исследование показало, что поле pcap_header.len равно нулю при возврате pcap_next. На самом деле поле caplen, похоже, отражает размер пакета правильно. Если я пытаюсь сбросить память пакета с адреса пакета - данные, кажется, действительны. По лен поля, равного нулю, я знаю, что это неверно. Это должно быть, по крайней мере, как каплену величины. Это ошибка? Какие шаги я должен предпринять, чтобы исправить это?
GDB показывает содержимое pcap_header как:
(gdb) p pcap_header
$ 1 = {ts = {tv_sec = 5242946, tv_usec = 1361456997}, caplen = 66, len = 0}
Может быть, я могу применить обходной путь? Я не хочу обновлять версию libpcap.
2 ответа
Надеюсь, я погуглил описание дефекта " https://bugzilla.redhat.com/show_bug.cgi?id=557728", и, похоже, оно до сих пор актуально. Проблема исчезла, когда я связал свое приложение с версией libpcap для общей библиотеки вместо того, чтобы связать его со статической. Затем система связывает мое приложение с libpcap во время выполнения, которое поставляется с RHEL.
С уважением, Александр Черняев.
Ядра до версии 2.6.27 не поддерживают запуск 32-битных двоичных файлов с использованием libpcap 1.0 или более поздней версии на 64-битном ядре.
В libpcap 1.0 и более поздних версиях используется механизм захвата с отображением в памяти в ядрах Linux, в которых он есть, и первая версия этого механизма не обеспечивала совместное использование структур данных между ядром и кодом с использованием механизма захвата с отображением в память были расположены в памяти одинаково в 32-битном и 64-битном режиме.
Ядра 2.6, предшествующие ядру 2.6.27, имеют только первую версию этого механизма. Ядро 2.6.27 имеет вторую версию этого механизма, которая гарантирует, что структуры данных располагаются в памяти одинаково в 32-битном и 64-битном режиме, так что 32-битный код пользовательского режима работает одинаково поверх 32-битных и 64-битных ядер.