一尘不染

如何在内核模块中捕获网络帧

linux

我想捕获某些NIC收到的帧。从中提取一些信息(当前我需要捕获源MAC和源IP地址);将这些信息保存在一些公共数据结构中;并让框架向上移动到TCP /
IP堆栈。

我以前使用过Netfilter,但显然它不提供Link层挂钩。
有什么办法可以做到吗?

我将其编写为内核模块;运行Linux内核2.6.32


阅读 191

收藏
2020-06-07

共1个答案

一尘不染

实际上,Netfilter应该可以正常工作,因为它接收了整个数据包(内部存储为sk_buff,其中包含链接层信息)。以下是一些示例代码,可以帮助您入门。此代码拦截给定设备的所有传入数据包,并打印src
MAC和src IP。

static struct nf_hook_ops nfin;

static unsigned int hook_func_in(unsigned int hooknum,
            struct sk_buff *skb,
                            const struct net_device *in,
                            const struct net_device *out,
                            int (*okfn)(struct sk_buff *))
{
    struct ethhdr *eth;
    struct iphdr *ip_header;
    /* check *in is the correct device */
    if (in is not the correct device)
          return NF_ACCEPT;

    eth = (struct ethhdr*)skb_mac_header(skb);
    ip_header = (struct iphdr *)skb_network_header(skb);
    printk("src mac %pM, dst mac %pM\n", eth->h_source, eth->h_dest);
    printk("src IP addr:=%d.%d.%d.%d:%d\n", NIPQUAD(ip_headr->saddr));
    return NF_ACCEPT;
}

static int __init init_main(void)
{
    nfin.hook     = hook_func_in;
    nfin.hooknum  = NF_IP_LOCAL_IN;
    nfin.pf       = PF_INET;
    nfin.priority = NF_IP_PRI_FIRST;
    nf_register_hook(&nfin);

    return 0;
}



static void __exit cleanup_main(void)
{
    nf_unregister_hook(&nfin);
}
module_init(init_main);
module_exit(cleanup_main);
2020-06-07