ZBLOG

int main(int argc, const char* argv[]) { pcap_if_t* alldevs; pcap_if_t* d; int inum; int i = 0; pcap_t* adhandle; int res; char errbuf[PCAP_ERRBUF_SIZE]; struct tm* ltime; char timestr[16]; struct pcap_pkthd...

好的,以下是你提供的代码加上详细的注释。该代码使用 pcap 库来捕获网络数据包,过滤 ICMP 数据包,并打印相关信息。

#include <stdio.h>
#include <stdlib.h>
#include <pcap.h> // 需要包含pcap库
#include <arpa/inet.h> // 用于处理IP地址
#include <time.h>

int main(int argc, const char* argv[])
{
    pcap_if_t* alldevs; // 用于存储所有可用的网络接口
    pcap_if_t* d; // 当前遍历到的网络接口
    int inum; // 用户选择的接口编号
    int i = 0; // 遍历计数器
    pcap_t* adhandle; // 捕获句柄
    int res; // 返回值,用于检测函数执行结果
    char errbuf[PCAP_ERRBUF_SIZE]; // 存储错误信息的缓冲区
    struct tm* ltime; // 时间结构体,用于格式化时间戳
    char timestr[16]; // 存储格式化后的时间字符串
    struct pcap_pkthdr* header; // 包头信息指针
    const u_char* pkt_data; // 指向数据包内容的指针
    time_t local_tv_sec; // 存储本地时间秒数部分 
    u_int netmask; // 子网掩码

	// 定义数据包过滤条件,这里只捕获ICMP协议的数据包(如ping)
	char packet_filter[] = "icmp"; 
	struct bpf_program fcode; // 用于存放编译后的过滤程序

	/* 获取本机设备列表 */
	if (pcap_findalldevs_ex((char*)PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
	{
	    fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
	    exit(1); // 如果获取失败,输出错误信息并退出程序。
	}

	/* 打印设备列表 */
	for (d = alldevs; d; d = d->next)
	{
	    printf("%d. %s", ++i, d->name);  // 输出设备名称和序号。
	    if (d->description)
	        printf(" (%s)\n", d->description);  // 如果有描述,输出描述。
	    else
	        printf(" (No description available)\n");

        /* 遍历每个接口的地址 */
        if (d->addresses != NULL) {
            pcap_addr_t *addr = d->addresses;
            for (; addr != NULL; addr = addr->next) {
                struct sockaddr_in *ip = (struct sockaddr_in *)addr->addr;
                struct sockaddr_in *netmask = (struct sockaddr_in *)addr->netmask;
                if (ip->sin_family == AF_INET) {  // 确保是IPv4地址类型。
                    printf("  IP Address: %s\n", inet_ntoa(ip->sin_addr));  // 打印IPv4地址。
                    printf("  Netmask: %s\n", inet_ntoa(netmask->sin_addr));  // 打印子网掩码。
                }
			}
		}
	}

	if (i == 0)
	{
	    printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
	    return -1;
	}

	printf("Enter the interface number (1-%d):", i);
	scanf("%d", &inum);  // 提示用户输入要监听的接口编号。

	if (inum < 1 || inum > i)
	{
	    printf("\nInterface number out of range.\n");
	    pcap_freealldevs(alldevs);  //释放设备列表内存空间。
	    return -1;
	}

	/* 跳转到用户选择的适配器 */
	for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);

	/* 打开设备进行数据包捕获 */
	if ((adhandle = pcap_open(d->name,          // 要打开的设备名
	    65536,            // 要捕捉的数据包大小(最大为65535)
                          /* 确保能捕获到不同数据链路层上的每个数据包的全部内容 */
        PCAP_OPENFLAG_PROMISCUOUS,   /* 混杂模式,即接收所有经过该设备的数据包 */
        1000,             /* 超时时间,单位毫秒 */
        NULL,             /* 不进行远程机器验证 */
        errbuf            /* 错误缓冲区 */)) == NULL)
	{
	    fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
	    pcap_freealldevs(alldevs);   /*释放设备列表内存空间。*/
	    return -1;
	}
	
	printf("\nlistening on %s %s...\n",d->name, d->description);

   /* 设置过滤器以只抓取特定类型的数据包 */
	if (d->addresses != NULL)
        netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
	else 
        netmask = 0xffffff;

	if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) >= 0) 
     {
         if(pcap_setfilter(adhandle,&fcode)<0){  
           fprintf(stderr,"\nError setting the filter.\n");
           pcap_freealldevs(alldevs);
           return -1;
         }
      } else {
          fprintf(stderr,"\nError setting the filter.\n");
          pcap_freealldevs(alldevs);
          return -1;
      }

	pcap_freealldevs(alldevs);   /*释放设备列表内存空间。*/

	printf("11111111111111111\n"); 

   /* 循环获取数据包并处理 */ 
	while ((res = pcap_next_ex(adhandle, &header,&pkt_data)) >= 0) {

       if(res==0)
           continue;      /* 超时,不做处理 */

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

       printf("%s ,%.6d len:%d\n" ,timestr ,header -> ts.tv_usec ,header -> len );  

       int len= header -> caplen +1 ;
       for(i=1;i<len;i++) {
              printf("%.2x ", pkt_data[i-1]);     /* 按字节打印出抓取到的数据,以16进制形式显示*/
              if((i%16)==0 )
                  printf("\n");  
          }
          printf("\n-----------------------------------------------------------------\n");
	  packetHandler(NULL ,header,pkt_data );  
   }

   if(res==-1){
      printf("Error reading the packets: % s \ n" ,pcap_geterr(adhandle));
      return -1;
   }

	return 0;

}

注释说明:

  • 此代码使用 libpcap 库来查找、列出并选择网络接口,然后在选定接口上以混杂模式捕获数据包。在这个例子中,它仅关注 ICMP 协议(例如 ping)的流量。
  • 使用了 pcap_findalldevs_ex 函数获取系统中的所有网络接口,并让用户选择一个进行监控。
  • 一旦成功打开选定的网络接口,就设置一个 BPF (Berkeley Packet Filter)以限制捕获的数据类型,只关注 ICMP 数据流,并开始循环读取数据包。

请确保在运行此代码之前已经安装好相关库,如 libpcap 和相应的开发环境。如果有进一步的问题,请随时提问!


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=6274

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?