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 17 static struct xfrm_tunnel *tunnel4_handlers __read_mostly; 18 static struct xfrm_tunnel *tunnel64_handlers __read_mostly; 19 static DEFINE_MUTEX(tunnel4_mutex); 20 21 static inline struct xfrm_tunnel **fam_handlers(unsigned short family) 22 { 23 return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; 24 } 25 26 int 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 rcu_assign_pointer(*pprev, handler); 43 44 ret = 0; 45 46 err: 47 mutex_unlock(&tunnel4_mutex); 48 49 return ret; 50 } 51 EXPORT_SYMBOL(xfrm4_tunnel_register); 52 53 int 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 EXPORT_SYMBOL(xfrm4_tunnel_deregister); 75 76 #define for_each_tunnel_rcu(head, handler) \ 77 for (handler = rcu_dereference(head); \ 78 handler != NULL; \ 79 handler = rcu_dereference(handler->next)) \ 80 81 static int tunnel4_rcv(struct sk_buff *skb) 82 { 83 struct xfrm_tunnel *handler; 84 85 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 86 goto drop; 87 88 for_each_tunnel_rcu(tunnel4_handlers, handler) 89 if (!handler->handler(skb)) 90 return 0; 91 92 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 93 94 drop: 95 kfree_skb(skb); 96 return 0; 97 } 98 99 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 100 static int tunnel64_rcv(struct sk_buff *skb) 101 { 102 struct xfrm_tunnel *handler; 103 104 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 105 goto drop; 106 107 for_each_tunnel_rcu(tunnel64_handlers, handler) 108 if (!handler->handler(skb)) 109 return 0; 110 111 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 112 113 drop: 114 kfree_skb(skb); 115 return 0; 116 } 117 #endif 118 119 static void tunnel4_err(struct sk_buff *skb, u32 info) 120 { 121 struct xfrm_tunnel *handler; 122 123 for_each_tunnel_rcu(tunnel4_handlers, handler) 124 if (!handler->err_handler(skb, info)) 125 break; 126 } 127 128 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 129 static void tunnel64_err(struct sk_buff *skb, u32 info) 130 { 131 struct xfrm_tunnel *handler; 132 133 for_each_tunnel_rcu(tunnel64_handlers, handler) 134 if (!handler->err_handler(skb, info)) 135 break; 136 } 137 #endif 138 139 static const struct net_protocol tunnel4_protocol = { 140 .handler = tunnel4_rcv, 141 .err_handler = tunnel4_err, 142 .no_policy = 1, 143 .netns_ok = 1, 144 }; 145 146 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 147 static const struct net_protocol tunnel64_protocol = { 148 .handler = tunnel64_rcv, 149 .err_handler = tunnel64_err, 150 .no_policy = 1, 151 .netns_ok = 1, 152 }; 153 #endif 154 155 static int __init tunnel4_init(void) 156 { 157 if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { 158 printk(KERN_ERR "tunnel4 init: can't add protocol\n"); 159 return -EAGAIN; 160 } 161 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 162 if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { 163 printk(KERN_ERR "tunnel64 init: can't add protocol\n"); 164 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); 165 return -EAGAIN; 166 } 167 #endif 168 return 0; 169 } 170 171 static void __exit tunnel4_fini(void) 172 { 173 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 174 if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) 175 printk(KERN_ERR "tunnel64 close: can't remove protocol\n"); 176 #endif 177 if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 178 printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); 179 } 180 181 module_init(tunnel4_init); 182 module_exit(tunnel4_fini); 183 MODULE_LICENSE("GPL"); 184