c - 从以太网 header 打印 MAC 地址

标签 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 进行了检查),那么获取以太网 header 属性是否正确?

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

当我使用 nc 发送“aaa”字符串时,此图像显示了结果,以太网 header 在 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 地址。来自 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;
    }

关于c - 从以太网 header 打印 MAC 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37808520/

相关文章:

django - 如何限制连接到一个端口并将其他请求重定向到另一个端口?

ubuntu - Fail2ban 禁止互联网提供商 IP 地址?

c - 打破 while 循环并重新启动代码

c - 如何用C语言从文件中提取数据

android - 如何将已编译的 android 内核文件 'Image.gz-dtb' 转换为可刷新的 .zip 或 .img 文件?

performance - 从源代码/从头开始编译 linux perf 工具及其依赖的内核模块

firewall - 在 Centos7 中向 firewalld 添加规则以允许来自服务器的所有流量

c - SPIN_LOCK_UNLOCKED 的 Linux 3.16 等价物是什么?

C - 有什么方法可以使用位检查来检查数字是否等于 1?

linux - 使用 'make xconfig' 从源代码编译内核的脚本