2

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

目前,它开始嗅探并等待数据包。但这不是我真正需要的。我希望它等待 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);
}
4

4 回答 4

7

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 明确警告不要这样做:

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

于 2012-12-06T17:51:43.873 回答
2

如果您从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 所做的那样)。该函数返回我们的会话处理程序。

如果这不起作用,请告诉我们。

于 2011-01-03T10:21:22.133 回答
0

我一直在研究和测试这些代码片段。在某个地方,我注意到当您退出 pcap_loop 时,虽然您可能已经看到了数据包,但退出条件表明您没有看到任何数据包。我由此假设数据包的所有处理都必须发生在回调函数的范围内。因此,如果我想快速重置并准备好接收另一个数据包,我将需要生成另一个进程来处理每个数据包。

于 2016-05-10T21:19:23.697 回答
0

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

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

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

于 2017-05-02T16:15:52.103 回答