从以太网报头打印MAC地址

从以太网报头打印MAC地址,c,linux-kernel,iptables,C,Linux Kernel,Iptables,我想检查由iptables(1.4)穿孔的数据包的以太网报头,因此我需要编写一个模块来捕获数据包并应用我的功能。我在Ethernet报头中查找mac destination值(仅用于测试目的),因此代码应如下所示: static bool match(const struct sk_buff *skb, struct xt_action_param *par) { struct ethhdr *hdr; hdr = eth_hdr(skb); printk

我想检查由iptables(1.4)穿孔的数据包的以太网报头,因此我需要编写一个模块来捕获数据包并应用我的功能。我在Ethernet报头中查找mac destination值(仅用于测试目的),因此代码应如下所示:

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帧中应相同,但与结果中显示的相同。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地址。发件人:

MAC/FDDI地址:
%下午00:01:02:03:04:05
%pMR 05:04:03:02:01:00
%pMF 00-01-02-03-04-05
%下午000102030405
%pmR 05043020100
用于以十六进制表示法打印6字节MAC/FDDI地址。“M”和“M”
说明符产生一个带有('M')或不带('M')字节的打印地址
分离器。默认的字节分隔符是冒号(“:”)。
如果涉及到FDDI地址,“F”说明符可以在
“M”说明符使用破折号(“-”)分隔符而不是默认分隔符
分离器。
对于蓝牙地址,应在“M”之后使用“R”说明符
说明符使用适合视觉解释的反向字节顺序
按小端顺序排列的蓝牙地址。
通过引用传递。
所以你可以用这个:

printk(KERN_INFO "hdr->h_dest 0x%pM\n", hdr->h_dest);
这些格式说明符在使用
vsnprintf
的任何位置提供。这是:


很高兴知道。我从来没有听说过%pM和朋友们+1我使用%x以六边形打印输出,这样我可以用wireshark轻松地验证结果,无论如何,我尝试了你的方法,我使用了%pM,但仍然有错误的输出,proto等于0000(wireshark show 0800)@yassine
%x
说明符打印
无符号int
,而
h_dest
无符号字符的数组。如果您不理解为什么这是错误的,那么您不应该编写内核驱动程序。另外,您的代码从来没有提到任何关于打印协议字段的内容。@JonathonReinhart,我使用同一行打印原型;printk(KERN_INFO“MACPROTO=%04x\n”,hdr->h_proto);最后,我使用了另一个数据包生成器,数据包似乎打印时没有错误,谢谢
    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;
    }