2011-01-03 3 views
2

Я хочу написать небольшое приложение, использующее Libpcap в C на Linux.прослушивание с использованием Pcap с таймаутом

В настоящее время он начинает нюхать и ждать пакетов. Но это не то, что мне нужно на самом деле. Я хочу, чтобы он подождал N секунд, а затем прекратил слушать.

Как я могу это достичь?

Вот мой код:

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) 
{ 
     printf("got packet\n); 
} 

int main() 
{ 
int ret = 0; 
char *dev = NULL; /* capture device name */ 
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ 
pcap_t *handle; /* packet capture handle */ 

char filter_exp[] = "udp dst port 1500"; /* filter expression */ 
struct bpf_program fp; /* compiled filter program (expression) */ 
bpf_u_int32 mask; /* subnet mask */ 
bpf_u_int32 net; /* ip */ 
int num_packets = 10; /* number of packets to capture */ 


/* get network number and mask associated with capture device */ 
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { 
    fprintf(stderr, "Couldn't get netmask for device %s: %s\n", 
     dev, errbuf); 
    net = 0; 
    mask = 0; 
} 


/* print capture info */ 
printf("Device: %s\n", dev); 
printf("Number of packets: %d\n", num_packets); 
printf("Filter expression: %s\n", filter_exp); 




/* open capture device */ 
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); 
if (handle == NULL) { 
    fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf); 
    exit(EXIT_FAILURE); 
} 



/* compile the filter expression */ 
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { 
    fprintf(stderr, "Couldn't parse filter %s: %s\n", 
     filter_exp, pcap_geterr(handle)); 
    exit(EXIT_FAILURE); 
} 

/* apply the compiled filter */ 
if (pcap_setfilter(handle, &fp) == -1) { 
    fprintf(stderr, "Couldn't install filter %s: %s\n", 
     filter_exp, pcap_geterr(handle)); 
    exit(EXIT_FAILURE); 
} 

/* now we can set our callback function */ 
pcap_loop(handle, num_packets, got_packet, NULL); 

/* cleanup */ 
pcap_freecode(&fp); 
pcap_close(handle); 
} 
+0

Пожалуйста, отформатируйте код. –

ответ

2

Если посмотреть на this странице с TCPDUMP сайте, вы можете увидеть follwing:

Открытие устройства для нюхают

Задача создания сеанса нюхания на самом деле довольно проста. Для этого используется pcap_open_live(). Прототип этой функции (из страницы PCAP) выглядит следующим образом:

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, 
         char *ebuf) 

первый аргумент является устройством, которое мы определили в предыдущем разделе. snaplen - целое число, которое определяет максимальное количество байтов, которое должно быть записано pcap. promisc, когда установлено значение true, приводит интерфейс в беспорядочный режим (однако, даже если для него установлено значение false, в некоторых случаях возможно, что интерфейс будет в беспорядочном режиме). to_ms - это время ожидания чтения в миллисекундах (значение 0 означает отсутствие тайм-аута, по крайней мере на некоторых платформах, это означает, что вы можете дождаться достаточного количества пакетов до того, как увидите какие-либо пакеты, поэтому вы должны использовать не- нулевой тайм-аут). Наконец, ebuf - это строка, в которой мы можем хранить любые сообщения об ошибках внутри (как мы это делали выше с errbuf). Функция возвращает наш обработчик сеанса.

Если это не поможет, сообщите нам об этом.

+0

Я использую pcap_open_live со значением тайм-аута, но не останавливается, когда заканчивается 1000 мс: pcap_open_live (dev, SNAP_LEN, 1, 1000, errbuf); – xyzt

+0

@xyzt - Пожалуйста, разместите свой код. –

6

Вы должны позвонить pcap_breakloop(), если хотите прекратить прослушивание. Таким образом, один из способов будет:

  • установки будильника Чтобы вызвать в N секунд,
  • установить обработчик сигнала для SIGALRM сигнала,
  • вызов pcap_breakloop() внутри обработчика сделать pcap_loop() возвращения.

код:

void alarm_handler(int sig) 
{ 
    pcap_breakloop(handle); 
} 

int main() 
{ 
    ... 

    alarm(N); 
    signal(SIGALRM, alarm_handler); 

    /* now we can set our callback function */ 
    pcap_loop(handle, num_packets, got_packet, NULL); 

    /* cleanup */ 
    pcap_freecode(&fp); 
    pcap_close(handle); 
} 

Примечание: Что касается использования тайм-аута чтения Libpcap, чтобы сделать это, она не будет и не может работать, человек PCAP явно предостерегает против него:

Тайм-аут чтения не может использоваться для вызова вызовов, которые считывают пакеты в течение ограниченного периода времени [...] Это означает, что тайм-аут чтения НЕ должен использоваться, например, в интерактивном приложении, чтобы разрешить цикл захвата пакета опрос для пользовательского ввода периодически, так как нет гарантии, что t пакеты считывания вызовов будут возвращены после истечения таймаута, даже если пакеты не были получены.

0

Я изучал и тестировал эти фрагменты кода некоторое время. Где-то я заметил, что, когда вы выходите из pcap_loop, хотя вы, возможно, видели пакеты, условия выхода показывают, что вы их не видели. Я предполагаю, что вся обработка пакета должна выполняться в области функции обратного вызова. Поэтому, если я хочу быстро выполнить сброс и быть готовым к другому пакету, мне нужно будет создать другой процесс для работы над каждым пакетом.

0

Старый пост, но я изучал и наткнулся на это.

С man-страницы для pcap_loop() он специально говорит: «Он не возвращается, когда происходят таймауты реального времени, вместо этого он пытается читать больше пакетов».

Но страницы руководства для pcap_dispatch() и pcap_next() указывают, что они возвращаются в таймаут.

Смежные вопросы