diff options
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r-- | net/ipv4/ipip.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 68a78731f72..c05c1df0bb0 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -255,7 +255,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c dev_hold(dev); ipip_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -273,7 +272,7 @@ static void ipip_tunnel_uninit(struct net_device *dev) dev_put(dev); } -static void ipip_err(struct sk_buff *skb, void *__unused) +static void ipip_err(struct sk_buff *skb, u32 info) { #ifndef I_WISH_WORLD_WERE_PERFECT @@ -852,11 +851,39 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev) return 0; } +#ifdef CONFIG_INET_TUNNEL static struct xfrm_tunnel ipip_handler = { .handler = ipip_rcv, .err_handler = ipip_err, }; +static inline int ipip_register(void) +{ + return xfrm4_tunnel_register(&ipip_handler); +} + +static inline int ipip_unregister(void) +{ + return xfrm4_tunnel_deregister(&ipip_handler); +} +#else +static struct net_protocol ipip_protocol = { + .handler = ipip_rcv, + .err_handler = ipip_err, + .no_policy = 1, +}; + +static inline int ipip_register(void) +{ + return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP); +} + +static inline int ipip_unregister(void) +{ + return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP); +} +#endif + static char banner[] __initdata = KERN_INFO "IPv4 over IPv4 tunneling driver\n"; @@ -866,7 +893,7 @@ static int __init ipip_init(void) printk(banner); - if (xfrm4_tunnel_register(&ipip_handler) < 0) { + if (ipip_register() < 0) { printk(KERN_INFO "ipip init: can't register tunnel\n"); return -EAGAIN; } @@ -888,16 +915,33 @@ static int __init ipip_init(void) err2: free_netdev(ipip_fb_tunnel_dev); err1: - xfrm4_tunnel_deregister(&ipip_handler); + ipip_unregister(); goto out; } +static void __exit ipip_destroy_tunnels(void) +{ + int prio; + + for (prio = 1; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + static void __exit ipip_fini(void) { - if (xfrm4_tunnel_deregister(&ipip_handler) < 0) + if (ipip_unregister() < 0) printk(KERN_INFO "ipip close: can't deregister tunnel\n"); - unregister_netdev(ipip_fb_tunnel_dev); + rtnl_lock(); + ipip_destroy_tunnels(); + unregister_netdevice(ipip_fb_tunnel_dev); + rtnl_unlock(); } module_init(ipip_init); |