首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用net_dev_add() API过滤和拦截Linux数据包?

如何使用net_dev_add() API过滤和拦截Linux数据包?
EN

Stack Overflow用户
提问于 2013-10-13 05:36:31
回答 2查看 7.7K关注 0票数 8

我正在为linux编写以太网网络驱动程序。我想接收数据包,编辑和重新发送它们。我知道如何在packet_interceptor函数中编辑数据包,但是如何在此函数中删除传入的数据包??

代码语言:javascript
运行
复制
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/sock.h>

struct packet_type my_proto;

int packet_interceptor(struct sk_buff *skb,
    struct net_device *dev,
    struct packet_type *pt,
    struct net_device *orig_dev) {

    // I dont want certain packets go to upper in net_devices for further processing.
    // How can I drop sk_buff here?!

  return 0;
}

static int hello_init( void ) {
    printk(KERN_INFO "Hello, world!\n");

    my_proto.type = htons(ETH_P_ALL);
    my_proto.dev = NULL;
    my_proto.func = packet_interceptor;

    dev_add_pack(&my_proto);
    return 0;
}    

static void hello_exit(void) {
  dev_remove_pack(&my_proto);
  printk(KERN_INFO "Bye, world\n");
}

module_init(hello_init);
module_exit(hello_exit);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-29 21:51:18

您正在使您的模块处理所有以太网数据包。Linux将向所有匹配的协议处理程序发送数据包。因为IP已经注册在您的内核中,您的模块和ip_rcv都将接收所有带有IP报头的SKB。

如果不更改内核代码,则无法更改此行为。一种可能性是创建一个netfilter模块。这样,您可以在ip_rcv函数之后截取数据包,如果愿意,可以删除它(在Netfilters PREROUTING钩子中)。

这里有一个小的Netfilter模块,我从我已经编写的一些代码中提取出来。这个模块尚未完成,但主要内容已经到位。

代码语言:javascript
运行
复制
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>

// Handler function
static unsigned int my_handler (
    unsigned int hook,
    struct sk_buff *skb,
    const struct net_device *in,
    const struct net_device *out,
    int (*okfn)(struct sk_buff *))
{
    return NF_ACCEPT;
// or
    return NF_DROP;
}

// Handler registering struct
static struct nf_hook_ops my_hook __read_mostly = {
    .hook = my_handler,
    .pf = NFPROTO_IPV4,
    .hooknum = (1 << NF_INET_PRE_ROUTING),
    .priority = NF_IP_PRI_FIRST // My hook will be run before any other netfilter hook
};

int my_init() {
    int err = nf_register_hook (&my_hook);
    if (err) {
            printk (KERN_ERR "Could not register hook\n");
    }
    return err;
}
票数 6
EN

Stack Overflow用户

发布于 2013-10-15 17:56:24

我研究了内核网络代码(自从我在里面做了任何事情一年后),我认为您应该能够做到这一点,而不会泄露任何内容:

代码语言:javascript
运行
复制
kfree_skb(skb);
return NET_RX_DROP;

编辑

这是在其他协议处理程序中完成的,比如ip_rcvarp_rcv (最后一个返回0而不是NET_RX_DROP,但我不认为返回值很重要)。如果删除skb,请记住不要调用任何其他处理程序。

查看ip.c中的ip_rcv代码(底部):input.c#L375

如果一切顺利,它会将skb传递给Netfilter,后者调用ip_rcv_finish (如果不删除它)。如果出了问题,它会释放skb并返回。

编辑

如果多个协议处理程序匹配一个SKB,内核将将其发送给所有这些处理程序。当您在其中一个模块中使用kfree_skb()时,SKB仍然存在于其他处理程序中。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19342252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档