比较接口(interface)的 ipv4 地址和数据包的源地址(libpcap)

标签 c ip libpcap

我正在使用 https://www.tcpdump.org/sniffex.c 中 C 代码的修改版使用 libpcap 打印有关通过接口(interface)的 TCP 数据包的信息。

这是我尝试用来检查接收到的数据包的源字段是否等于当前接口(interface)的 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) 和接口(interface)的 IP 地址 (IPv4 地址) 不同,根据程序,它们的值始终相等。

Output of program

问题可能是什么?

最佳答案

inet_ntoa返回一个指向已在 inet_ntoa 内部的静态内存中构造的字符串的指针。 。每次调用时它都会重新使用相同的静态内存。当你这样做时:

    dev_ip = inet_ntoa(...);

dev_ip设置为指向该内部静态缓冲区。此时静态缓冲区包含一个表示接口(interface)地址的字符串,因此您的:

    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不使用(和重复使用)内部缓冲区。它要求调用者提供放置字符串的缓冲区。

关于比较接口(interface)的 ipv4 地址和数据包的源地址(libpcap),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58306371/

相关文章:

PHP:有什么更好的方法可以在不使用 IP 地址作为唯一标识符的情况下计算每台计算机的浏览量?

python - 使用 Python 查找网络(外部)IP 地址

batch-file - 检测设备是否在线

c - 如何在 C 中嗅探数据包时查找 TCP 重传

c - 将指针作为较短的数组传递

c - 如何使用简单的语句描述有关C语言中函数 'sprintf'的重复格式说明符?

c++ - Eclipse:无需为文件构建

c - 时间差(以微秒为单位)

c++ - 停止使用 libpcap 捕获数据并将其保存在文件中

c - 在 C 中加载共享内存