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; 18 static struct xfrm_tunnel *tunnel64_handlers; 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 *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 static int tunnel4_rcv(struct sk_buff *skb) 77 { 78 struct xfrm_tunnel *handler; 79 80 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 81 goto drop; 82 83 for (handler = tunnel4_handlers; handler; handler = handler->next) 84 if (!handler->handler(skb)) 85 return 0; 86 87 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 88 89 drop: 90 kfree_skb(skb); 91 return 0; 92 } 93 94 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 95 static int tunnel64_rcv(struct sk_buff *skb) 96 { 97 struct xfrm_tunnel *handler; 98 99 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 100 goto drop; 101 102 for (handler = tunnel64_handlers; handler; handler = handler->next) 103 if (!handler->handler(skb)) 104 return 0; 105 106 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 107 108 drop: 109 kfree_skb(skb); 110 return 0; 111 } 112 #endif 113 114 static void tunnel4_err(struct sk_buff *skb, u32 info) 115 { 116 struct xfrm_tunnel *handler; 117 118 for (handler = tunnel4_handlers; handler; handler = handler->next) 119 if (!handler->err_handler(skb, info)) 120 break; 121 } 122 123 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 124 static void tunnel64_err(struct sk_buff *skb, u32 info) 125 { 126 struct xfrm_tunnel *handler; 127 128 for (handler = tunnel64_handlers; handler; handler = handler->next) 129 if (!handler->err_handler(skb, info)) 130 break; 131 } 132 #endif 133 134 static const struct net_protocol tunnel4_protocol = { 135 .handler = tunnel4_rcv, 136 .err_handler = tunnel4_err, 137 .no_policy = 1, 138 .netns_ok = 1, 139 }; 140 141 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 142 static const struct net_protocol tunnel64_protocol = { 143 .handler = tunnel64_rcv, 144 .err_handler = tunnel64_err, 145 .no_policy = 1, 146 .netns_ok = 1, 147 }; 148 #endif 149 150 static int __init tunnel4_init(void) 151 { 152 if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { 153 printk(KERN_ERR "tunnel4 init: can't add protocol\n"); 154 return -EAGAIN; 155 } 156 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 157 if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { 158 printk(KERN_ERR "tunnel64 init: can't add protocol\n"); 159 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); 160 return -EAGAIN; 161 } 162 #endif 163 return 0; 164 } 165 166 static void __exit tunnel4_fini(void) 167 { 168 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 169 if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) 170 printk(KERN_ERR "tunnel64 close: can't remove protocol\n"); 171 #endif 172 if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 173 printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); 174 } 175 176 module_init(tunnel4_init); 177 module_exit(tunnel4_fini); 178 MODULE_LICENSE("GPL"); 179