c - 比较接口的ipv4地址和数据包的源地址(libpcap)
问题描述
我正在使用对https://www.tcpdump.org/sniffex.c中 C 代码的修改来使用 libpcap 打印有关通过接口的 TCP 数据包的信息。
这是我试图用来检查接收到的数据包的源字段是否等于当前接口的 IP 地址的回调代码示例(因此仅分析传出数据包)。这是一个相当广泛的程序,所以我决定只包括有问题的部分:
// retrieve IP address of interface
char * dev_name = "eth0";
struct ifreq ifr;
int fd;
char *dev_ip;
fd = socket(AF_INET, SOCK_DGRAM, 0);
// type of address to retrieve (IPv4)
ifr.ifr_addr.sa_family = AF_INET;
// copy the interface name in the ifreq structure
strncpy(ifr.ifr_name , dev_name , IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
dev_ip = inet_ntoa(( (struct sockaddr_in *)&ifr.ifr_addr )->sin_addr);
printf("IPv4 address: %s\n", dev_ip);
printf("inet_ntoa: %s\n",inet_ntoa(ip->ip_src));
if (strcmp(dev_ip,inet_ntoa(ip->ip_src)) == 0)
printf("EQUAL!\n");
但是,正如您在以下屏幕截图中看到的那样,即使源 IP ( inet_ntoa
) 和接口的 IP 地址 ( IPv4 address
) 不同,根据程序,它们的值总是相等的。
问题可能是什么?
解决方案
inet_ntoa
返回一个指向字符串的指针,该字符串在 . 内部的静态内存中构造inet_ntoa
。每次调用它时都会重复使用相同的静态内存。当你这样做时:
dev_ip = inet_ntoa(...);
dev_ip
设置为指向该内部静态缓冲区。此时静态缓冲区包含一个表示接口地址的字符串,因此您的:
printf("IPv4 address: %s\n", dev_ip);
显示预期结果。但是你这样做:
printf("inet_ntoa: %s\n",inet_ntoa(ip->ip_src));
并用表示数据包地址的字符串覆盖 inet_ntoa
的内部缓冲区。
但请记住,dev_ip
它仍然指向该内部缓冲区。所以当你这样做时:
if (strcmp(dev_ip,inet_ntoa(ip->ip_src)) == 0)
(顺便说一句,它不必要地用已经存在的数据包地址再次覆盖内部缓冲区)传递给的两个参数strcmp
都是指向inet_nota
内部缓冲区的指针,因此strcmp
总是会发现目标字符串匹配 - 因为两个参数指向同一个字符串。
要修复,请在调用它后立即生成字符串的本地副本inet_ntoa
,通过复制到本地缓冲区或执行以下操作:
dev_ip = strdup(inet_ntoa(...));
(请记住,free(dev_ip)
当您不再需要该字符串时),或者更好的是,如果您的平台具有该功能 ,则使用inet_ntoa
调用的线程安全变体。不使用(和重复使用)内部缓冲区。它要求其调用者提供将放置字符串的缓冲区。inet_ntoa_r
inet_ntoa_r
推荐阅读
- python - 网络抓取 BS4 表位于但为空 findall
- c# - 没有使用 csvHelper 映射类型的属性
- dji-sdk - 如何从 DJI H.264 视频中获取帧?
- node.js - 使用异步迭代器时避免退出 for-await 循环
- html - Anchor tag is messing with img position
- amazon-web-services - Can't create AWS ALB kubernetes ingress controller in Terraform
- javascript - Taking user input from a form, showing it on a website in an array, and replacing variety of the strings with different words
- python - Reverse url not found
- python - Odd placeholder or pre-statement on string declaration
- elasticsearch - 如何在弹性搜索中查询 IP 范围?