1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6.
3 *
4 * Copyright (C) 2013 secunet Security Networks AG
5 *
6 * Author:
7 * Steffen Klassert <steffen.klassert@secunet.com>
8 *
9 * Based on:
10 * net/ipv4/xfrm4_protocol.c
11 */
12
13 #include <linux/init.h>
14 #include <linux/mutex.h>
15 #include <linux/skbuff.h>
16 #include <linux/icmpv6.h>
17 #include <net/ip6_route.h>
18 #include <net/ipv6.h>
19 #include <net/protocol.h>
20 #include <net/xfrm.h>
21
22 static struct xfrm6_protocol __rcu *esp6_handlers __read_mostly;
23 static struct xfrm6_protocol __rcu *ah6_handlers __read_mostly;
24 static struct xfrm6_protocol __rcu *ipcomp6_handlers __read_mostly;
25 static DEFINE_MUTEX(xfrm6_protocol_mutex);
26
proto_handlers(u8 protocol)27 static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol)
28 {
29 switch (protocol) {
30 case IPPROTO_ESP:
31 return &esp6_handlers;
32 case IPPROTO_AH:
33 return &ah6_handlers;
34 case IPPROTO_COMP:
35 return &ipcomp6_handlers;
36 }
37
38 return NULL;
39 }
40
41 #define for_each_protocol_rcu(head, handler) \
42 for (handler = rcu_dereference(head); \
43 handler != NULL; \
44 handler = rcu_dereference(handler->next)) \
45
xfrm6_rcv_cb(struct sk_buff * skb,u8 protocol,int err)46 static int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
47 {
48 int ret;
49 struct xfrm6_protocol *handler;
50 struct xfrm6_protocol __rcu **head = proto_handlers(protocol);
51
52 if (!head)
53 return 0;
54
55 for_each_protocol_rcu(*proto_handlers(protocol), handler)
56 if ((ret = handler->cb_handler(skb, err)) <= 0)
57 return ret;
58
59 return 0;
60 }
61
xfrm6_rcv_encap(struct sk_buff * skb,int nexthdr,__be32 spi,int encap_type)62 int xfrm6_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
63 int encap_type)
64 {
65 int ret;
66 struct xfrm6_protocol *handler;
67 struct xfrm6_protocol __rcu **head = proto_handlers(nexthdr);
68
69 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
70 XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
71 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
72
73 if (!head)
74 goto out;
75
76 if (!skb_dst(skb)) {
77 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
78 int flags = RT6_LOOKUP_F_HAS_SADDR;
79 struct dst_entry *dst;
80 struct flowi6 fl6 = {
81 .flowi6_iif = skb->dev->ifindex,
82 .daddr = ip6h->daddr,
83 .saddr = ip6h->saddr,
84 .flowlabel = ip6_flowinfo(ip6h),
85 .flowi6_mark = skb->mark,
86 .flowi6_proto = ip6h->nexthdr,
87 };
88
89 dst = ip6_route_input_lookup(dev_net(skb->dev), skb->dev, &fl6,
90 skb, flags);
91 if (dst->error) {
92 dst_release(dst);
93 goto drop;
94 }
95 skb_dst_set(skb, dst);
96 }
97
98 for_each_protocol_rcu(*head, handler)
99 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
100 return ret;
101
102 out:
103 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
104
105 drop:
106 kfree_skb(skb);
107 return 0;
108 }
109 EXPORT_SYMBOL(xfrm6_rcv_encap);
110
xfrm6_esp_rcv(struct sk_buff * skb)111 static int xfrm6_esp_rcv(struct sk_buff *skb)
112 {
113 int ret;
114 struct xfrm6_protocol *handler;
115
116 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
117
118 for_each_protocol_rcu(esp6_handlers, handler)
119 if ((ret = handler->handler(skb)) != -EINVAL)
120 return ret;
121
122 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
123
124 kfree_skb(skb);
125 return 0;
126 }
127
xfrm6_esp_err(struct sk_buff * skb,struct inet6_skb_parm * opt,u8 type,u8 code,int offset,__be32 info)128 static int xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
129 u8 type, u8 code, int offset, __be32 info)
130 {
131 struct xfrm6_protocol *handler;
132
133 for_each_protocol_rcu(esp6_handlers, handler)
134 if (!handler->err_handler(skb, opt, type, code, offset, info))
135 return 0;
136
137 return -ENOENT;
138 }
139
xfrm6_ah_rcv(struct sk_buff * skb)140 static int xfrm6_ah_rcv(struct sk_buff *skb)
141 {
142 int ret;
143 struct xfrm6_protocol *handler;
144
145 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
146
147 for_each_protocol_rcu(ah6_handlers, handler)
148 if ((ret = handler->handler(skb)) != -EINVAL)
149 return ret;
150
151 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
152
153 kfree_skb(skb);
154 return 0;
155 }
156
xfrm6_ah_err(struct sk_buff * skb,struct inet6_skb_parm * opt,u8 type,u8 code,int offset,__be32 info)157 static int xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
158 u8 type, u8 code, int offset, __be32 info)
159 {
160 struct xfrm6_protocol *handler;
161
162 for_each_protocol_rcu(ah6_handlers, handler)
163 if (!handler->err_handler(skb, opt, type, code, offset, info))
164 return 0;
165
166 return -ENOENT;
167 }
168
xfrm6_ipcomp_rcv(struct sk_buff * skb)169 static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
170 {
171 int ret;
172 struct xfrm6_protocol *handler;
173
174 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
175
176 for_each_protocol_rcu(ipcomp6_handlers, handler)
177 if ((ret = handler->handler(skb)) != -EINVAL)
178 return ret;
179
180 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
181
182 kfree_skb(skb);
183 return 0;
184 }
185
xfrm6_ipcomp_err(struct sk_buff * skb,struct inet6_skb_parm * opt,u8 type,u8 code,int offset,__be32 info)186 static int xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
187 u8 type, u8 code, int offset, __be32 info)
188 {
189 struct xfrm6_protocol *handler;
190
191 for_each_protocol_rcu(ipcomp6_handlers, handler)
192 if (!handler->err_handler(skb, opt, type, code, offset, info))
193 return 0;
194
195 return -ENOENT;
196 }
197
198 static const struct inet6_protocol esp6_protocol = {
199 .handler = xfrm6_esp_rcv,
200 .err_handler = xfrm6_esp_err,
201 .flags = INET6_PROTO_NOPOLICY,
202 };
203
204 static const struct inet6_protocol ah6_protocol = {
205 .handler = xfrm6_ah_rcv,
206 .err_handler = xfrm6_ah_err,
207 .flags = INET6_PROTO_NOPOLICY,
208 };
209
210 static const struct inet6_protocol ipcomp6_protocol = {
211 .handler = xfrm6_ipcomp_rcv,
212 .err_handler = xfrm6_ipcomp_err,
213 .flags = INET6_PROTO_NOPOLICY,
214 };
215
216 static const struct xfrm_input_afinfo xfrm6_input_afinfo = {
217 .family = AF_INET6,
218 .callback = xfrm6_rcv_cb,
219 };
220
netproto(unsigned char protocol)221 static inline const struct inet6_protocol *netproto(unsigned char protocol)
222 {
223 switch (protocol) {
224 case IPPROTO_ESP:
225 return &esp6_protocol;
226 case IPPROTO_AH:
227 return &ah6_protocol;
228 case IPPROTO_COMP:
229 return &ipcomp6_protocol;
230 }
231
232 return NULL;
233 }
234
xfrm6_protocol_register(struct xfrm6_protocol * handler,unsigned char protocol)235 int xfrm6_protocol_register(struct xfrm6_protocol *handler,
236 unsigned char protocol)
237 {
238 struct xfrm6_protocol __rcu **pprev;
239 struct xfrm6_protocol *t;
240 bool add_netproto = false;
241 int ret = -EEXIST;
242 int priority = handler->priority;
243
244 if (!proto_handlers(protocol) || !netproto(protocol))
245 return -EINVAL;
246
247 mutex_lock(&xfrm6_protocol_mutex);
248
249 if (!rcu_dereference_protected(*proto_handlers(protocol),
250 lockdep_is_held(&xfrm6_protocol_mutex)))
251 add_netproto = true;
252
253 for (pprev = proto_handlers(protocol);
254 (t = rcu_dereference_protected(*pprev,
255 lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
256 pprev = &t->next) {
257 if (t->priority < priority)
258 break;
259 if (t->priority == priority)
260 goto err;
261 }
262
263 handler->next = *pprev;
264 rcu_assign_pointer(*pprev, handler);
265
266 ret = 0;
267
268 err:
269 mutex_unlock(&xfrm6_protocol_mutex);
270
271 if (add_netproto) {
272 if (inet6_add_protocol(netproto(protocol), protocol)) {
273 pr_err("%s: can't add protocol\n", __func__);
274 ret = -EAGAIN;
275 }
276 }
277
278 return ret;
279 }
280 EXPORT_SYMBOL(xfrm6_protocol_register);
281
xfrm6_protocol_deregister(struct xfrm6_protocol * handler,unsigned char protocol)282 int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
283 unsigned char protocol)
284 {
285 struct xfrm6_protocol __rcu **pprev;
286 struct xfrm6_protocol *t;
287 int ret = -ENOENT;
288
289 if (!proto_handlers(protocol) || !netproto(protocol))
290 return -EINVAL;
291
292 mutex_lock(&xfrm6_protocol_mutex);
293
294 for (pprev = proto_handlers(protocol);
295 (t = rcu_dereference_protected(*pprev,
296 lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
297 pprev = &t->next) {
298 if (t == handler) {
299 *pprev = handler->next;
300 ret = 0;
301 break;
302 }
303 }
304
305 if (!rcu_dereference_protected(*proto_handlers(protocol),
306 lockdep_is_held(&xfrm6_protocol_mutex))) {
307 if (inet6_del_protocol(netproto(protocol), protocol) < 0) {
308 pr_err("%s: can't remove protocol\n", __func__);
309 ret = -EAGAIN;
310 }
311 }
312
313 mutex_unlock(&xfrm6_protocol_mutex);
314
315 synchronize_net();
316
317 return ret;
318 }
319 EXPORT_SYMBOL(xfrm6_protocol_deregister);
320
xfrm6_protocol_init(void)321 int __init xfrm6_protocol_init(void)
322 {
323 return xfrm_input_register_afinfo(&xfrm6_input_afinfo);
324 }
325
xfrm6_protocol_fini(void)326 void xfrm6_protocol_fini(void)
327 {
328 xfrm_input_unregister_afinfo(&xfrm6_input_afinfo);
329 }
330