diff -pruN -x .config linux-2.6.8.1/drivers/net/Kconfig linux-2.6.8.1-xfrm_dev/drivers/net/Kconfig --- linux-2.6.8.1/drivers/net/Kconfig 2004-08-14 12:56:00.000000000 +0200 +++ linux-2.6.8.1-xfrm_dev/drivers/net/Kconfig 2004-09-08 17:33:55.000000000 +0200 @@ -41,6 +41,10 @@ config DUMMY Instead of 'dummy', the devices will then be called 'dummy0', 'dummy1' etc. +config XFRM_DEV + tristate "XFRM net driver support (EXPERIMENTAL)" + depends on NETDEVICES && EXPERIMENTAL + config BONDING tristate "Bonding driver support" depends on NETDEVICES diff -pruN -x .config linux-2.6.8.1/drivers/net/Makefile linux-2.6.8.1-xfrm_dev/drivers/net/Makefile --- linux-2.6.8.1/drivers/net/Makefile 2004-08-14 12:55:09.000000000 +0200 +++ linux-2.6.8.1-xfrm_dev/drivers/net/Makefile 2004-09-08 17:32:17.000000000 +0200 @@ -108,6 +108,7 @@ ifeq ($(CONFIG_SLIP_COMPRESSED),y) endif obj-$(CONFIG_DUMMY) += dummy.o +obj-$(CONFIG_XFRM_DEV) += xfrm_dev.o obj-$(CONFIG_DE600) += de600.o obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_LANCE) += lance.o diff -pruN -x .config linux-2.6.8.1/drivers/net/xfrm_dev.c linux-2.6.8.1-xfrm_dev/drivers/net/xfrm_dev.c --- linux-2.6.8.1/drivers/net/xfrm_dev.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.8.1-xfrm_dev/drivers/net/xfrm_dev.c 2004-09-16 14:33:11.000000000 +0200 @@ -0,0 +1,129 @@ +/* xfrm_dev.c: a XFRM virtual net device +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +static int xfrm_dev_count = 8; + +static struct net_device **xfrm_devs; + +/* Maximum number of xfrm devices to be set up by this module. */ +module_param(xfrm_dev_count, int, 0); +MODULE_PARM_DESC(xfrm_dev_count, "Number of XFRM pseudo devices"); + +static int xfrm_dev_xmit(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *xfrm_dev_get_stats(struct net_device *dev); + +static int xfrm_dev_set_address(struct net_device *dev, void *p) +{ + struct sockaddr *sa = p; + + if (!is_valid_ether_addr(sa->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); + return 0; +} + +/* fake multicast ability */ +static void set_multicast_list(struct net_device *dev) +{ +} + +static void xfrm_dev_setup(struct net_device *dev) +{ + /* Initialize the device structure. */ + dev->get_stats = xfrm_dev_get_stats; + dev->hard_start_xmit = xfrm_dev_xmit; + dev->set_multicast_list = set_multicast_list; + dev->set_mac_address = xfrm_dev_set_address; + + /* Fill in device structure with ethernet-generic values. */ + ether_setup(dev); + dev->tx_queue_len = 0; + dev->change_mtu = NULL; + dev->flags |= IFF_NOARP; + dev->flags &= ~IFF_MULTICAST; + SET_MODULE_OWNER(dev); +} + +static int xfrm_dev_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct net_device_stats *stats = dev->priv; + + stats->tx_packets++; + stats->tx_bytes+=skb->len; + + dev_kfree_skb(skb); + return 0; +} + +static struct net_device_stats *xfrm_dev_get_stats(struct net_device *dev) +{ + return dev->priv; +} + +static int __init xfrm_dev_init_one(int index) +{ + struct net_device *dev_xfrm_dev; + int err; + + dev_xfrm_dev = alloc_netdev(sizeof(struct net_device_stats), + "xfrm%d", xfrm_dev_setup); + + if (!dev_xfrm_dev) + return -ENOMEM; + + if ((err = register_netdev(dev_xfrm_dev))) { + free_netdev(dev_xfrm_dev); + dev_xfrm_dev = NULL; + } else { + xfrm_devs[index] = dev_xfrm_dev; + } + + return err; +} + +static void xfrm_dev_free_one(int index) +{ + unregister_netdev(xfrm_devs[index]); + free_netdev(xfrm_devs[index]); +} + +static int __init xfrm_dev_init_module(void) +{ + int i,err = 0; + + xfrm_devs = kmalloc(xfrm_dev_count * sizeof(void *), GFP_KERNEL); + if (!xfrm_devs) + return -ENOMEM; + for (i = 0; i < xfrm_dev_count && !err; i++) + err = xfrm_dev_init_one(i); + if (err) { + while (--i >= 0) + xfrm_dev_free_one(i); + } + return 0; +} + +static void __exit xfrm_dev_cleanup_module(void) +{ + int i; + for (i = 0; i < xfrm_dev_count; i++) + xfrm_dev_free_one(i); + kfree(xfrm_devs); +} + +module_init(xfrm_dev_init_module); +module_exit(xfrm_dev_cleanup_module); +MODULE_AUTHOR("Sebastian Classen"); +MODULE_DESCRIPTION("Provides a virtual interface for tunnels using XFRM."); diff -pruN -x .config linux-2.6.8.1/include/net/xfrm.h linux-2.6.8.1-xfrm_dev/include/net/xfrm.h --- linux-2.6.8.1/include/net/xfrm.h 2004-08-14 12:56:00.000000000 +0200 +++ linux-2.6.8.1-xfrm_dev/include/net/xfrm.h 2004-09-13 12:07:59.000000000 +0200 @@ -139,6 +139,10 @@ struct xfrm_state struct xfrm_lifetime_cur curlft; struct timer_list timer; + /* XFRM device name and reference */ + char *xfrm_dev_name; + struct net_device *xfrm_dev; + /* Reference to data common to all the instances of this * transformer. */ struct xfrm_type *type; diff -pruN -x .config linux-2.6.8.1/net/ipv4/xfrm4_input.c linux-2.6.8.1-xfrm_dev/net/ipv4/xfrm4_input.c --- linux-2.6.8.1/net/ipv4/xfrm4_input.c 2004-08-14 12:54:50.000000000 +0200 +++ linux-2.6.8.1-xfrm_dev/net/ipv4/xfrm4_input.c 2004-09-16 13:34:51.000000000 +0200 @@ -138,6 +138,16 @@ int xfrm4_rcv_encap(struct sk_buff *skb, dst_release(skb->dst); skb->dst = NULL; } + if (!x->xfrm_dev) + if (x->xfrm_dev_name) { + x->xfrm_dev = dev_get_by_name(x->xfrm_dev_name); + printk ("xfrm4_input: Finde Device: %s --> 0x%p\n", x->xfrm_dev_name, x->xfrm_dev); + } + if (x->xfrm_dev) { + printk ("xfrm4_input: Device vorher: %s (0x%p)\n", skb->dev->name, skb->dev); + skb->dev = x->xfrm_dev; + printk ("xfrm4_input: Device nachher: %s (0x%p)\n", skb->dev->name, skb->dev); + } netif_rx(skb); return 0; } else { diff -pruN -x .config linux-2.6.8.1/net/ipv4/xfrm4_output.c linux-2.6.8.1-xfrm_dev/net/ipv4/xfrm4_output.c --- linux-2.6.8.1/net/ipv4/xfrm4_output.c 2004-08-14 12:55:09.000000000 +0200 +++ linux-2.6.8.1-xfrm_dev/net/ipv4/xfrm4_output.c 2004-09-16 13:06:21.000000000 +0200 @@ -14,6 +14,7 @@ #include #include #include +#include /* Add encapsulation header. * @@ -92,6 +93,8 @@ out: return ret; } +int xfrm4_nfhook(struct sk_buff *skb) { return 0; } + int xfrm4_output(struct sk_buff **pskb) { struct sk_buff *skb = *pskb; @@ -106,6 +109,14 @@ int xfrm4_output(struct sk_buff **pskb) goto error_nolock; } + printk("xfrm4_output: dev=%s input_dev=%s real_dev=%s\n", skb->dev->name, skb->input_dev->name, skb->real_dev->name); + printk("xfrm4_output: dst->dev=%s rt->u.dst.dev=%s\n", skb->dst->dev->name, ((struct rtable*)(skb->dst))->u.dst.dev->name); + printk("xfrm4_output: xfrm_dev=%s (0x%p)\n", x->xfrm_dev_name, x->xfrm_dev); + + err = NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev, xfrm4_nfhook); + if (err) + goto error_nolock; + spin_lock_bh(&x->lock); err = xfrm_state_check(x, skb); if (err) @@ -128,11 +139,17 @@ int xfrm4_output(struct sk_buff **pskb) x->curlft.packets++; spin_unlock_bh(&x->lock); - + if (!(skb->dst = dst_pop(dst))) { err = -EHOSTUNREACH; goto error_nolock; } + + nf_reset(skb); + err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dst->dev, xfrm4_nfhook); + if (err) + goto error_nolock; + err = NET_XMIT_BYPASS; out_exit: diff -pruN -x .config linux-2.6.8.1/net/ipv4/xfrm4_policy.c linux-2.6.8.1-xfrm_dev/net/ipv4/xfrm4_policy.c --- linux-2.6.8.1/net/ipv4/xfrm4_policy.c 2004-08-14 12:55:48.000000000 +0200 +++ linux-2.6.8.1-xfrm_dev/net/ipv4/xfrm4_policy.c 2004-09-14 14:36:39.000000000 +0200 @@ -125,7 +125,16 @@ __xfrm4_bundle_create(struct xfrm_policy x->u.rt.fl = *fl; dst_prev->xfrm = xfrm[i++]; - dst_prev->dev = rt->u.dst.dev; + if (!dst_prev->xfrm->xfrm_dev) + if (dst_prev->xfrm->xfrm_dev_name) { + dst_prev->xfrm->xfrm_dev = dev_get_by_name(dst_prev->xfrm->xfrm_dev_name); + printk ("xfrm4_policy: Finde Device: %s --> 0x%p\n", dst_prev->xfrm->xfrm_dev_name, dst_prev->xfrm->xfrm_dev); + } + if (dst_prev->xfrm->xfrm_dev) + dst_prev->dev = dst_prev->xfrm->xfrm_dev; + else + dst_prev->dev = rt->u.dst.dev; + printk ("xfrm4_policy: Device: %s (0x%p)\n", dst_prev->dev->name, dst_prev->dev); if (rt->u.dst.dev) dev_hold(rt->u.dst.dev); dst_prev->obsolete = -1; diff -pruN -x .config linux-2.6.8.1/net/xfrm/xfrm_state.c linux-2.6.8.1-xfrm_dev/net/xfrm/xfrm_state.c --- linux-2.6.8.1/net/xfrm/xfrm_state.c 2004-08-14 12:55:48.000000000 +0200 +++ linux-2.6.8.1-xfrm_dev/net/xfrm/xfrm_state.c 2004-09-13 12:13:52.000000000 +0200 @@ -184,6 +184,9 @@ struct xfrm_state *xfrm_state_alloc(void x->lft.hard_byte_limit = XFRM_INF; x->lft.hard_packet_limit = XFRM_INF; x->lock = SPIN_LOCK_UNLOCKED; + printk("xfrm_state_alloc: 0x%p\n",x); + x->xfrm_dev_name = "xfrm0"; + x->xfrm_dev = NULL; } return x; }