strncmp()和if()不同意......我错过了什么? (原始插座)

时间:2010-07-29 10:04:53

标签: c strcmp raw-sockets

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

在下面的代码中,有人可以向我解释为什么strncmp返回零(意味着字符串匹配)但是“if(ethernet_header-> h_dest == mac)”无法执行(不匹配)。 变量“mac”和“ethernet_header-> h_dest”都是相同的类型和长度。

更多背景资料: - 这是在linux 64bit(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);
 }

}

6 个答案:

答案 0 :(得分:9)

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

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

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

将为真(它只检查第一个零字节)。

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

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

然后将macethif (mac == eth)进行比较会得到false,因为它们是不同的指针,一个以78结尾,另一个以{{}结尾1}}。

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

memcmp

答案 1 :(得分:1)

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

答案 2 :(得分: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
  • p1p2相等,因为它们都指向内存中的相同const字符串。
  • 如果是数组,则为每个数组变量(在堆栈中)分配一个5字节的连续块,并将字符串asdf\0复制到这些位置。
  • s1s2是两个不同的指针,指向堆中恰好包含相同值的两个不同的5字节序列块。

答案 3 :(得分:0)

这段代码是什么?

if(ethernet_header->h_dest == mac)

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

在C语言中,==对字符串不起作用。您必须改为使用strncmp()

只需更改

 if(ethernet_header->h_dest == mac) {

if(result == 0) {