使用PCAP与超时听 [英] listening using Pcap with timeout

查看:139
本文介绍了使用PCAP与超时听的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要写在Linux上使用C中的Libpcap的一个小应用程序。

目前,它开始嗅探并等待数据包。但是,这不是我的实际需要。我希望它等待N秒,然后停止监听。

我怎样才能做到这一点?

下面是我的code:

 无效got_packet(u_char * ARGS,常量结构pcap_pkthdr *头,常量u_char *包)
{
       的printf(得到包\\ n)的;
}诠释的main()
{
 INT RET = 0;
 字符* dev的= NULL; / *捕获设备名称* /
 烧焦errbuf [PCAP_ERRBUF_SIZE] / *错误缓冲区* /
 pcap_t *手柄; / *数据包捕获手柄* / 烧焦filter_exp [] =UDP目的端口1500; / *过滤器前pression * /
 结构bpf_program FP; / *编译过滤器程序(如pression)* /
 bpf_u_int32口罩; /* 子网掩码 */
 bpf_u_int32网; / * * IP /
 INT num_packets = 10; / *包的数量来捕捉* /
 / *与捕获设备*有关获得网络号和掩码/
 如果(pcap_lookupnet(DEV,&安培;净&安培;面膜,errbuf)== -1){
  fprintf中(标准错误,无法对设备%s的网络掩码获取%S \\ n,
      开发,errbuf);
  净= 0;
  屏蔽= 0;
 }
 / *打印捕获信息* /
 的printf(设备:%S \\ n,DEV);
 的printf(数据包数:%d \\ n,num_packets);
 的printf(过滤前pression:%S \\ n,filter_exp);
 / *打开捕获设备* /
 处理= pcap_open_live(DEV,SNAP_LEN,1,1000,errbuf);
 如果(手柄== NULL){
  fprintf中(标准错误,无法打开设备%S:%S \\ n,开发,errbuf);
  出口(EXIT_FAILURE);
 } / *编译过滤器前pression * /
 如果(使用pcap_compile(手柄,和放大器; FP,filter_exp,0,净)== -1){
  fprintf中(标准错误,无法解析过滤%S:%S \\ n,
      filter_exp,pcap_geterr(手柄));
  出口(EXIT_FAILURE);
 } / *应用过滤器编译* /
 如果(pcap_setfilter(手柄,和放大器; FP)== -1){
  fprintf中(标准错误,无法安装过滤%S:%S \\ n,
      filter_exp,pcap_geterr(手柄));
  出口(EXIT_FAILURE);
 } / *现在,我们可以设置我们的回调函数* /
 pcap_loop(手柄,num_packets,got_packet,NULL); /* 清理 */
 pcap_free code(安培; FP);
 pcap_close(手柄);
}


解决方案

您应该叫 pcap_breakloop()当你想停止收听。所以,一种方式将是:


  • 设置报警在N秒触发,

  • 安装一个信号处理器 SIGALRM 信号时,

  • 通话 pcap_breakloop()里面的处理程序,使 pcap_loop()的回报。

code:

 无效alarm_handler(INT SIG)
{
    pcap_breakloop(手柄);
}诠释的main()
{
    ...    报警(N);
    信号(SIGALRM,al​​arm_handler);    / *现在,我们可以设置我们的回调函数* /
    pcap_loop(手柄,num_packets,got_packet,NULL);    /* 清理 */
    pcap_free code(安培; FP);
    pcap_close(手柄);
}

请注意:由于使用的libpcap的读取超时要做到这一点,它不会也不能工作,人PCAP明确警告反对:


  

读超时不能用来使该读数据包的有限的一段时间内返回呼叫[...]这意味着读取超时不应该被使用,例如,在一个交互式应用,以允许该数据包捕获循环轮询用户输入的定期,因为谁也不能保证,即使没有数据包已经到达超时到期后打电话阅读包会回来。


I want to write a small application using Libpcap in C on Linux.

Currently, it starts to sniff and wait for the packets. But that's not what I need actually. I want it to wait for N seconds and then stop listening.

How can I achieve that?

Here is my code:

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);
}

解决方案

You should call pcap_breakloop() when you want stop listening. So one way would be to:

  • setup an alarm to trigger in N seconds,
  • install a signal handler for SIGALRM signal,
  • call pcap_breakloop() inside the handler to make pcap_loop() return.

code:

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);
}

Note: As for using libpcap's read timeout to do this, it won't and can't work, man pcap explicitly warns against it:

The read timeout cannot be used to cause calls that read packets to return within a limited period of time [...] This means that the read timeout should NOT be used, for example, in an interactive application to allow the packet capture loop to poll for user input periodically, as there's no guarantee that a call reading packets will return after the timeout expires even if no packets have arrived.

这篇关于使用PCAP与超时听的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆