从以太网标头打印MAC地址

时间:2016-06-14 09:46:28

标签: c linux-kernel iptables

我想检查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检查过),所以它是获得以太网头部属性的正确功能吗?

更新 我使用了帖子中提供的解决方案,但仍然输出错误,如果结构指向错误的位置就好了 enter image description here

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

1 个答案:

答案 0 :(得分:6)

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