【问题标题】:Print MAC address from Ethernet header从以太网标头打印 MAC 地址
【发布时间】:2016-10-14 23:31:00
【问题描述】:

我想检查由 iptables (1.4) 处理的数据包的以太网标头,所以我需要编写一个模块来捕获数据包并应用我的功能。我正在以太网头中寻找mac目标值(仅用于测试目的),所以代码应该是这样的:

static bool match(const struct sk_buff *skb, struct xt_action_param *par)
{
    struct ethhdr *hdr;        
    hdr = eth_hdr(skb);
    printk(KERN_INFO "hdr->h_dest 0x%x\n", hdr->h_dest);
    printk(KERN_INFO "MACPROTO=%04x\n", hdr->h_proto);

问题是我无法获得正确的值,我有一些甚至不在真实帧中的东西(我用 Wireshark 进行了检查),那么获取以太网标头属性是否正确?

更新: 我使用了帖子中提出的解决方案,但仍然有错误的输出,就像结构指向错误的地方一样

当我使用 nc 发送“aaa”字符串时,此图像显示结果,以太网标头在 to 帧中应该是相同的,但在结果中,它不是。

【问题讨论】:

    标签: c linux-kernel iptables


    【解决方案1】:

    struct ethhdr 是这样定义的:

    /*
     *  This is an Ethernet frame header.
     */
    
    struct ethhdr {
        unsigned char   h_dest[ETH_ALEN];   /* destination eth addr */
        unsigned char   h_source[ETH_ALEN]; /* source ether addr    */
        __be16      h_proto;        /* packet type ID field */
    } __attribute__((packed));
    

    但您的代码正在尝试使用 %x 打印该字节数组:

    printk(KERN_INFO "hdr->h_dest 0x%x\n", hdr->h_dest);
    

    这没有任何意义,并且可能会导致生成编译器警告。这是内核代码 - 你正在使用-Werror-Wall对吗?


    好消息:printk 支持直接打印 MAC 地址。来自documentation/printk-formats.txt

    MAC/FDDI addresses:
    
        %pM 00:01:02:03:04:05
        %pMR    05:04:03:02:01:00
        %pMF    00-01-02-03-04-05
        %pm 000102030405
        %pmR    050403020100
    
        For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm' 
        specifiers result in a printed address with ('M') or without ('m') byte
        separators. The default byte separator is the colon (':').
    
        Where FDDI addresses are concerned the 'F' specifier can be used after
        the 'M' specifier to use dash ('-') separators instead of the default
        separator.
    
        For Bluetooth addresses the 'R' specifier shall be used after the 'M' 
        specifier to use reversed byte order suitable for visual interpretation
        of Bluetooth addresses which are in the little endian order.
    
        Passed by reference.
    

    所以你可以使用这个:

    printk(KERN_INFO "hdr->h_dest 0x%pM\n", hdr->h_dest);
    

    这些格式说明符在使用vsnprintf 的任何地方都提供。这里是an example

        switch (dev->type) {
        case ARPHRD_ETHER:
                nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
                               eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
                               ntohs(eth_hdr(skb)->h_proto));
                return;
        default:
                break;
        }
    

    【讨论】:

    • 很高兴知道。我从未听说过 %pM 和朋友们。 +1
    • 我使用 %x 以十六进制打印输出,这样我就可以使用wireshark 轻松验证结果,无论如何,我尝试了你的方法,我使用了 %pM,但仍然有错误的输出,proto等于 0000(wireshark 显示 0800)
    • @yassine %x 说明符打印unsigned int,而h_destunsigned char 的数组。如果您不明白为什么这是错误的,那么您不应该编写内核驱动程序。此外,您的代码从未提及任何有关打印协议字段的内容。
    • @JonathonReinhart,我用同一行打印原型; printk(KERN_INFO "MACPROTO=%04x\n", hdr->h_proto);
    • 最后我使用了另一个数据包生成器,数据包似乎打印没有错误,谢谢
    猜你喜欢
    • 2016-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多