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

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

 #include  #include  #include  #include  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); 

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

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

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

 #include  #include  // 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; } 

我浏览了内核网络代码(一年后我在那里做了任何事情),我认为你应该能够做到这一点而不泄漏任何东西:

 kfree_skb(skb); return NET_RX_DROP; 

编辑

这在其他协议处理程序中完成,如ip_rcvarp_rcv (最后一个返回0而不是NET_RX_DROP,但我认为返回值不重要)。 如果你放弃skb,请记住不要打电话给任何其他处理程序。

在ip.c中查看ip_rcv的代码(在底部): http ://lxr.free-electrons.com/source/net/ipv4/ip_input.c#L375

如果一切顺利,它会将skb传递给Netfilter,Netfilter然后调用ip_rcv_finish (如果它不丢弃它)。 如果出现问题,它会释放skb并返回。

编辑

如果多个协议处理程序与SKB匹配,则内核会将其发送给所有协议处理程序。 当你在其中一个模块中使用kfree_skb()时,SKB仍将继续使用其他处理程序。