прослушивание с использованием Pcap с таймаутом - PullRequest
2 голосов
/ 03 января 2011

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

В настоящее время оно начинает прослушивать и ждать пакетов.Но это не то, что мне нужно на самом деле.Я хочу, чтобы он подождал 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);
}

Ответы [ 5 ]

6 голосов
/ 06 декабря 2012

Вы должны позвонить 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, он не будет и не сможет 'В этом случае man pcap явно предупреждает об этом:

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

2 голосов
/ 03 января 2011

Если вы посмотрите на эту страницу с tcpdump веб-сайта, вы увидите следующее:

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

Задача создания сеанса сниффинга действительно очень проста. Для этого мы используем 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 голосов
/ 10 сентября 2018

Вы можете использовать функцию pcap_next () и установить время ожидания с помощью pcap_set_timeout, для libpcap 1.8.1 вам нужен немедленный режим, см. https://github.com/the-tcpdump-group/libpcap/issues/572.

0 голосов
/ 02 мая 2017

Старый пост, но я исследовал и наткнулся на это.

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

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

0 голосов
/ 11 мая 2016

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

...