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