0

我正在尝试构建一个在以太网级别(使用原始套接字)工作的简单回显服务器/客户端。服务器端自己工作并显示 eth0 上的所有传入数据包。客户端工作并在 eth0 上发送以太网数据包(我用 wireshark 检查了这个,可以看到数据包出去了。)我现在想做一个过滤器,只查看我感兴趣的数据包。(这基于目标/源地址。)

在下面的代码中,有人可以向我解释为什么 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 *) &ethernet_header->h_proto, 2);
   printf("\n\n");
   printf("Length: %d\n",len);
  }

 } else {
  printf("Packet size too small (length: %d)!\n",len);
 }

}
4

6 回答 6

9

不应该使用裸机strncmp或裸机来比较 MAC 地址。if

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

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

会是真的(它只检查第一个零字节)。

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

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

然后macethwith比较if (mac == eth)会给你,false因为它们是不同的指针,一个以 结尾78,另一个以7c.

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

int result = memcmp (ethernet_header->h_dest, mac, ETH_ALEN);
于 2010-07-29T10:09:54.363 回答
1

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

于 2010-07-29T10:08:35.207 回答
1

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

strncmp返回零,因为这两个位置的字符串对于ETH_ALEN字符来说是相同的——这并不意味着它们是相等的ethernet_header->h_destmac它们是两个不同的指针

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相等,因为它们都指向内存中相同的 const 字符串。
  • 对于数组,为每个数组变量(在堆栈中)分配一个 5 字节的连续块,并将字符串asdf\0复制到这些位置。
  • s1并且s2是两个不同的指针,它们指向堆中恰好包含相同值的两个不同的 5 字节序列块。
于 2010-07-29T10:09:58.620 回答
0

这段代码是什么?

if(ethernet_header->h_dest == mac)

不在 C 中进行字符串比较,只是在您的情况下始终为假的指针比较。

于 2010-07-29T10:07:35.433 回答
0

只是比较原始if(ethernet_header->h_dest == mac)指针值。这意味着它会检查两个字符串是否从相同的内存地址开始。通常,这不是你想要的。

要比较两个 c 字符串的内容,请始终使用strncmp().

于 2010-07-29T10:08:08.140 回答
0

在 C 中,==不能像您想象的那样在字符串上工作。您必须strncmp()改用。

只是改变

 if(ethernet_header->h_dest == mac) {

if(result == 0) {
于 2010-07-29T10:12:02.413 回答