strncmp() 和 if() 不同意...我错过了什么? (原始套接字)

发布于 2024-09-12 03:21:14 字数 1408 浏览 6 评论 0原文

我正在尝试构建一个在以太网级别工作的简单回显服务器/客户端(使用原始套接字)。 服务器端自行工作并显示 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 *) &ethernet_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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

靑春怀旧 2024-09-19 03:21:14

strncmp 和裸露的 if 都不应该用于比较 MAC 地址。

如果它们可能嵌入了零字节,第一个将无法正常工作,这会导致 strncmp 声明它们相等,但实际上它们并不相等。这是因为以下两个值的 strncmp

ff ff 00 ff ff ff
ff ff 00 aa aa aa

将为 true(它仅检查第一个零字节)。

第二个方法不起作用,因为您比较的是指针,而不是指针指向的内容。如果您有以下内存布局:

0x12345678 (mac) | 0x11111111 |
0x1234567c (eth) | 0x11111111 |

那么将 macethif (mac == eth) 进行比较将得到 false< /code> 因为它们是不同的指针,一个以 78 结尾,另一个以 7c 结尾。

您应该使用 memcmp 来代替,因为它会比较原始内存字节,而不会在早期的零字节处停止:

int result = memcmp (ethernet_header->h_dest, mac, ETH_ALEN);

Neither strncmp nor a naked if 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 a strncmp of the following two values:

ff ff 00 ff ff ff
ff ff 00 aa aa aa

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:

0x12345678 (mac) | 0x11111111 |
0x1234567c (eth) | 0x11111111 |

then comparing mac with eth with if (mac == eth) will give you false since they are distinct pointers, one ending in 78, the other in 7c.

You should use memcmp instead since it will compare the raw memory bytes without stopping at an early zero byte:

int result = memcmp (ethernet_header->h_dest, mac, ETH_ALEN);
深居我梦 2024-09-19 03:21:14

您无法使用 == 运算符测试字符串相等性。这就是 strcmp() 函数首先存在的原因。

You can't test for string equality using the == operator. That's why the strcmp() functions exist in the first place.

能怎样 2024-09-19 03:21:14

strncmp 将指向 char 的指针作为其前两个参数。

strncmp 返回零,因为这两个位置的字符串对于 ETH_ALEN 字符是相同的 - 这并不意味着 ethernet_header->h_dest 和 < code>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
  • p1p2 相等,因为它们都指向内存中的同一个 const 字符串。
  • 对于数组,将为每个数组变量(在堆栈中)分配一个 5 字节的连续块,并将字符串 asdf\0 复制到这些位置。
  • s1s2 是两个不同的指针,它们指向堆中恰好包含相同值的两个不同的 5 字节序列块。

strncmp takes pointers to char as its first two arguments.

strncmp returns zero because the strings at those two locations are same for ETH_ALEN characters - that doesn't mean that ethernet_header->h_dest and mac are equal. They are two different pointers.

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;
}

The output:

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 and p2 are equal because they both are pointing to the same const string in the memory.
  • In case of arrays, a continuous block of 5 bytes is allocated to each array variables (in the stack) and the string asdf\0 is copied into those locations.
  • s1 and s2 are two different pointers that point to two different blocks of 5 byte sequences in the heap that happens to contain same value.
離人涙 2024-09-19 03:21:14

这个代码是什么?

if(ethernet_header->h_dest == mac)

在 C 中不进行字符串比较,只是进行指针比较,在您的情况下总是错误的。

What is this code?

if(ethernet_header->h_dest == mac)

Does not do a string compare in C, just a pointer comparision which always be false in your case.

无力看清 2024-09-19 03:21:14

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().

蒗幽 2024-09-19 03:21:14

在 C 中,== 并不像您想象的那样对字符串起作用。您必须使用 strncmp() 来代替。

只需更改

 if(ethernet_header->h_dest == mac) {

if(result == 0) {

In C, == does not work on strings as you think. You must use strncmp() instead.

Just change

 if(ethernet_header->h_dest == mac) {

to

if(result == 0) {
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文