strncmp() 和 if() 不同意...我错过了什么? (原始套接字)
我正在尝试构建一个在以太网级别工作的简单回显服务器/客户端(使用原始套接字)。 服务器端自行工作并显示 eth0 上的所有传入数据包。 客户端工作并在 eth0 上发送以太网数据包(我用wireshark检查了这一点,可以看到数据包发出。) 我现在想做一个过滤器来只查看我感兴趣的数据包。 (这是基于目标/源地址。)
在下面的代码中,有人可以向我解释为什么 strncmp 返回零(意味着字符串匹配)但“if(ethernet_header->h_dest == mac)”失败执行(不匹配)。 变量“mac”和“ethernet_header->h_dest”的类型和长度相同。
更多背景: - 这是在 linux 64 位 (ubuntu) 上完成的 - 我在同一台机器上使用 eth0 进行发送/接收......我不认为这应该是一个问题?
我只是不明白为什么 strcmp 返回匹配项而 if 不返回。我缺少什么?
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);
}
}
I'm trying to build a simple echo server/client that works on ethernet level(using raw sockets).
The server side by itself works and shows all incoming packets on eth0.
The client works and sends ethernet packets on eth0 (I checked this with wireshark and can see the packets going out.)
I now want to make a filter to only look at the packets I'm interested. (This is based on the destination/source addresses.)
In the code below, could someone please explain to me why strncmp returns zero(meaning the strings match) but yet the "if(ethernet_header->h_dest == mac)" fails to execute (don't match).
Both the variables "mac" and "ethernet_header->h_dest" is the same type and length.
Some more background:
- This is done on linux 64bit (ubuntu)
- I'm using eth0 on the same machine for sending/receiving....I don't think this should be a problem?
I just don't understand why strcmp returns a match and if doesn't. What am I missing??
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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
strncmp
和裸露的if
都不应该用于比较 MAC 地址。如果它们可能嵌入了零字节,第一个将无法正常工作,这会导致 strncmp 声明它们相等,但实际上它们并不相等。这是因为以下两个值的
strncmp
将为 true(它仅检查第一个零字节)。
第二个方法不起作用,因为您比较的是指针,而不是指针指向的内容。如果您有以下内存布局:
那么将
mac
与eth
与if (mac == eth)
进行比较将得到false< /code> 因为它们是不同的指针,一个以
78
结尾,另一个以7c
结尾。您应该使用 memcmp 来代替,因为它会比较原始内存字节,而不会在早期的零字节处停止:
Neither
strncmp
nor a nakedif
should be used for comparing MAC addresses.The first won't work properly in cases where they may have an embedded zero byte which would cause
strncmp
to state they're equal when they're actually not. That's because astrncmp
of the following two values:would be true (it only checks up to the first zero byte).
The second won't work because you're comparing pointers rather than the contents that the pointers point to. If you have the following memory layout:
then comparing
mac
witheth
withif (mac == eth)
will give youfalse
since they are distinct pointers, one ending in78
, the other in7c
.You should use
memcmp
instead since it will compare the raw memory bytes without stopping at an early zero byte:您无法使用 == 运算符测试字符串相等性。这就是 strcmp() 函数首先存在的原因。
You can't test for string equality using the == operator. That's why the strcmp() functions exist in the first place.
strncmp
将指向 char 的指针作为其前两个参数。strncmp
返回零,因为这两个位置的字符串对于ETH_ALEN
字符是相同的 - 这并不意味着ethernet_header->h_dest
和 < code>mac 是相等的。它们是两个不同的指针。输出:
p1
和p2
相等,因为它们都指向内存中的同一个 const 字符串。asdf\0
复制到这些位置。s1
和s2
是两个不同的指针,它们指向堆中恰好包含相同值的两个不同的 5 字节序列块。strncmp
takes pointers to char as its first two arguments.strncmp
returns zero because the strings at those two locations are same forETH_ALEN
characters - that doesn't mean thatethernet_header->h_dest
andmac
are equal. They are two different pointers.The output:
p1
andp2
are equal because they both are pointing to the same const string in the memory.asdf\0
is copied into those locations.s1
ands2
are two different pointers that point to two different blocks of 5 byte sequences in the heap that happens to contain same value.这个代码是什么?
在 C 中不进行字符串比较,只是进行指针比较,在您的情况下总是错误的。
What is this code?
Does not do a string compare in C, just a pointer comparision which always be false in your case.
if(ethernet_header->h_dest == mac)
只是比较原始指针值。这意味着它会检查两个字符串是否从同一内存地址开始。通常,这不是您想要的。要比较两个 C 字符串的内容,请始终使用
strncmp()
。The
if(ethernet_header->h_dest == mac)
just compares the raw pointer values. That means it checks, if both strings start at the same memory address. Usually, that's not what you want.To compare the content of two c-strings, always use
strncmp()
.在 C 中,
==
并不像您想象的那样对字符串起作用。您必须使用strncmp()
来代替。只需更改
为
In C,
==
does not work on strings as you think. You must usestrncmp()
instead.Just change
to