首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >libpcap包嗅探流量分析

libpcap包嗅探流量分析
EN

Stack Overflow用户
提问于 2015-03-22 01:59:58
回答 1查看 269关注 0票数 0

我在C++上用libpcap做了一个包嗅探器。这是我的代码。

代码语言:javascript
复制
int PacketSniff(int *count)
{
   int ifnum;
   int NumOfDevs=0;
   char errbuf[PCAP_ERRBUF_SIZE];
   bpf_u_int32 ip;
   bpf_u_int32  netmask;
   struct in_addr ip_addr , netmask_addr;
   pcap_if_t *devs , *d;
   pcap_t *handler;
   char packet_filter[] = "ip";
   struct bpf_program fcode;


   /* Find all interface devices */
   pcap_findalldevs(&devs, errbuf);

   for(d=devs; d; d=d->next)
   {
       printf("%d. %s", ++NumOfDevs, d->name);
       if (d->description)
       {
           printf(" (%s)\n", d->description);
       }
       else
       {
           printf(" (No description available)\n");
       }
   }
   if(NumOfDevs==0)
   {
       printf("\nNo interfaces found!\n");
       return (-1);
   }


   /* Prompt User to select interface */
   printf("Enter the interface number (1-%d):\n",NumOfDevs);
   scanf("%d",&ifnum);

   if(ifnum < 1 || ifnum > NumOfDevs)
   {
       printf("\nInterface number out of range.\n");
       /* Free the device list */
       pcap_freealldevs(devs);
       return (-1);
   }


   /* Jump to the selected adapter/interface */
   for(d=devs; ifnum>1 ;d=d->next, ifnum--);

   /* Open the selected adapter/interface */
   handler = pcap_open_live(d->name, 65535, 0, 2000, errbuf);

   if ((handler = pcap_open_live(d->name, 65535, 0, 2000, errbuf)) == NULL)
   {
       fprintf(stderr, "Couldn't open device %s: %s\n", d->name, errbuf);
       return(-1);
   }




   if (pcap_datalink(handler) != DLT_EN10MB )
   {
       fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
       pcap_freealldevs(devs);
       return -1;

   }

   /* This means that we set the datalink layer header size at 14 */
   int linkhdrlen = 14;


   if (pcap_lookupnet(d->name, &ip, &netmask, errbuf) <0 )
   {
       fprintf(stderr, "Can't get netmask for device %s\n", d->name);
       netmask = 0;
       ip = 0;
   }


   /* Compile the filter */
   if (pcap_compile(handler, &fcode, packet_filter, 1, netmask) <0 )
   {
       fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.  Error:  %s\n", errbuf);
       pcap_freealldevs(devs);
       return -1;
   }

   /* Set the filter */
   if (pcap_setfilter(handler, &fcode)<0)
   {
       fprintf(stderr,"\nError setting the filter. Error: %s\n", errbuf);
       pcap_freealldevs(devs);
       return -1;
   }


   printf("\nListening for packets on interface <%s>...\n", d->name);

   /* At this point, we don't need any more the device list. Free it */
   pcap_freealldevs(devs);

   pcap_loop(handler, 0, my_callback, NULL);}

my_callback是这样的:

代码语言:javascript
复制
void my_callback(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_ptr){

   struct tm ltime;
   char timestr[16];
   struct ip_header *iphdr;
   struct tcp_header *tcphdr;
   time_t local_tv_sec;




   /* Convert the timestamp to readable format */

   local_tv_sec = header->ts.tv_sec;
   localtime_r(&local_tv_sec , &ltime);
   strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);

   /* Print timestamp and length of the packet */
   printf("Time >> %s.%.6d \nPacket Length:%d \n\n", timestr, header->ts.tv_usec, header->len);

   /* Retireve the position of the ip header    http://www.tcpdump.org/pcap.html */
   iphdr = (ip_header *) (pkt_ptr +14);       




   // Advance to the transport layer header then parse and display
   // the fields based on the type of hearder: tcp, udp or icmp.

   pkt_ptr += 4*iphdr->ver_ihl ;
   tcphdr = (tcp_header *)(pkt_ptr + 14);
   /* print ip addresses and tcp ports */
   printf("%d.%d.%d.%d : %d ---> %d.%d.%d.%d : %d\n\n",
          iphdr->saddr.byte1,
          iphdr->saddr.byte2,
          iphdr->saddr.byte3,
          iphdr->saddr.byte4,
          tcphdr->src_port,
          iphdr->daddr.byte1,
          iphdr->daddr.byte2,
          iphdr->daddr.byte3,
          iphdr->daddr.byte4,
          tcphdr->dst_port);}

现在,我可以嗅探数据包并打印各种内容。但我的目标是从被嗅探的数据包(如numOfpackets、numOfTCPpackets、numOfIncomingPAcket、numOfOutgoingPackets、数据包大小方差、时间间隔方差)中提取统计数据。但我希望这能在1000ms的时间内完成。

例如:每隔1000ms我想要一个输出文件..

numOfTCPPackets = ....

numof = ....

我的问题是:如何合并这些时间窗口?如何在不过多干扰嗅探速度的情况下提取所需的统计数据?

非常感谢!

EN

回答 1

Stack Overflow用户

发布于 2015-03-22 02:50:35

使用pcap_next()而不是pcap_loop()来获取数据包,并使用pcap_set_timeout()将超时设置为一个较小的值,例如10毫秒,以防止pcap_next()永远阻塞,以便将统计信息写入文件的代码有机会运行。您需要在循环中调用pcap_next(),并在pcap_next()调用之后编写类似以下代码:

代码语言:javascript
复制
if (cur_time64() - last_time64 >= stat_time64)
{
    last_time64 += stat_time64;
    print_statistics_to_file();
}

...where cur_time64()将当前时间作为64位整数返回,单位为微秒(如果使用类Unix操作系统,则可以使用gettimeofday()实现cur_time64() )。在您的示例中,stat_time64应该是1秒,即1000*1000。

然后,继续处理数据包。检查pcap_next()的返回值是否返回数据包:如果不是,则继续循环;如果是,则处理该数据包。

要在不过多影响嗅探速度的情况下进行检查,您唯一的选择就是尽可能高效地编写代码。只处理那些您绝对需要处理的报头字段,即可以避免检查IP和TCP报头的校验和。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29186088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档