How to filter and intercept Linux packages using net_dev_add () API?

I am writing a network network driver for Linux. I want to receive packages, edit and resend them. I know how to edit a package in the packet_interceptor function, but how can I remove incoming packets in this function?

 #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); 
+7
c network-programming kernel-module linux-device-driver netfilter
source share
2 answers

You create your module to handle all ethernet packets. Linux will send packets to all relevant protocol handlers. Since IP is already registered in your kernel, your module and ip_rcv will receive all SKBs with IP headers.

You cannot change this behavior without changing the kernel code. One possibility is to create a netfilter module. Thus, you can intercept the packet after the ip_rcv function and delete it if you want (in Netfilters PREROUTING hook).

Here is a small Netfilter module that I extracted from some code that I already wrote. This module is not complete, but the main material is in place.

 #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
source share

I looked at the kernel network code (a year since I did something there), and I think you should do this without missing anything:

 kfree_skb(skb); return NET_RX_DROP; 

Edit

This is done in other protocol handlers such as ip_rcv and arp_rcv (the latter returns 0 instead of NET_RX_DROP, but I don't think the return value matters very much). Remember that you do not call any other handlers if you throw skb.

See the ip_rcv code in ip.c (below): http://lxr.free-electrons.com/source/net/ipv4/ip_input.c#L375

If all goes well, it passes skb to Netfilter, which then calls ip_rcv_finish (if it doesn't drop it). If something goes wrong, it will free skb and return.

Edit

If more than one protocol handler matches SKB, the kernel will send it to all of them. When you kfree_skb() in one of the modules, SKB will continue to live in other handlers.

+6
source share

All Articles