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 16 static struct xfrm_tunnel *tunnel4_handlers; 17 static struct xfrm_tunnel *tunnel64_handlers; 18 static DEFINE_MUTEX(tunnel4_mutex); 19 20 static inline struct xfrm_tunnel **fam_handlers(unsigned short family) 21 { 22 return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; 23 } 24 25 int 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 45 err: 46 mutex_unlock(&tunnel4_mutex); 47 48 return ret; 49 } 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 75 EXPORT_SYMBOL(xfrm4_tunnel_deregister); 76 77 static 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 90 drop: 91 kfree_skb(skb); 92 return 0; 93 } 94 95 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 96 static 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 109 drop: 110 kfree_skb(skb); 111 return 0; 112 } 113 #endif 114 115 static 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) 125 static 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 135 static 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) 143 static 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 151 static 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 167 static 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 177 module_init(tunnel4_init); 178 module_exit(tunnel4_fini); 179 MODULE_LICENSE("GPL"); 180