1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/init.h>
18#include <linux/mutex.h>
19#include <linux/skbuff.h>
20#include <net/icmp.h>
21#include <net/ip.h>
22#include <net/protocol.h>
23#include <net/xfrm.h>
24
25static struct xfrm4_protocol __rcu *esp4_handlers __read_mostly;
26static struct xfrm4_protocol __rcu *ah4_handlers __read_mostly;
27static struct xfrm4_protocol __rcu *ipcomp4_handlers __read_mostly;
28static DEFINE_MUTEX(xfrm4_protocol_mutex);
29
30static inline struct xfrm4_protocol __rcu **proto_handlers(u8 protocol)
31{
32 switch (protocol) {
33 case IPPROTO_ESP:
34 return &esp4_handlers;
35 case IPPROTO_AH:
36 return &ah4_handlers;
37 case IPPROTO_COMP:
38 return &ipcomp4_handlers;
39 }
40
41 return NULL;
42}
43
44#define for_each_protocol_rcu(head, handler) \
45 for (handler = rcu_dereference(head); \
46 handler != NULL; \
47 handler = rcu_dereference(handler->next)) \
48
49static int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
50{
51 int ret;
52 struct xfrm4_protocol *handler;
53 struct xfrm4_protocol __rcu **head = proto_handlers(protocol);
54
55 if (!head)
56 return 0;
57
58 for_each_protocol_rcu(*head, handler)
59 if ((ret = handler->cb_handler(skb, err)) <= 0)
60 return ret;
61
62 return 0;
63}
64
65int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
66 int encap_type)
67{
68 int ret;
69 struct xfrm4_protocol *handler;
70 struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr);
71
72 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
73 XFRM_SPI_SKB_CB(skb)->family = AF_INET;
74 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
75
76 if (!head)
77 goto out;
78
79 if (!skb_dst(skb)) {
80 const struct iphdr *iph = ip_hdr(skb);
81
82 if (ip_route_input_noref(skb, iph->daddr, iph->saddr,
83 iph->tos, skb->dev))
84 goto drop;
85 }
86
87 for_each_protocol_rcu(*head, handler)
88 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
89 return ret;
90
91out:
92 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
93
94drop:
95 kfree_skb(skb);
96 return 0;
97}
98EXPORT_SYMBOL(xfrm4_rcv_encap);
99
100static int xfrm4_esp_rcv(struct sk_buff *skb)
101{
102 int ret;
103 struct xfrm4_protocol *handler;
104
105 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
106
107 for_each_protocol_rcu(esp4_handlers, handler)
108 if ((ret = handler->handler(skb)) != -EINVAL)
109 return ret;
110
111 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
112
113 kfree_skb(skb);
114 return 0;
115}
116
117static int xfrm4_esp_err(struct sk_buff *skb, u32 info)
118{
119 struct xfrm4_protocol *handler;
120
121 for_each_protocol_rcu(esp4_handlers, handler)
122 if (!handler->err_handler(skb, info))
123 return 0;
124
125 return -ENOENT;
126}
127
128static int xfrm4_ah_rcv(struct sk_buff *skb)
129{
130 int ret;
131 struct xfrm4_protocol *handler;
132
133 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
134
135 for_each_protocol_rcu(ah4_handlers, handler)
136 if ((ret = handler->handler(skb)) != -EINVAL)
137 return ret;
138
139 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
140
141 kfree_skb(skb);
142 return 0;
143}
144
145static int xfrm4_ah_err(struct sk_buff *skb, u32 info)
146{
147 struct xfrm4_protocol *handler;
148
149 for_each_protocol_rcu(ah4_handlers, handler)
150 if (!handler->err_handler(skb, info))
151 return 0;
152
153 return -ENOENT;
154}
155
156static int xfrm4_ipcomp_rcv(struct sk_buff *skb)
157{
158 int ret;
159 struct xfrm4_protocol *handler;
160
161 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
162
163 for_each_protocol_rcu(ipcomp4_handlers, handler)
164 if ((ret = handler->handler(skb)) != -EINVAL)
165 return ret;
166
167 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
168
169 kfree_skb(skb);
170 return 0;
171}
172
173static int xfrm4_ipcomp_err(struct sk_buff *skb, u32 info)
174{
175 struct xfrm4_protocol *handler;
176
177 for_each_protocol_rcu(ipcomp4_handlers, handler)
178 if (!handler->err_handler(skb, info))
179 return 0;
180
181 return -ENOENT;
182}
183
184static const struct net_protocol esp4_protocol = {
185 .handler = xfrm4_esp_rcv,
186 .err_handler = xfrm4_esp_err,
187 .no_policy = 1,
188 .netns_ok = 1,
189};
190
191static const struct net_protocol ah4_protocol = {
192 .handler = xfrm4_ah_rcv,
193 .err_handler = xfrm4_ah_err,
194 .no_policy = 1,
195 .netns_ok = 1,
196};
197
198static const struct net_protocol ipcomp4_protocol = {
199 .handler = xfrm4_ipcomp_rcv,
200 .err_handler = xfrm4_ipcomp_err,
201 .no_policy = 1,
202 .netns_ok = 1,
203};
204
205static const struct xfrm_input_afinfo xfrm4_input_afinfo = {
206 .family = AF_INET,
207 .callback = xfrm4_rcv_cb,
208};
209
210static inline const struct net_protocol *netproto(unsigned char protocol)
211{
212 switch (protocol) {
213 case IPPROTO_ESP:
214 return &esp4_protocol;
215 case IPPROTO_AH:
216 return &ah4_protocol;
217 case IPPROTO_COMP:
218 return &ipcomp4_protocol;
219 }
220
221 return NULL;
222}
223
224int xfrm4_protocol_register(struct xfrm4_protocol *handler,
225 unsigned char protocol)
226{
227 struct xfrm4_protocol __rcu **pprev;
228 struct xfrm4_protocol *t;
229 bool add_netproto = false;
230 int ret = -EEXIST;
231 int priority = handler->priority;
232
233 if (!proto_handlers(protocol) || !netproto(protocol))
234 return -EINVAL;
235
236 mutex_lock(&xfrm4_protocol_mutex);
237
238 if (!rcu_dereference_protected(*proto_handlers(protocol),
239 lockdep_is_held(&xfrm4_protocol_mutex)))
240 add_netproto = true;
241
242 for (pprev = proto_handlers(protocol);
243 (t = rcu_dereference_protected(*pprev,
244 lockdep_is_held(&xfrm4_protocol_mutex))) != NULL;
245 pprev = &t->next) {
246 if (t->priority < priority)
247 break;
248 if (t->priority == priority)
249 goto err;
250 }
251
252 handler->next = *pprev;
253 rcu_assign_pointer(*pprev, handler);
254
255 ret = 0;
256
257err:
258 mutex_unlock(&xfrm4_protocol_mutex);
259
260 if (add_netproto) {
261 if (inet_add_protocol(netproto(protocol), protocol)) {
262 pr_err("%s: can't add protocol\n", __func__);
263 ret = -EAGAIN;
264 }
265 }
266
267 return ret;
268}
269EXPORT_SYMBOL(xfrm4_protocol_register);
270
271int xfrm4_protocol_deregister(struct xfrm4_protocol *handler,
272 unsigned char protocol)
273{
274 struct xfrm4_protocol __rcu **pprev;
275 struct xfrm4_protocol *t;
276 int ret = -ENOENT;
277
278 if (!proto_handlers(protocol) || !netproto(protocol))
279 return -EINVAL;
280
281 mutex_lock(&xfrm4_protocol_mutex);
282
283 for (pprev = proto_handlers(protocol);
284 (t = rcu_dereference_protected(*pprev,
285 lockdep_is_held(&xfrm4_protocol_mutex))) != NULL;
286 pprev = &t->next) {
287 if (t == handler) {
288 *pprev = handler->next;
289 ret = 0;
290 break;
291 }
292 }
293
294 if (!rcu_dereference_protected(*proto_handlers(protocol),
295 lockdep_is_held(&xfrm4_protocol_mutex))) {
296 if (inet_del_protocol(netproto(protocol), protocol) < 0) {
297 pr_err("%s: can't remove protocol\n", __func__);
298 ret = -EAGAIN;
299 }
300 }
301
302 mutex_unlock(&xfrm4_protocol_mutex);
303
304 synchronize_net();
305
306 return ret;
307}
308EXPORT_SYMBOL(xfrm4_protocol_deregister);
309
310void __init xfrm4_protocol_init(void)
311{
312 xfrm_input_register_afinfo(&xfrm4_input_afinfo);
313}
314EXPORT_SYMBOL(xfrm4_protocol_init);
315