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

问题描述 投票:0回答:1

我正在使用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)不同,根据程序,它们的值也始终相等。

Output of program

可能是什么问题?

c ip libpcap
1个回答
1
投票

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)

((该BTW不必要地再次使用数据包的地址重写了内部缓冲区,该地址已经存在)传递给strcmp的两个参数都是inet_nota内部缓冲区的指针,因此strcmp将始终发现目标字符串匹配-因为两个参数都指向相同的字符串。

要解决,可以在调用后立即将inet_ntoa生成的字符串进行本地复制,方法是将其复制到本地缓冲区中,或者执行类似的操作:

    dev_ip = strdup(inet_ntoa(...));

((并且,当您不再需要该字符串时,请记住free(dev_ip)),或者,如果您的平台具有该功能,则最好使用称为inet_ntoa的线程安全变体inet_ntoa_rinet_ntoa_r不使用(或重复使用)内部缓冲区。它要求其调用者提供要放置字符串的缓冲区。

© www.soinside.com 2019 - 2024. All rights reserved.