strncmp()和if()不一致…我缺少什么??(原始插座)
我正在尝试构建一个简单的echo服务器/客户端,它使用原始套接字在以太网级别上工作。 服务器端自行工作并在eth0上显示所有传入的数据包。 客户端在eth0上工作并发送以太网数据包。我与wireshark进行了检查,可以看到数据包发出。 我现在想做一个过滤器,只查看我感兴趣的数据包。这基于目标/源地址 在下面的代码中,是否有人可以向我解释为什么strncmp返回零意味着字符串匹配,但ifethernet\u header->h\u dest==mac无法执行不匹配。 变量mac和ethernet_header->h_dest的类型和长度相同 更多背景: -这是在linux 64位ubuntu上完成的 -我在同一台机器上使用eth0进行发送/接收…我不认为这应该是个问题 我只是不明白为什么strcmp返回匹配,如果没有。我错过了什么strncmp()和if()不一致…我缺少什么??(原始插座),c,strcmp,raw-sockets,C,Strcmp,Raw Sockets,我正在尝试构建一个简单的echo服务器/客户端,它使用原始套接字在以太网级别上工作。 服务器端自行工作并在eth0上显示所有传入的数据包。 客户端在eth0上工作并发送以太网数据包。我与wireshark进行了检查,可以看到数据包发出。 我现在想做一个过滤器,只查看我感兴趣的数据包。这基于目标/源地址 在下面的代码中,是否有人可以向我解释为什么strncmp返回零意味着字符串匹配,但ifethernet\u header->h\u dest==mac无法执行不匹配。 变量mac和ethernet
void ParseEthernetHeader(unsigned char *packet, int len) {
struct ethhdr *ethernet_header;
unsigned char mac[ETH_ALEN] = {0x01, 0x55, 0x56, 0x88, 0x32, 0x7c};
if (len > sizeof(struct ethhdr)) {
ethernet_header = (struct ethhdr *) packet;
int result = strncmp(ethernet_header->h_dest, mac, ETH_ALEN);
printf("Result: %d\n", result);
if(ethernet_header->h_dest == mac) {
/* First set of 6 bytes are Destination MAC */
PrintInHex("Destination MAC: ", ethernet_header->h_dest, 6);
printf("\n");
/* Second set of 6 bytes are Source MAC */
PrintInHex("Source MAC: ", ethernet_header->h_source, 6);
printf("\n");
/* Last 2 bytes in the Ethernet header are the protocol it carries */
PrintInHex("Protocol: ", (void *) ðernet_header->h_proto, 2);
printf("\n\n");
printf("Length: %d\n",len);
}
} else {
printf("Packet size too small (length: %d)!\n",len);
}
}
这是什么代码
if(ethernet_header->h_dest == mac)
在C中不进行字符串比较,只进行指针比较,在您的情况下,指针比较始终为false。ifethernet\u header->h\u dest==mac只比较原始指针值。这意味着它会检查两个字符串是否从相同的内存地址开始。通常,这不是你想要的
要比较两个c字符串的内容,请始终使用strncmp。不能使用==运算符测试字符串是否相等。这就是strcmp函数首先存在的原因。不应使用strncmp或裸if来比较MAC地址 第一种方法在它们可能有一个嵌入的零字节的情况下无法正常工作,这会导致strncmp声明它们相等,而实际上它们不相等。这是因为strncmp包含以下两个值:
ff ff 00 ff ff ff
ff ff 00 aa aa aa
它只检查第一个零字节
第二种方法不起作用,因为您正在比较指针,而不是指针指向的内容。如果您具有以下内存布局:
0x12345678 (mac) | 0x11111111 |
0x1234567c (eth) | 0x11111111 |
然后将mac和eth与if mac==eth进行比较,会得到false,因为它们是不同的指针,一个以78结尾,另一个以7c结尾
您应该改用memcmp,因为它将比较原始内存字节,而不会在早期的零字节处停止:
int result = memcmp (ethernet_header->h_dest, mac, ETH_ALEN);
strncmp将指向char的指针作为其前两个参数
strncmp返回零,因为这两个位置的字符串对于ETH_ALEN字符是相同的-这并不意味着ethernet_header->h_dest和mac是相等的。它们是两个不同的指针
输出:
a1 and a2: strcmp gives 0 and they are different
p1 and p2: strcmp gives 0 and they are equal
s1 and s2: strcmp gives 0 and they are different
p1和p2相等,因为它们都指向内存中相同的常量字符串。
对于数组,将为堆栈中的每个数组变量分配一个5字节的连续块,并将字符串asdf\0复制到这些位置。
s1和s2是两个不同的指针,指向堆中恰好包含相同值的5字节序列的两个不同块。
在C中,==不能像您所想的那样处理字符串。您必须改用strncmp
换衣服
if(ethernet_header->h_dest == mac) {
到
啊,真的!符合事实的符合事实的简单的错误!谢谢大家!请注意,这种使用strcmp(memcmp得到保证)的bug在过去一直是一个安全问题,例如在比较散列值时。
if(ethernet_header->h_dest == mac) {
if(result == 0) {