2.4.8 frame diverter for modules
Subsystems (2)
PATCH 1/1 2.4.8 frame diverter for modules
Here is a patch against 2.4.8 that implements support for diverting network frames to an arbitrary kernel module. It is similar to the user-level packet diverter except that it handles both incoming and outgoing packets, and the module can discard the packet if it wants to. There is also a callback when a packet is freed. This allows a modular way of doing low-level packet frobbing without going out to userland.
As noted in the code, it currently only supports 1 'diverter module', but it would be pretty easy to support more...
Comments? Anyone find this sort of thing useful besides us?
Signature · 2 lines
-Will :: AD6XL :: http://www.loopfree.net/ Orton :: finger [email protected] for GPG public key
include/linux/moddv.h +31 -0
@@ -0,0 +1,31 @@ +#ifndef _MODDV_H_ +#define _MODDV_H_ + +struct moddv_calls { +atomic_t unloading; +atomic_t usage; +int (*divert_tx)(struct sk_buff **,struct net_device **,struct packet_type **); +int (*divert_rx)(struct sk_buff **,struct net_device **,struct packet_type **); +void (*divert_bind)(struct net_device *,struct packet_type *); +void (*divert_free)(struct sk_buff *); +}; + +extern int register_divert_module (struct moddv_calls *); +extern void unregister_divert_module (struct moddv_calls * ); +void mod_divert_inject_out (struct sk_buff *,struct net_device *); +void mod_divert_inject_in (struct sk_buff *,struct net_device *,struct packet_type *); + +int handle_mod_divert_tx (struct sk_buff **,struct net_device **); +int handle_mod_divert_rx (struct sk_buff **,struct net_device **,struct packet_type **); +void mod_divert_skb_use (struct sk_buff *); +void mod_divert_skb_unuse (struct sk_buff *); +void mod_divert_init (void ); + +extern struct moddv_calls *diverter; + +#define MDV_DISCARD 1 +#define MDV_HOLD 2 +#define MDV_CHAIN 3 + + +#endif /* _MODDV_H_ */
include/linux/netdevice.h +3 -0
@@ -418,6 +418,9 @@ struct packet_type *);void *data;/* Private to the packet type */ struct packet_type *next; +#ifdef CONFIG_MOD_DIVERT +void *divertPtr;/* Private ptr for the module diverter */ +#endif };
include/linux/skbuff.h +3 -0
@@ -213,6 +213,9 @@#ifdef CONFIG_NET_SCHED __u32 tc_index;/* traffic control index */ #endif +#ifdef CONFIG_MOD_DIVERT +void *divertPtr1; +#endif };#define SK_WMEM_MAX 65535
net/Config.in +1 -0
@@ -64,6 +64,7 @@ tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT + bool 'Frame diverter for modules (EXPERIMENTAL)' CONFIG_MOD_DIVERT # if [ "$CONFIG_LLC" = "y" ]; then # bool ' Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI # fi
net/core/Makefile +1 -0
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o obj-$(CONFIG_NETFILTER) += netfilter.o +obj-$(CONFIG_MOD_DIVERT) += moddv.o obj-$(CONFIG_NET_DIVERT) += dv.o obj-$(CONFIG_NET_PROFILE) += profile.o
net/core/dev.c +31 -3
@@ -103,6 +103,9 @@#if defined(CONFIG_NET_RADIO ) || defined(CONFIG_NET_PCMCIA_RADIO )#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ +#ifdef CONFIG_MOD_DIVERT +#include <linux/moddv.h> +#endif /* CONFIG_MOD_DIVERT */ #ifdef CONFIG_PLIP extern int plip_init (void );#endif
@@ -152,8 +155,13 @@* 86DD IPv6 */ +#ifdef CONFIG_MOD_DIVERT +struct packet_type *ptype_base[16 ];/* 16 way hashed list */ +struct packet_type *ptype_all =NULL ;/* Taps */ +#else /* !CONFIG_MOD_DIVERT */ static struct packet_type *ptype_base[16 ];/* 16 way hashed list */ static struct packet_type *ptype_all =NULL ;/* Taps */ +#endif /* !CONFIG_MOD_DIVERT */ #ifdef OFFLINE_SAMPLE static void sample_queue (unsigned long dummy);
@@ -987,6 +995,12 @@return -ENOMEM ; } +/* call the module diverter */ +#ifdef CONFIG_MOD_DIVERT +if (handle_mod_divert_tx (&skb, &dev)) +return NET_XMIT_SUCCESS ; +#endif +/* Grab device queue */ spin_lock_bh (&dev->queue_lock); q = dev->qdisc;
@@ -1475,6 +1489,10 @@deliver_to_old_ones (pt_prev, skb,0 ); else {atomic_inc (&skb->users); +#ifdef CONFIG_MOD_DIVERT +if (handle_mod_divert_rx (&skb, &rx_dev, &pt_prev)) + goto DEAD_PACKET; +#endif /* CONFIG_MOD_DIVERT */ pt_prev->func (skb, skb->dev, pt_prev);
@@ -1487,12 +1505,19 @@if (pt_prev) {if (!pt_prev->data)deliver_to_old_ones (pt_prev, skb,1 ); -else +else { +#ifdef CONFIG_MOD_DIVERT +if (handle_mod_divert_rx (&skb, &rx_dev, &pt_prev)) + goto DEAD_PACKET; +#endif /* CONFIG_MOD_DIVERT */ pt_prev->func (skb, skb->dev, pt_prev); + } }else kfree_skb (skb); } - +#ifdef CONFIG_MOD_DIVERT +DEAD_PACKET: +#endif dev_put (rx_dev);if (bugdet-- <0 || jiffies - start_time >1 )
@@ -2783,7 +2808,10 @@*/ net_device_init (); - + +#ifdef CONFIG_MOD_DIVERT +mod_divert_init (); +#endif /* CONFIG_MOD_DIVERT */ return 0 ; }
net/core/moddv.c +239 -0
239 lines not on this page · raw message
net/core/skbuff.c +27 -0
@@ -51,6 +51,9 @@#include <linux/cache.h> #include <linux/init.h> #include <linux/highmem.h> +#ifdef CONFIG_MOD_DIVERT +#include <linux/moddv.h> +#endif /* CONFIG_MOD_DIVERT */ #include <net/ip.h> #include <net/protocol.h>
@@ -209,6 +212,9 @@atomic_set (&(skb_shinfo (skb)->dataref),1 );skb_shinfo (skb)->nr_frags =0 ;skb_shinfo (skb)->frag_list =NULL ; +#ifdef CONFIG_MOD_DIVERT + skb->divertPtr1 =NULL ; +#endif return skb; nodata:
@@ -250,6 +256,9 @@#ifdef CONFIG_NET_SCHED skb->tc_index =0 ;#endif +#ifdef CONFIG_MOD_DIVERT + skb->divertPtr1 =NULL ; +#endif /* CONFIG_MOD_DIVERT */ }static void skb_drop_fraglist (struct sk_buff *skb)
@@ -275,6 +284,9 @@static void skb_release_data (struct sk_buff *skb) { +#ifdef CONFIG_MOD_DIVERT +if (skb->head) { +#endif if (!skb->cloned ||atomic_dec_and_test (&(skb_shinfo (skb)->dataref))) {if (skb_shinfo (skb)->nr_frags) {
@@ -288,6 +300,9 @@kfree (skb->head); } +#ifdef CONFIG_MOD_DIVERT + } +#endif }/*
@@ -316,7 +331,12 @@BUG (); } +#ifdef CONFIG_MOD_DIVERT +if (skb->dst) +dst_release (skb->dst); +#else dst_release (skb->dst); +#endif if (skb->destructor) {if (in_irq ()) { printk(KERN_WARNING "Warning: kfree_skb on hard IRQ %p\n",
@@ -327,6 +347,10 @@#ifdef CONFIG_NETFILTER nf_conntrack_put (skb->nfct);#endif +#ifdef CONFIG_MOD_DIVERT +if (skb->divertPtr1) +mod_divert_skb_unuse (skb); +#endif /* CONFIG_MOD_DIVERT */ skb_headerinit (skb,NULL ,0 );/* clean state */ kfree_skbmem (skb); }
@@ -404,6 +428,9 @@ skb->cloned =1 ;#ifdef CONFIG_NETFILTER nf_conntrack_get (skb->nfct); +#endif +#ifdef CONFIG_MOD_DIVERT + n->divertPtr1 =NULL ;#endif return n; }
net/netsyms.c +8 -0
@@ -34,6 +34,9 @@#ifdef CONFIG_NET_DIVERT #include <linux/divert.h> #endif /* CONFIG_NET_DIVERT */ +#ifdef CONFIG_MOD_DIVERT +#include <linux/moddv.h> +#endif /* CONFIG_MOD_DIVERT */ #ifdef CONFIG_NET extern __u32 sysctl_wmem_max;
@@ -230,6 +233,11 @@EXPORT_SYMBOL (free_divert_blk);EXPORT_SYMBOL (divert_ioctl);#endif /* CONFIG_NET_DIVERT */ + +#ifdef CONFIG_MOD_DIVERT +EXPORT_SYMBOL_NOVERS (register_divert_module); +EXPORT_SYMBOL_NOVERS (unregister_divert_module); +#endif /* CONFIG_MOD_DIVERT */ #ifdef CONFIG_INET /* Internet layer registration */