Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27-rc6 179 lines 4.0 kB view raw
1/* tunnel4.c: Generic IP tunnel transformer. 2 * 3 * Copyright (C) 2003 David S. Miller (davem@redhat.com) 4 */ 5 6#include <linux/init.h> 7#include <linux/module.h> 8#include <linux/mutex.h> 9#include <linux/netdevice.h> 10#include <linux/skbuff.h> 11#include <net/icmp.h> 12#include <net/ip.h> 13#include <net/protocol.h> 14#include <net/xfrm.h> 15 16static struct xfrm_tunnel *tunnel4_handlers; 17static struct xfrm_tunnel *tunnel64_handlers; 18static DEFINE_MUTEX(tunnel4_mutex); 19 20static inline struct xfrm_tunnel **fam_handlers(unsigned short family) 21{ 22 return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; 23} 24 25int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) 26{ 27 struct xfrm_tunnel **pprev; 28 int ret = -EEXIST; 29 int priority = handler->priority; 30 31 mutex_lock(&tunnel4_mutex); 32 33 for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) { 34 if ((*pprev)->priority > priority) 35 break; 36 if ((*pprev)->priority == priority) 37 goto err; 38 } 39 40 handler->next = *pprev; 41 *pprev = handler; 42 43 ret = 0; 44 45err: 46 mutex_unlock(&tunnel4_mutex); 47 48 return ret; 49} 50 51EXPORT_SYMBOL(xfrm4_tunnel_register); 52 53int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) 54{ 55 struct xfrm_tunnel **pprev; 56 int ret = -ENOENT; 57 58 mutex_lock(&tunnel4_mutex); 59 60 for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) { 61 if (*pprev == handler) { 62 *pprev = handler->next; 63 ret = 0; 64 break; 65 } 66 } 67 68 mutex_unlock(&tunnel4_mutex); 69 70 synchronize_net(); 71 72 return ret; 73} 74 75EXPORT_SYMBOL(xfrm4_tunnel_deregister); 76 77static int tunnel4_rcv(struct sk_buff *skb) 78{ 79 struct xfrm_tunnel *handler; 80 81 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 82 goto drop; 83 84 for (handler = tunnel4_handlers; handler; handler = handler->next) 85 if (!handler->handler(skb)) 86 return 0; 87 88 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 89 90drop: 91 kfree_skb(skb); 92 return 0; 93} 94 95#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 96static int tunnel64_rcv(struct sk_buff *skb) 97{ 98 struct xfrm_tunnel *handler; 99 100 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 101 goto drop; 102 103 for (handler = tunnel64_handlers; handler; handler = handler->next) 104 if (!handler->handler(skb)) 105 return 0; 106 107 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 108 109drop: 110 kfree_skb(skb); 111 return 0; 112} 113#endif 114 115static void tunnel4_err(struct sk_buff *skb, u32 info) 116{ 117 struct xfrm_tunnel *handler; 118 119 for (handler = tunnel4_handlers; handler; handler = handler->next) 120 if (!handler->err_handler(skb, info)) 121 break; 122} 123 124#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 125static void tunnel64_err(struct sk_buff *skb, u32 info) 126{ 127 struct xfrm_tunnel *handler; 128 129 for (handler = tunnel64_handlers; handler; handler = handler->next) 130 if (!handler->err_handler(skb, info)) 131 break; 132} 133#endif 134 135static struct net_protocol tunnel4_protocol = { 136 .handler = tunnel4_rcv, 137 .err_handler = tunnel4_err, 138 .no_policy = 1, 139 .netns_ok = 1, 140}; 141 142#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 143static struct net_protocol tunnel64_protocol = { 144 .handler = tunnel64_rcv, 145 .err_handler = tunnel64_err, 146 .no_policy = 1, 147 .netns_ok = 1, 148}; 149#endif 150 151static int __init tunnel4_init(void) 152{ 153 if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { 154 printk(KERN_ERR "tunnel4 init: can't add protocol\n"); 155 return -EAGAIN; 156 } 157#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 158 if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { 159 printk(KERN_ERR "tunnel64 init: can't add protocol\n"); 160 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); 161 return -EAGAIN; 162 } 163#endif 164 return 0; 165} 166 167static void __exit tunnel4_fini(void) 168{ 169#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 170 if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) 171 printk(KERN_ERR "tunnel64 close: can't remove protocol\n"); 172#endif 173 if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 174 printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); 175} 176 177module_init(tunnel4_init); 178module_exit(tunnel4_fini); 179MODULE_LICENSE("GPL");