Linux-libre 5.4.48-gnu
[librecmc/linux-libre.git] / net / ipv6 / seg6_iptunnel.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  SR-IPv6 implementation
4  *
5  *  Author:
6  *  David Lebrun <david.lebrun@uclouvain.be>
7  */
8
9 #include <linux/types.h>
10 #include <linux/skbuff.h>
11 #include <linux/net.h>
12 #include <linux/module.h>
13 #include <net/ip.h>
14 #include <net/ip_tunnels.h>
15 #include <net/lwtunnel.h>
16 #include <net/netevent.h>
17 #include <net/netns/generic.h>
18 #include <net/ip6_fib.h>
19 #include <net/route.h>
20 #include <net/seg6.h>
21 #include <linux/seg6.h>
22 #include <linux/seg6_iptunnel.h>
23 #include <net/addrconf.h>
24 #include <net/ip6_route.h>
25 #include <net/dst_cache.h>
26 #ifdef CONFIG_IPV6_SEG6_HMAC
27 #include <net/seg6_hmac.h>
28 #endif
29
30 struct seg6_lwt {
31         struct dst_cache cache;
32         struct seg6_iptunnel_encap tuninfo[0];
33 };
34
35 static inline struct seg6_lwt *seg6_lwt_lwtunnel(struct lwtunnel_state *lwt)
36 {
37         return (struct seg6_lwt *)lwt->data;
38 }
39
40 static inline struct seg6_iptunnel_encap *
41 seg6_encap_lwtunnel(struct lwtunnel_state *lwt)
42 {
43         return seg6_lwt_lwtunnel(lwt)->tuninfo;
44 }
45
46 static const struct nla_policy seg6_iptunnel_policy[SEG6_IPTUNNEL_MAX + 1] = {
47         [SEG6_IPTUNNEL_SRH]     = { .type = NLA_BINARY },
48 };
49
50 static int nla_put_srh(struct sk_buff *skb, int attrtype,
51                        struct seg6_iptunnel_encap *tuninfo)
52 {
53         struct seg6_iptunnel_encap *data;
54         struct nlattr *nla;
55         int len;
56
57         len = SEG6_IPTUN_ENCAP_SIZE(tuninfo);
58
59         nla = nla_reserve(skb, attrtype, len);
60         if (!nla)
61                 return -EMSGSIZE;
62
63         data = nla_data(nla);
64         memcpy(data, tuninfo, len);
65
66         return 0;
67 }
68
69 static void set_tun_src(struct net *net, struct net_device *dev,
70                         struct in6_addr *daddr, struct in6_addr *saddr)
71 {
72         struct seg6_pernet_data *sdata = seg6_pernet(net);
73         struct in6_addr *tun_src;
74
75         rcu_read_lock();
76
77         tun_src = rcu_dereference(sdata->tun_src);
78
79         if (!ipv6_addr_any(tun_src)) {
80                 memcpy(saddr, tun_src, sizeof(struct in6_addr));
81         } else {
82                 ipv6_dev_get_saddr(net, dev, daddr, IPV6_PREFER_SRC_PUBLIC,
83                                    saddr);
84         }
85
86         rcu_read_unlock();
87 }
88
89 /* Compute flowlabel for outer IPv6 header */
90 static __be32 seg6_make_flowlabel(struct net *net, struct sk_buff *skb,
91                                   struct ipv6hdr *inner_hdr)
92 {
93         int do_flowlabel = net->ipv6.sysctl.seg6_flowlabel;
94         __be32 flowlabel = 0;
95         u32 hash;
96
97         if (do_flowlabel > 0) {
98                 hash = skb_get_hash(skb);
99                 hash = rol32(hash, 16);
100                 flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK;
101         } else if (!do_flowlabel && skb->protocol == htons(ETH_P_IPV6)) {
102                 flowlabel = ip6_flowlabel(inner_hdr);
103         }
104         return flowlabel;
105 }
106
107 /* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
108 int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
109 {
110         struct dst_entry *dst = skb_dst(skb);
111         struct net *net = dev_net(dst->dev);
112         struct ipv6hdr *hdr, *inner_hdr;
113         struct ipv6_sr_hdr *isrh;
114         int hdrlen, tot_len, err;
115         __be32 flowlabel;
116
117         hdrlen = (osrh->hdrlen + 1) << 3;
118         tot_len = hdrlen + sizeof(*hdr);
119
120         err = skb_cow_head(skb, tot_len + skb->mac_len);
121         if (unlikely(err))
122                 return err;
123
124         inner_hdr = ipv6_hdr(skb);
125         flowlabel = seg6_make_flowlabel(net, skb, inner_hdr);
126
127         skb_push(skb, tot_len);
128         skb_reset_network_header(skb);
129         skb_mac_header_rebuild(skb);
130         hdr = ipv6_hdr(skb);
131
132         /* inherit tc, flowlabel and hlim
133          * hlim will be decremented in ip6_forward() afterwards and
134          * decapsulation will overwrite inner hlim with outer hlim
135          */
136
137         if (skb->protocol == htons(ETH_P_IPV6)) {
138                 ip6_flow_hdr(hdr, ip6_tclass(ip6_flowinfo(inner_hdr)),
139                              flowlabel);
140                 hdr->hop_limit = inner_hdr->hop_limit;
141         } else {
142                 ip6_flow_hdr(hdr, 0, flowlabel);
143                 hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb));
144
145                 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
146         }
147
148         hdr->nexthdr = NEXTHDR_ROUTING;
149
150         isrh = (void *)hdr + sizeof(*hdr);
151         memcpy(isrh, osrh, hdrlen);
152
153         isrh->nexthdr = proto;
154
155         hdr->daddr = isrh->segments[isrh->first_segment];
156         set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr);
157
158 #ifdef CONFIG_IPV6_SEG6_HMAC
159         if (sr_has_hmac(isrh)) {
160                 err = seg6_push_hmac(net, &hdr->saddr, isrh);
161                 if (unlikely(err))
162                         return err;
163         }
164 #endif
165
166         skb_postpush_rcsum(skb, hdr, tot_len);
167
168         return 0;
169 }
170 EXPORT_SYMBOL_GPL(seg6_do_srh_encap);
171
172 /* insert an SRH within an IPv6 packet, just after the IPv6 header */
173 int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
174 {
175         struct ipv6hdr *hdr, *oldhdr;
176         struct ipv6_sr_hdr *isrh;
177         int hdrlen, err;
178
179         hdrlen = (osrh->hdrlen + 1) << 3;
180
181         err = skb_cow_head(skb, hdrlen + skb->mac_len);
182         if (unlikely(err))
183                 return err;
184
185         oldhdr = ipv6_hdr(skb);
186
187         skb_pull(skb, sizeof(struct ipv6hdr));
188         skb_postpull_rcsum(skb, skb_network_header(skb),
189                            sizeof(struct ipv6hdr));
190
191         skb_push(skb, sizeof(struct ipv6hdr) + hdrlen);
192         skb_reset_network_header(skb);
193         skb_mac_header_rebuild(skb);
194
195         hdr = ipv6_hdr(skb);
196
197         memmove(hdr, oldhdr, sizeof(*hdr));
198
199         isrh = (void *)hdr + sizeof(*hdr);
200         memcpy(isrh, osrh, hdrlen);
201
202         isrh->nexthdr = hdr->nexthdr;
203         hdr->nexthdr = NEXTHDR_ROUTING;
204
205         isrh->segments[0] = hdr->daddr;
206         hdr->daddr = isrh->segments[isrh->first_segment];
207
208 #ifdef CONFIG_IPV6_SEG6_HMAC
209         if (sr_has_hmac(isrh)) {
210                 struct net *net = dev_net(skb_dst(skb)->dev);
211
212                 err = seg6_push_hmac(net, &hdr->saddr, isrh);
213                 if (unlikely(err))
214                         return err;
215         }
216 #endif
217
218         skb_postpush_rcsum(skb, hdr, sizeof(struct ipv6hdr) + hdrlen);
219
220         return 0;
221 }
222 EXPORT_SYMBOL_GPL(seg6_do_srh_inline);
223
224 static int seg6_do_srh(struct sk_buff *skb)
225 {
226         struct dst_entry *dst = skb_dst(skb);
227         struct seg6_iptunnel_encap *tinfo;
228         int proto, err = 0;
229
230         tinfo = seg6_encap_lwtunnel(dst->lwtstate);
231
232         switch (tinfo->mode) {
233         case SEG6_IPTUN_MODE_INLINE:
234                 if (skb->protocol != htons(ETH_P_IPV6))
235                         return -EINVAL;
236
237                 err = seg6_do_srh_inline(skb, tinfo->srh);
238                 if (err)
239                         return err;
240                 break;
241         case SEG6_IPTUN_MODE_ENCAP:
242                 err = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6);
243                 if (err)
244                         return err;
245
246                 if (skb->protocol == htons(ETH_P_IPV6))
247                         proto = IPPROTO_IPV6;
248                 else if (skb->protocol == htons(ETH_P_IP))
249                         proto = IPPROTO_IPIP;
250                 else
251                         return -EINVAL;
252
253                 err = seg6_do_srh_encap(skb, tinfo->srh, proto);
254                 if (err)
255                         return err;
256
257                 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
258                 skb_set_inner_protocol(skb, skb->protocol);
259                 skb->protocol = htons(ETH_P_IPV6);
260                 break;
261         case SEG6_IPTUN_MODE_L2ENCAP:
262                 if (!skb_mac_header_was_set(skb))
263                         return -EINVAL;
264
265                 if (pskb_expand_head(skb, skb->mac_len, 0, GFP_ATOMIC) < 0)
266                         return -ENOMEM;
267
268                 skb_mac_header_rebuild(skb);
269                 skb_push(skb, skb->mac_len);
270
271                 err = seg6_do_srh_encap(skb, tinfo->srh, NEXTHDR_NONE);
272                 if (err)
273                         return err;
274
275                 skb->protocol = htons(ETH_P_IPV6);
276                 break;
277         }
278
279         ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
280         skb_set_transport_header(skb, sizeof(struct ipv6hdr));
281
282         return 0;
283 }
284
285 static int seg6_input(struct sk_buff *skb)
286 {
287         struct dst_entry *orig_dst = skb_dst(skb);
288         struct dst_entry *dst = NULL;
289         struct seg6_lwt *slwt;
290         int err;
291
292         err = seg6_do_srh(skb);
293         if (unlikely(err)) {
294                 kfree_skb(skb);
295                 return err;
296         }
297
298         slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
299
300         preempt_disable();
301         dst = dst_cache_get(&slwt->cache);
302         preempt_enable();
303
304         skb_dst_drop(skb);
305
306         if (!dst) {
307                 ip6_route_input(skb);
308                 dst = skb_dst(skb);
309                 if (!dst->error) {
310                         preempt_disable();
311                         dst_cache_set_ip6(&slwt->cache, dst,
312                                           &ipv6_hdr(skb)->saddr);
313                         preempt_enable();
314                 }
315         } else {
316                 skb_dst_set(skb, dst);
317         }
318
319         err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
320         if (unlikely(err))
321                 return err;
322
323         return dst_input(skb);
324 }
325
326 static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
327 {
328         struct dst_entry *orig_dst = skb_dst(skb);
329         struct dst_entry *dst = NULL;
330         struct seg6_lwt *slwt;
331         int err = -EINVAL;
332
333         err = seg6_do_srh(skb);
334         if (unlikely(err))
335                 goto drop;
336
337         slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
338
339         preempt_disable();
340         dst = dst_cache_get(&slwt->cache);
341         preempt_enable();
342
343         if (unlikely(!dst)) {
344                 struct ipv6hdr *hdr = ipv6_hdr(skb);
345                 struct flowi6 fl6;
346
347                 memset(&fl6, 0, sizeof(fl6));
348                 fl6.daddr = hdr->daddr;
349                 fl6.saddr = hdr->saddr;
350                 fl6.flowlabel = ip6_flowinfo(hdr);
351                 fl6.flowi6_mark = skb->mark;
352                 fl6.flowi6_proto = hdr->nexthdr;
353
354                 dst = ip6_route_output(net, NULL, &fl6);
355                 if (dst->error) {
356                         err = dst->error;
357                         dst_release(dst);
358                         goto drop;
359                 }
360
361                 preempt_disable();
362                 dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
363                 preempt_enable();
364         }
365
366         skb_dst_drop(skb);
367         skb_dst_set(skb, dst);
368
369         err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
370         if (unlikely(err))
371                 goto drop;
372
373         return dst_output(net, sk, skb);
374 drop:
375         kfree_skb(skb);
376         return err;
377 }
378
379 static int seg6_build_state(struct nlattr *nla,
380                             unsigned int family, const void *cfg,
381                             struct lwtunnel_state **ts,
382                             struct netlink_ext_ack *extack)
383 {
384         struct nlattr *tb[SEG6_IPTUNNEL_MAX + 1];
385         struct seg6_iptunnel_encap *tuninfo;
386         struct lwtunnel_state *newts;
387         int tuninfo_len, min_size;
388         struct seg6_lwt *slwt;
389         int err;
390
391         if (family != AF_INET && family != AF_INET6)
392                 return -EINVAL;
393
394         err = nla_parse_nested_deprecated(tb, SEG6_IPTUNNEL_MAX, nla,
395                                           seg6_iptunnel_policy, extack);
396
397         if (err < 0)
398                 return err;
399
400         if (!tb[SEG6_IPTUNNEL_SRH])
401                 return -EINVAL;
402
403         tuninfo = nla_data(tb[SEG6_IPTUNNEL_SRH]);
404         tuninfo_len = nla_len(tb[SEG6_IPTUNNEL_SRH]);
405
406         /* tuninfo must contain at least the iptunnel encap structure,
407          * the SRH and one segment
408          */
409         min_size = sizeof(*tuninfo) + sizeof(struct ipv6_sr_hdr) +
410                    sizeof(struct in6_addr);
411         if (tuninfo_len < min_size)
412                 return -EINVAL;
413
414         switch (tuninfo->mode) {
415         case SEG6_IPTUN_MODE_INLINE:
416                 if (family != AF_INET6)
417                         return -EINVAL;
418
419                 break;
420         case SEG6_IPTUN_MODE_ENCAP:
421                 break;
422         case SEG6_IPTUN_MODE_L2ENCAP:
423                 break;
424         default:
425                 return -EINVAL;
426         }
427
428         /* verify that SRH is consistent */
429         if (!seg6_validate_srh(tuninfo->srh, tuninfo_len - sizeof(*tuninfo)))
430                 return -EINVAL;
431
432         newts = lwtunnel_state_alloc(tuninfo_len + sizeof(*slwt));
433         if (!newts)
434                 return -ENOMEM;
435
436         slwt = seg6_lwt_lwtunnel(newts);
437
438         err = dst_cache_init(&slwt->cache, GFP_ATOMIC);
439         if (err) {
440                 kfree(newts);
441                 return err;
442         }
443
444         memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);
445
446         newts->type = LWTUNNEL_ENCAP_SEG6;
447         newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
448
449         if (tuninfo->mode != SEG6_IPTUN_MODE_L2ENCAP)
450                 newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT;
451
452         newts->headroom = seg6_lwt_headroom(tuninfo);
453
454         *ts = newts;
455
456         return 0;
457 }
458
459 static void seg6_destroy_state(struct lwtunnel_state *lwt)
460 {
461         dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache);
462 }
463
464 static int seg6_fill_encap_info(struct sk_buff *skb,
465                                 struct lwtunnel_state *lwtstate)
466 {
467         struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate);
468
469         if (nla_put_srh(skb, SEG6_IPTUNNEL_SRH, tuninfo))
470                 return -EMSGSIZE;
471
472         return 0;
473 }
474
475 static int seg6_encap_nlsize(struct lwtunnel_state *lwtstate)
476 {
477         struct seg6_iptunnel_encap *tuninfo = seg6_encap_lwtunnel(lwtstate);
478
479         return nla_total_size(SEG6_IPTUN_ENCAP_SIZE(tuninfo));
480 }
481
482 static int seg6_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
483 {
484         struct seg6_iptunnel_encap *a_hdr = seg6_encap_lwtunnel(a);
485         struct seg6_iptunnel_encap *b_hdr = seg6_encap_lwtunnel(b);
486         int len = SEG6_IPTUN_ENCAP_SIZE(a_hdr);
487
488         if (len != SEG6_IPTUN_ENCAP_SIZE(b_hdr))
489                 return 1;
490
491         return memcmp(a_hdr, b_hdr, len);
492 }
493
494 static const struct lwtunnel_encap_ops seg6_iptun_ops = {
495         .build_state = seg6_build_state,
496         .destroy_state = seg6_destroy_state,
497         .output = seg6_output,
498         .input = seg6_input,
499         .fill_encap = seg6_fill_encap_info,
500         .get_encap_size = seg6_encap_nlsize,
501         .cmp_encap = seg6_encap_cmp,
502         .owner = THIS_MODULE,
503 };
504
505 int __init seg6_iptunnel_init(void)
506 {
507         return lwtunnel_encap_add_ops(&seg6_iptun_ops, LWTUNNEL_ENCAP_SEG6);
508 }
509
510 void seg6_iptunnel_exit(void)
511 {
512         lwtunnel_encap_del_ops(&seg6_iptun_ops, LWTUNNEL_ENCAP_SEG6);
513 }