strncmp()和if()不同意...我在想什么? (原始套接字)
我想构建一个简单的echo服务器/客户端工作在以太网级别(使用原始套接字)。 服务器端本身工作并显示eth0上的所有传入数据包。 客户端在eth0上工作并发送以太网数据包(我用wireshark检查过这个数据包,可以看到数据包发送出去)。 我现在想做一个过滤器,只查看我感兴趣的数据包。 (这是基于目的地/源地址。)strncmp()和if()不同意...我在想什么? (原始套接字)
在下面的代码中,有人请向我解释为什么strncmp返回零(意味着字符串匹配),但“if(ethernet_header-> h_dest == mac )“执行失败(不匹配)。 变量“mac”和“ethernet_header-> h_dest”是相同的类型和长度。
一些更多的背景: - 这是Linux 64位完成(Ubuntu的) - 我使用的是同一台机器上发送/接收的eth0 ....我不认为这应该是一个问题吗?
我只是不明白为什么strcmp返回匹配,如果没有。我在想什么?
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);
}
}
strncmp
和if
都不应该用于比较MAC地址。
如果第一个嵌入的零字节可能会导致strncmp
在实际不相等时表示它们相等,则它们将无法正常工作。这是因为以下两个值的strncmp
:
ff ff 00 ff ff ff
ff ff 00 aa aa aa
将是真实的(只检查到第一个零字节)。因为你比较指针而非内容的指针指向
第二个将无法工作。如果你有以下的内存布局:
0x12345678 (mac) | 0x11111111 |
0x1234567c (eth) | 0x11111111 |
然后用eth
与if (mac == eth)
比较mac
会给你false
,因为它们是不同的指针,一个在78
结束,另一个在7c
。
您应该使用memcmp
,而不是因为它比较原始内存字节没有在早期零字节停止:
int result = memcmp (ethernet_header->h_dest, mac, ETH_ALEN);
请注意,这种错误(使用'strcmp()',其中'memcmp()'是有保证的)过去一直是一个安全问题,例如。当比较散列值时。 – caf 2010-07-29 13:40:36
什么是该代码?
if(ethernet_header->h_dest == mac)
不在C中做字符串比较,只是一个指针比较,它总是在你的情况下是错误的。
if(ethernet_header->h_dest == mac)
只比较原始指针值。这意味着它检查,如果两个字符串在相同的内存地址开始。通常情况下,这不是你想要的。
要比较两个C字符串的内容,请始终使用strncmp()
。
您不能测试使用==操作符串平等。这就是为什么strcmp()函数首先存在的原因。
strncmp
需要指向char作为其首两个参数。
strncmp
回报为零,因为在这些两个位置的字符串是同为ETH_ALEN
字符 - 这并不意味着ethernet_header->h_dest
和mac
是相等的。他们是两个不同的指针。
int main()
{
char a1[] = "asdf";
char a2[] = "asdf";
char *p1 = "asdf";
char *p2 = "asdf";
char *s1 = malloc(5);
char *s2 = malloc(5);
strcpy(s1, "asdf");
strcpy(s2, "asdf");
printf("a1 and a2: strcmp gives %d and they are %s\n", strcmp(a1, a2), a1 == a2 ? "equal" : "different");
printf("p1 and p2: strcmp gives %d and they are %s\n", strcmp(p1, p2), p1 == p2 ? "equal" : "different");
printf("s1 and s2: strcmp gives %d and they are %s\n", strcmp(s1, s2), s1 == s2 ? "equal" : "different");
return 0;
}
输出:
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) {
到
if(result == 0) {
啊,不错!真正!真正!简单的错误!谢谢大家! – NomadAlien 2010-07-29 10:13:22