xref: /linux/net/ipv4/tunnel4.c (revision d39d0ed196aa1685bb24771e92f78633c66ac9cb)
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