使用Pcap监听超时

问题描述 投票:2回答:5

我想在Linux上使用C语言编写一个小应用程序。

目前,它开始嗅探并等待数据包。但这不是我真正需要的。我希望它等待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);
}
c linux pcap
5个回答
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的读取超时来执行此操作,它将不会也无法工作,man pcap明确警告它:

读取超时不能用于使读取数据包的调用在有限的时间内返回[...]这意味着不应使用读取超时,例如,在交互式应用程序中允许数据包捕获循环定期轮询用户输入,因为即使没有数据包到达,也无法保证在超时到期后呼叫读取数据包将返回。


2
投票

如果你看一下tcpdump网站上的this页面,你可以看到以下内容:

打开设备进行嗅探

创建嗅探会话的任务非常简单。为此,我们使用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_loop时,尽管你可能已经看过数据包,但退出条件表明你没有看到过。我假设数据包的所有处理必须在回调函数的范围内进行。因此,如果我想快速重置并为另一个数据包做好准备,我将需要生成另一个进程来处理每个数据包。


0
投票

老帖子,但我正在研究并遇到这个。

从pcap_loop()的手册页中,它明确地说,“当实时读取超时发生时它不会返回;相反,它会尝试读取更多数据包。”

但pcap_dispatch()和pcap_next()的手册页都表明它们在超时时返回。


0
投票

您可以使用pcap_next()函数并使用pcap_set_timeout设置超时,对于libpcap 1.8.1,您需要立即模式,请参阅https://github.com/the-tcpdump-group/libpcap/issues/572

© www.soinside.com 2019 - 2024. All rights reserved.