• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  SR-IPv6 implementation
4  *
5  *  Authors:
6  *  David Lebrun <david.lebrun@uclouvain.be>
7  *  eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com>
8  */
9 
10 #include <linux/types.h>
11 #include <linux/skbuff.h>
12 #include <linux/net.h>
13 #include <linux/module.h>
14 #include <net/ip.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_local.h>
23 #include <net/addrconf.h>
24 #include <net/ip6_route.h>
25 #include <net/dst_cache.h>
26 #include <net/ip_tunnels.h>
27 #ifdef CONFIG_IPV6_SEG6_HMAC
28 #include <net/seg6_hmac.h>
29 #endif
30 #include <net/seg6_local.h>
31 #include <linux/etherdevice.h>
32 #include <linux/bpf.h>
33 
34 struct seg6_local_lwt;
35 
36 struct seg6_action_desc {
37 	int action;
38 	unsigned long attrs;
39 	int (*input)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
40 	int static_headroom;
41 };
42 
43 struct bpf_lwt_prog {
44 	struct bpf_prog *prog;
45 	char *name;
46 };
47 
48 struct seg6_local_lwt {
49 	int action;
50 	struct ipv6_sr_hdr *srh;
51 	int table;
52 	struct in_addr nh4;
53 	struct in6_addr nh6;
54 	int iif;
55 	int oif;
56 	struct bpf_lwt_prog bpf;
57 
58 	int headroom;
59 	struct seg6_action_desc *desc;
60 };
61 
seg6_local_lwtunnel(struct lwtunnel_state * lwt)62 static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
63 {
64 	return (struct seg6_local_lwt *)lwt->data;
65 }
66 
get_srh(struct sk_buff * skb)67 static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb)
68 {
69 	struct ipv6_sr_hdr *srh;
70 	int len, srhoff = 0;
71 
72 	if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
73 		return NULL;
74 
75 	if (!pskb_may_pull(skb, srhoff + sizeof(*srh)))
76 		return NULL;
77 
78 	srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
79 
80 	len = (srh->hdrlen + 1) << 3;
81 
82 	if (!pskb_may_pull(skb, srhoff + len))
83 		return NULL;
84 
85 	/* note that pskb_may_pull may change pointers in header;
86 	 * for this reason it is necessary to reload them when needed.
87 	 */
88 	srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
89 
90 	if (!seg6_validate_srh(srh, len))
91 		return NULL;
92 
93 	return srh;
94 }
95 
get_and_validate_srh(struct sk_buff * skb)96 static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb)
97 {
98 	struct ipv6_sr_hdr *srh;
99 
100 	srh = get_srh(skb);
101 	if (!srh)
102 		return NULL;
103 
104 	if (srh->segments_left == 0)
105 		return NULL;
106 
107 #ifdef CONFIG_IPV6_SEG6_HMAC
108 	if (!seg6_hmac_validate_skb(skb))
109 		return NULL;
110 #endif
111 
112 	return srh;
113 }
114 
decap_and_validate(struct sk_buff * skb,int proto)115 static bool decap_and_validate(struct sk_buff *skb, int proto)
116 {
117 	struct ipv6_sr_hdr *srh;
118 	unsigned int off = 0;
119 
120 	srh = get_srh(skb);
121 	if (srh && srh->segments_left > 0)
122 		return false;
123 
124 #ifdef CONFIG_IPV6_SEG6_HMAC
125 	if (srh && !seg6_hmac_validate_skb(skb))
126 		return false;
127 #endif
128 
129 	if (ipv6_find_hdr(skb, &off, proto, NULL, NULL) < 0)
130 		return false;
131 
132 	if (!pskb_pull(skb, off))
133 		return false;
134 
135 	skb_postpull_rcsum(skb, skb_network_header(skb), off);
136 
137 	skb_reset_network_header(skb);
138 	skb_reset_transport_header(skb);
139 	if (iptunnel_pull_offloads(skb))
140 		return false;
141 
142 	return true;
143 }
144 
advance_nextseg(struct ipv6_sr_hdr * srh,struct in6_addr * daddr)145 static void advance_nextseg(struct ipv6_sr_hdr *srh, struct in6_addr *daddr)
146 {
147 	struct in6_addr *addr;
148 
149 	srh->segments_left--;
150 	addr = srh->segments + srh->segments_left;
151 	*daddr = *addr;
152 }
153 
seg6_lookup_nexthop(struct sk_buff * skb,struct in6_addr * nhaddr,u32 tbl_id)154 int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
155 			u32 tbl_id)
156 {
157 	struct net *net = dev_net(skb->dev);
158 	struct ipv6hdr *hdr = ipv6_hdr(skb);
159 	int flags = RT6_LOOKUP_F_HAS_SADDR;
160 	struct dst_entry *dst = NULL;
161 	struct rt6_info *rt;
162 	struct flowi6 fl6;
163 
164 	fl6.flowi6_iif = skb->dev->ifindex;
165 	fl6.daddr = nhaddr ? *nhaddr : hdr->daddr;
166 	fl6.saddr = hdr->saddr;
167 	fl6.flowlabel = ip6_flowinfo(hdr);
168 	fl6.flowi6_mark = skb->mark;
169 	fl6.flowi6_proto = hdr->nexthdr;
170 
171 	if (nhaddr)
172 		fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;
173 
174 	if (!tbl_id) {
175 		dst = ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags);
176 	} else {
177 		struct fib6_table *table;
178 
179 		table = fib6_get_table(net, tbl_id);
180 		if (!table)
181 			goto out;
182 
183 		rt = ip6_pol_route(net, table, 0, &fl6, skb, flags);
184 		dst = &rt->dst;
185 	}
186 
187 	if (dst && dst->dev->flags & IFF_LOOPBACK && !dst->error) {
188 		dst_release(dst);
189 		dst = NULL;
190 	}
191 
192 out:
193 	if (!dst) {
194 		rt = net->ipv6.ip6_blk_hole_entry;
195 		dst = &rt->dst;
196 		dst_hold(dst);
197 	}
198 
199 	skb_dst_drop(skb);
200 	skb_dst_set(skb, dst);
201 	return dst->error;
202 }
203 
204 /* regular endpoint function */
input_action_end(struct sk_buff * skb,struct seg6_local_lwt * slwt)205 static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt)
206 {
207 	struct ipv6_sr_hdr *srh;
208 
209 	srh = get_and_validate_srh(skb);
210 	if (!srh)
211 		goto drop;
212 
213 	advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
214 
215 	seg6_lookup_nexthop(skb, NULL, 0);
216 
217 	return dst_input(skb);
218 
219 drop:
220 	kfree_skb(skb);
221 	return -EINVAL;
222 }
223 
224 /* regular endpoint, and forward to specified nexthop */
input_action_end_x(struct sk_buff * skb,struct seg6_local_lwt * slwt)225 static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt)
226 {
227 	struct ipv6_sr_hdr *srh;
228 
229 	srh = get_and_validate_srh(skb);
230 	if (!srh)
231 		goto drop;
232 
233 	advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
234 
235 	seg6_lookup_nexthop(skb, &slwt->nh6, 0);
236 
237 	return dst_input(skb);
238 
239 drop:
240 	kfree_skb(skb);
241 	return -EINVAL;
242 }
243 
input_action_end_t(struct sk_buff * skb,struct seg6_local_lwt * slwt)244 static int input_action_end_t(struct sk_buff *skb, struct seg6_local_lwt *slwt)
245 {
246 	struct ipv6_sr_hdr *srh;
247 
248 	srh = get_and_validate_srh(skb);
249 	if (!srh)
250 		goto drop;
251 
252 	advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
253 
254 	seg6_lookup_nexthop(skb, NULL, slwt->table);
255 
256 	return dst_input(skb);
257 
258 drop:
259 	kfree_skb(skb);
260 	return -EINVAL;
261 }
262 
263 /* decapsulate and forward inner L2 frame on specified interface */
input_action_end_dx2(struct sk_buff * skb,struct seg6_local_lwt * slwt)264 static int input_action_end_dx2(struct sk_buff *skb,
265 				struct seg6_local_lwt *slwt)
266 {
267 	struct net *net = dev_net(skb->dev);
268 	struct net_device *odev;
269 	struct ethhdr *eth;
270 
271 	if (!decap_and_validate(skb, NEXTHDR_NONE))
272 		goto drop;
273 
274 	if (!pskb_may_pull(skb, ETH_HLEN))
275 		goto drop;
276 
277 	skb_reset_mac_header(skb);
278 	eth = (struct ethhdr *)skb->data;
279 
280 	/* To determine the frame's protocol, we assume it is 802.3. This avoids
281 	 * a call to eth_type_trans(), which is not really relevant for our
282 	 * use case.
283 	 */
284 	if (!eth_proto_is_802_3(eth->h_proto))
285 		goto drop;
286 
287 	odev = dev_get_by_index_rcu(net, slwt->oif);
288 	if (!odev)
289 		goto drop;
290 
291 	/* As we accept Ethernet frames, make sure the egress device is of
292 	 * the correct type.
293 	 */
294 	if (odev->type != ARPHRD_ETHER)
295 		goto drop;
296 
297 	if (!(odev->flags & IFF_UP) || !netif_carrier_ok(odev))
298 		goto drop;
299 
300 	skb_orphan(skb);
301 
302 	if (skb_warn_if_lro(skb))
303 		goto drop;
304 
305 	skb_forward_csum(skb);
306 
307 	if (skb->len - ETH_HLEN > odev->mtu)
308 		goto drop;
309 
310 	skb->dev = odev;
311 	skb->protocol = eth->h_proto;
312 
313 	return dev_queue_xmit(skb);
314 
315 drop:
316 	kfree_skb(skb);
317 	return -EINVAL;
318 }
319 
320 /* decapsulate and forward to specified nexthop */
input_action_end_dx6(struct sk_buff * skb,struct seg6_local_lwt * slwt)321 static int input_action_end_dx6(struct sk_buff *skb,
322 				struct seg6_local_lwt *slwt)
323 {
324 	struct in6_addr *nhaddr = NULL;
325 
326 	/* this function accepts IPv6 encapsulated packets, with either
327 	 * an SRH with SL=0, or no SRH.
328 	 */
329 
330 	if (!decap_and_validate(skb, IPPROTO_IPV6))
331 		goto drop;
332 
333 	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
334 		goto drop;
335 
336 	/* The inner packet is not associated to any local interface,
337 	 * so we do not call netif_rx().
338 	 *
339 	 * If slwt->nh6 is set to ::, then lookup the nexthop for the
340 	 * inner packet's DA. Otherwise, use the specified nexthop.
341 	 */
342 
343 	if (!ipv6_addr_any(&slwt->nh6))
344 		nhaddr = &slwt->nh6;
345 
346 	skb_set_transport_header(skb, sizeof(struct ipv6hdr));
347 
348 	seg6_lookup_nexthop(skb, nhaddr, 0);
349 
350 	return dst_input(skb);
351 drop:
352 	kfree_skb(skb);
353 	return -EINVAL;
354 }
355 
input_action_end_dx4(struct sk_buff * skb,struct seg6_local_lwt * slwt)356 static int input_action_end_dx4(struct sk_buff *skb,
357 				struct seg6_local_lwt *slwt)
358 {
359 	struct iphdr *iph;
360 	__be32 nhaddr;
361 	int err;
362 
363 	if (!decap_and_validate(skb, IPPROTO_IPIP))
364 		goto drop;
365 
366 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
367 		goto drop;
368 
369 	skb->protocol = htons(ETH_P_IP);
370 
371 	iph = ip_hdr(skb);
372 
373 	nhaddr = slwt->nh4.s_addr ?: iph->daddr;
374 
375 	skb_dst_drop(skb);
376 
377 	skb_set_transport_header(skb, sizeof(struct iphdr));
378 
379 	err = ip_route_input(skb, nhaddr, iph->saddr, 0, skb->dev);
380 	if (err)
381 		goto drop;
382 
383 	return dst_input(skb);
384 
385 drop:
386 	kfree_skb(skb);
387 	return -EINVAL;
388 }
389 
input_action_end_dt6(struct sk_buff * skb,struct seg6_local_lwt * slwt)390 static int input_action_end_dt6(struct sk_buff *skb,
391 				struct seg6_local_lwt *slwt)
392 {
393 	if (!decap_and_validate(skb, IPPROTO_IPV6))
394 		goto drop;
395 
396 	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
397 		goto drop;
398 
399 	skb_set_transport_header(skb, sizeof(struct ipv6hdr));
400 
401 	seg6_lookup_nexthop(skb, NULL, slwt->table);
402 
403 	return dst_input(skb);
404 
405 drop:
406 	kfree_skb(skb);
407 	return -EINVAL;
408 }
409 
410 /* push an SRH on top of the current one */
input_action_end_b6(struct sk_buff * skb,struct seg6_local_lwt * slwt)411 static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
412 {
413 	struct ipv6_sr_hdr *srh;
414 	int err = -EINVAL;
415 
416 	srh = get_and_validate_srh(skb);
417 	if (!srh)
418 		goto drop;
419 
420 	err = seg6_do_srh_inline(skb, slwt->srh);
421 	if (err)
422 		goto drop;
423 
424 	ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
425 	skb_set_transport_header(skb, sizeof(struct ipv6hdr));
426 
427 	seg6_lookup_nexthop(skb, NULL, 0);
428 
429 	return dst_input(skb);
430 
431 drop:
432 	kfree_skb(skb);
433 	return err;
434 }
435 
436 /* encapsulate within an outer IPv6 header and a specified SRH */
input_action_end_b6_encap(struct sk_buff * skb,struct seg6_local_lwt * slwt)437 static int input_action_end_b6_encap(struct sk_buff *skb,
438 				     struct seg6_local_lwt *slwt)
439 {
440 	struct ipv6_sr_hdr *srh;
441 	int err = -EINVAL;
442 
443 	srh = get_and_validate_srh(skb);
444 	if (!srh)
445 		goto drop;
446 
447 	advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
448 
449 	skb_reset_inner_headers(skb);
450 	skb->encapsulation = 1;
451 
452 	err = seg6_do_srh_encap(skb, slwt->srh, IPPROTO_IPV6);
453 	if (err)
454 		goto drop;
455 
456 	ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
457 	skb_set_transport_header(skb, sizeof(struct ipv6hdr));
458 
459 	seg6_lookup_nexthop(skb, NULL, 0);
460 
461 	return dst_input(skb);
462 
463 drop:
464 	kfree_skb(skb);
465 	return err;
466 }
467 
468 DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states);
469 
seg6_bpf_has_valid_srh(struct sk_buff * skb)470 bool seg6_bpf_has_valid_srh(struct sk_buff *skb)
471 {
472 	struct seg6_bpf_srh_state *srh_state =
473 		this_cpu_ptr(&seg6_bpf_srh_states);
474 	struct ipv6_sr_hdr *srh = srh_state->srh;
475 
476 	if (unlikely(srh == NULL))
477 		return false;
478 
479 	if (unlikely(!srh_state->valid)) {
480 		if ((srh_state->hdrlen & 7) != 0)
481 			return false;
482 
483 		srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
484 		if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3))
485 			return false;
486 
487 		srh_state->valid = true;
488 	}
489 
490 	return true;
491 }
492 
input_action_end_bpf(struct sk_buff * skb,struct seg6_local_lwt * slwt)493 static int input_action_end_bpf(struct sk_buff *skb,
494 				struct seg6_local_lwt *slwt)
495 {
496 	struct seg6_bpf_srh_state *srh_state =
497 		this_cpu_ptr(&seg6_bpf_srh_states);
498 	struct ipv6_sr_hdr *srh;
499 	int ret;
500 
501 	srh = get_and_validate_srh(skb);
502 	if (!srh) {
503 		kfree_skb(skb);
504 		return -EINVAL;
505 	}
506 	advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
507 
508 	/* preempt_disable is needed to protect the per-CPU buffer srh_state,
509 	 * which is also accessed by the bpf_lwt_seg6_* helpers
510 	 */
511 	preempt_disable();
512 	srh_state->srh = srh;
513 	srh_state->hdrlen = srh->hdrlen << 3;
514 	srh_state->valid = true;
515 
516 	rcu_read_lock();
517 	bpf_compute_data_pointers(skb);
518 	ret = bpf_prog_run_save_cb(slwt->bpf.prog, skb);
519 	rcu_read_unlock();
520 
521 	switch (ret) {
522 	case BPF_OK:
523 	case BPF_REDIRECT:
524 		break;
525 	case BPF_DROP:
526 		goto drop;
527 	default:
528 		pr_warn_once("bpf-seg6local: Illegal return value %u\n", ret);
529 		goto drop;
530 	}
531 
532 	if (srh_state->srh && !seg6_bpf_has_valid_srh(skb))
533 		goto drop;
534 
535 	preempt_enable();
536 	if (ret != BPF_REDIRECT)
537 		seg6_lookup_nexthop(skb, NULL, 0);
538 
539 	return dst_input(skb);
540 
541 drop:
542 	preempt_enable();
543 	kfree_skb(skb);
544 	return -EINVAL;
545 }
546 
547 static struct seg6_action_desc seg6_action_table[] = {
548 	{
549 		.action		= SEG6_LOCAL_ACTION_END,
550 		.attrs		= 0,
551 		.input		= input_action_end,
552 	},
553 	{
554 		.action		= SEG6_LOCAL_ACTION_END_X,
555 		.attrs		= (1 << SEG6_LOCAL_NH6),
556 		.input		= input_action_end_x,
557 	},
558 	{
559 		.action		= SEG6_LOCAL_ACTION_END_T,
560 		.attrs		= (1 << SEG6_LOCAL_TABLE),
561 		.input		= input_action_end_t,
562 	},
563 	{
564 		.action		= SEG6_LOCAL_ACTION_END_DX2,
565 		.attrs		= (1 << SEG6_LOCAL_OIF),
566 		.input		= input_action_end_dx2,
567 	},
568 	{
569 		.action		= SEG6_LOCAL_ACTION_END_DX6,
570 		.attrs		= (1 << SEG6_LOCAL_NH6),
571 		.input		= input_action_end_dx6,
572 	},
573 	{
574 		.action		= SEG6_LOCAL_ACTION_END_DX4,
575 		.attrs		= (1 << SEG6_LOCAL_NH4),
576 		.input		= input_action_end_dx4,
577 	},
578 	{
579 		.action		= SEG6_LOCAL_ACTION_END_DT6,
580 		.attrs		= (1 << SEG6_LOCAL_TABLE),
581 		.input		= input_action_end_dt6,
582 	},
583 	{
584 		.action		= SEG6_LOCAL_ACTION_END_B6,
585 		.attrs		= (1 << SEG6_LOCAL_SRH),
586 		.input		= input_action_end_b6,
587 	},
588 	{
589 		.action		= SEG6_LOCAL_ACTION_END_B6_ENCAP,
590 		.attrs		= (1 << SEG6_LOCAL_SRH),
591 		.input		= input_action_end_b6_encap,
592 		.static_headroom	= sizeof(struct ipv6hdr),
593 	},
594 	{
595 		.action		= SEG6_LOCAL_ACTION_END_BPF,
596 		.attrs		= (1 << SEG6_LOCAL_BPF),
597 		.input		= input_action_end_bpf,
598 	},
599 
600 };
601 
__get_action_desc(int action)602 static struct seg6_action_desc *__get_action_desc(int action)
603 {
604 	struct seg6_action_desc *desc;
605 	int i, count;
606 
607 	count = ARRAY_SIZE(seg6_action_table);
608 	for (i = 0; i < count; i++) {
609 		desc = &seg6_action_table[i];
610 		if (desc->action == action)
611 			return desc;
612 	}
613 
614 	return NULL;
615 }
616 
seg6_local_input(struct sk_buff * skb)617 static int seg6_local_input(struct sk_buff *skb)
618 {
619 	struct dst_entry *orig_dst = skb_dst(skb);
620 	struct seg6_action_desc *desc;
621 	struct seg6_local_lwt *slwt;
622 
623 	if (skb->protocol != htons(ETH_P_IPV6)) {
624 		kfree_skb(skb);
625 		return -EINVAL;
626 	}
627 
628 	slwt = seg6_local_lwtunnel(orig_dst->lwtstate);
629 	desc = slwt->desc;
630 
631 	return desc->input(skb, slwt);
632 }
633 
634 static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = {
635 	[SEG6_LOCAL_ACTION]	= { .type = NLA_U32 },
636 	[SEG6_LOCAL_SRH]	= { .type = NLA_BINARY },
637 	[SEG6_LOCAL_TABLE]	= { .type = NLA_U32 },
638 	[SEG6_LOCAL_NH4]	= { .type = NLA_BINARY,
639 				    .len = sizeof(struct in_addr) },
640 	[SEG6_LOCAL_NH6]	= { .type = NLA_BINARY,
641 				    .len = sizeof(struct in6_addr) },
642 	[SEG6_LOCAL_IIF]	= { .type = NLA_U32 },
643 	[SEG6_LOCAL_OIF]	= { .type = NLA_U32 },
644 	[SEG6_LOCAL_BPF]	= { .type = NLA_NESTED },
645 };
646 
parse_nla_srh(struct nlattr ** attrs,struct seg6_local_lwt * slwt)647 static int parse_nla_srh(struct nlattr **attrs, struct seg6_local_lwt *slwt)
648 {
649 	struct ipv6_sr_hdr *srh;
650 	int len;
651 
652 	srh = nla_data(attrs[SEG6_LOCAL_SRH]);
653 	len = nla_len(attrs[SEG6_LOCAL_SRH]);
654 
655 	/* SRH must contain at least one segment */
656 	if (len < sizeof(*srh) + sizeof(struct in6_addr))
657 		return -EINVAL;
658 
659 	if (!seg6_validate_srh(srh, len))
660 		return -EINVAL;
661 
662 	slwt->srh = kmemdup(srh, len, GFP_KERNEL);
663 	if (!slwt->srh)
664 		return -ENOMEM;
665 
666 	slwt->headroom += len;
667 
668 	return 0;
669 }
670 
put_nla_srh(struct sk_buff * skb,struct seg6_local_lwt * slwt)671 static int put_nla_srh(struct sk_buff *skb, struct seg6_local_lwt *slwt)
672 {
673 	struct ipv6_sr_hdr *srh;
674 	struct nlattr *nla;
675 	int len;
676 
677 	srh = slwt->srh;
678 	len = (srh->hdrlen + 1) << 3;
679 
680 	nla = nla_reserve(skb, SEG6_LOCAL_SRH, len);
681 	if (!nla)
682 		return -EMSGSIZE;
683 
684 	memcpy(nla_data(nla), srh, len);
685 
686 	return 0;
687 }
688 
cmp_nla_srh(struct seg6_local_lwt * a,struct seg6_local_lwt * b)689 static int cmp_nla_srh(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
690 {
691 	int len = (a->srh->hdrlen + 1) << 3;
692 
693 	if (len != ((b->srh->hdrlen + 1) << 3))
694 		return 1;
695 
696 	return memcmp(a->srh, b->srh, len);
697 }
698 
parse_nla_table(struct nlattr ** attrs,struct seg6_local_lwt * slwt)699 static int parse_nla_table(struct nlattr **attrs, struct seg6_local_lwt *slwt)
700 {
701 	slwt->table = nla_get_u32(attrs[SEG6_LOCAL_TABLE]);
702 
703 	return 0;
704 }
705 
put_nla_table(struct sk_buff * skb,struct seg6_local_lwt * slwt)706 static int put_nla_table(struct sk_buff *skb, struct seg6_local_lwt *slwt)
707 {
708 	if (nla_put_u32(skb, SEG6_LOCAL_TABLE, slwt->table))
709 		return -EMSGSIZE;
710 
711 	return 0;
712 }
713 
cmp_nla_table(struct seg6_local_lwt * a,struct seg6_local_lwt * b)714 static int cmp_nla_table(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
715 {
716 	if (a->table != b->table)
717 		return 1;
718 
719 	return 0;
720 }
721 
parse_nla_nh4(struct nlattr ** attrs,struct seg6_local_lwt * slwt)722 static int parse_nla_nh4(struct nlattr **attrs, struct seg6_local_lwt *slwt)
723 {
724 	memcpy(&slwt->nh4, nla_data(attrs[SEG6_LOCAL_NH4]),
725 	       sizeof(struct in_addr));
726 
727 	return 0;
728 }
729 
put_nla_nh4(struct sk_buff * skb,struct seg6_local_lwt * slwt)730 static int put_nla_nh4(struct sk_buff *skb, struct seg6_local_lwt *slwt)
731 {
732 	struct nlattr *nla;
733 
734 	nla = nla_reserve(skb, SEG6_LOCAL_NH4, sizeof(struct in_addr));
735 	if (!nla)
736 		return -EMSGSIZE;
737 
738 	memcpy(nla_data(nla), &slwt->nh4, sizeof(struct in_addr));
739 
740 	return 0;
741 }
742 
cmp_nla_nh4(struct seg6_local_lwt * a,struct seg6_local_lwt * b)743 static int cmp_nla_nh4(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
744 {
745 	return memcmp(&a->nh4, &b->nh4, sizeof(struct in_addr));
746 }
747 
parse_nla_nh6(struct nlattr ** attrs,struct seg6_local_lwt * slwt)748 static int parse_nla_nh6(struct nlattr **attrs, struct seg6_local_lwt *slwt)
749 {
750 	memcpy(&slwt->nh6, nla_data(attrs[SEG6_LOCAL_NH6]),
751 	       sizeof(struct in6_addr));
752 
753 	return 0;
754 }
755 
put_nla_nh6(struct sk_buff * skb,struct seg6_local_lwt * slwt)756 static int put_nla_nh6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
757 {
758 	struct nlattr *nla;
759 
760 	nla = nla_reserve(skb, SEG6_LOCAL_NH6, sizeof(struct in6_addr));
761 	if (!nla)
762 		return -EMSGSIZE;
763 
764 	memcpy(nla_data(nla), &slwt->nh6, sizeof(struct in6_addr));
765 
766 	return 0;
767 }
768 
cmp_nla_nh6(struct seg6_local_lwt * a,struct seg6_local_lwt * b)769 static int cmp_nla_nh6(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
770 {
771 	return memcmp(&a->nh6, &b->nh6, sizeof(struct in6_addr));
772 }
773 
parse_nla_iif(struct nlattr ** attrs,struct seg6_local_lwt * slwt)774 static int parse_nla_iif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
775 {
776 	slwt->iif = nla_get_u32(attrs[SEG6_LOCAL_IIF]);
777 
778 	return 0;
779 }
780 
put_nla_iif(struct sk_buff * skb,struct seg6_local_lwt * slwt)781 static int put_nla_iif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
782 {
783 	if (nla_put_u32(skb, SEG6_LOCAL_IIF, slwt->iif))
784 		return -EMSGSIZE;
785 
786 	return 0;
787 }
788 
cmp_nla_iif(struct seg6_local_lwt * a,struct seg6_local_lwt * b)789 static int cmp_nla_iif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
790 {
791 	if (a->iif != b->iif)
792 		return 1;
793 
794 	return 0;
795 }
796 
parse_nla_oif(struct nlattr ** attrs,struct seg6_local_lwt * slwt)797 static int parse_nla_oif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
798 {
799 	slwt->oif = nla_get_u32(attrs[SEG6_LOCAL_OIF]);
800 
801 	return 0;
802 }
803 
put_nla_oif(struct sk_buff * skb,struct seg6_local_lwt * slwt)804 static int put_nla_oif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
805 {
806 	if (nla_put_u32(skb, SEG6_LOCAL_OIF, slwt->oif))
807 		return -EMSGSIZE;
808 
809 	return 0;
810 }
811 
cmp_nla_oif(struct seg6_local_lwt * a,struct seg6_local_lwt * b)812 static int cmp_nla_oif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
813 {
814 	if (a->oif != b->oif)
815 		return 1;
816 
817 	return 0;
818 }
819 
820 #define MAX_PROG_NAME 256
821 static const struct nla_policy bpf_prog_policy[SEG6_LOCAL_BPF_PROG_MAX + 1] = {
822 	[SEG6_LOCAL_BPF_PROG]	   = { .type = NLA_U32, },
823 	[SEG6_LOCAL_BPF_PROG_NAME] = { .type = NLA_NUL_STRING,
824 				       .len = MAX_PROG_NAME },
825 };
826 
parse_nla_bpf(struct nlattr ** attrs,struct seg6_local_lwt * slwt)827 static int parse_nla_bpf(struct nlattr **attrs, struct seg6_local_lwt *slwt)
828 {
829 	struct nlattr *tb[SEG6_LOCAL_BPF_PROG_MAX + 1];
830 	struct bpf_prog *p;
831 	int ret;
832 	u32 fd;
833 
834 	ret = nla_parse_nested_deprecated(tb, SEG6_LOCAL_BPF_PROG_MAX,
835 					  attrs[SEG6_LOCAL_BPF],
836 					  bpf_prog_policy, NULL);
837 	if (ret < 0)
838 		return ret;
839 
840 	if (!tb[SEG6_LOCAL_BPF_PROG] || !tb[SEG6_LOCAL_BPF_PROG_NAME])
841 		return -EINVAL;
842 
843 	slwt->bpf.name = nla_memdup(tb[SEG6_LOCAL_BPF_PROG_NAME], GFP_KERNEL);
844 	if (!slwt->bpf.name)
845 		return -ENOMEM;
846 
847 	fd = nla_get_u32(tb[SEG6_LOCAL_BPF_PROG]);
848 	p = bpf_prog_get_type(fd, BPF_PROG_TYPE_LWT_SEG6LOCAL);
849 	if (IS_ERR(p)) {
850 		kfree(slwt->bpf.name);
851 		return PTR_ERR(p);
852 	}
853 
854 	slwt->bpf.prog = p;
855 	return 0;
856 }
857 
put_nla_bpf(struct sk_buff * skb,struct seg6_local_lwt * slwt)858 static int put_nla_bpf(struct sk_buff *skb, struct seg6_local_lwt *slwt)
859 {
860 	struct nlattr *nest;
861 
862 	if (!slwt->bpf.prog)
863 		return 0;
864 
865 	nest = nla_nest_start_noflag(skb, SEG6_LOCAL_BPF);
866 	if (!nest)
867 		return -EMSGSIZE;
868 
869 	if (nla_put_u32(skb, SEG6_LOCAL_BPF_PROG, slwt->bpf.prog->aux->id))
870 		return -EMSGSIZE;
871 
872 	if (slwt->bpf.name &&
873 	    nla_put_string(skb, SEG6_LOCAL_BPF_PROG_NAME, slwt->bpf.name))
874 		return -EMSGSIZE;
875 
876 	return nla_nest_end(skb, nest);
877 }
878 
cmp_nla_bpf(struct seg6_local_lwt * a,struct seg6_local_lwt * b)879 static int cmp_nla_bpf(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
880 {
881 	if (!a->bpf.name && !b->bpf.name)
882 		return 0;
883 
884 	if (!a->bpf.name || !b->bpf.name)
885 		return 1;
886 
887 	return strcmp(a->bpf.name, b->bpf.name);
888 }
889 
890 struct seg6_action_param {
891 	int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt);
892 	int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
893 	int (*cmp)(struct seg6_local_lwt *a, struct seg6_local_lwt *b);
894 };
895 
896 static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = {
897 	[SEG6_LOCAL_SRH]	= { .parse = parse_nla_srh,
898 				    .put = put_nla_srh,
899 				    .cmp = cmp_nla_srh },
900 
901 	[SEG6_LOCAL_TABLE]	= { .parse = parse_nla_table,
902 				    .put = put_nla_table,
903 				    .cmp = cmp_nla_table },
904 
905 	[SEG6_LOCAL_NH4]	= { .parse = parse_nla_nh4,
906 				    .put = put_nla_nh4,
907 				    .cmp = cmp_nla_nh4 },
908 
909 	[SEG6_LOCAL_NH6]	= { .parse = parse_nla_nh6,
910 				    .put = put_nla_nh6,
911 				    .cmp = cmp_nla_nh6 },
912 
913 	[SEG6_LOCAL_IIF]	= { .parse = parse_nla_iif,
914 				    .put = put_nla_iif,
915 				    .cmp = cmp_nla_iif },
916 
917 	[SEG6_LOCAL_OIF]	= { .parse = parse_nla_oif,
918 				    .put = put_nla_oif,
919 				    .cmp = cmp_nla_oif },
920 
921 	[SEG6_LOCAL_BPF]	= { .parse = parse_nla_bpf,
922 				    .put = put_nla_bpf,
923 				    .cmp = cmp_nla_bpf },
924 
925 };
926 
parse_nla_action(struct nlattr ** attrs,struct seg6_local_lwt * slwt)927 static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)
928 {
929 	struct seg6_action_param *param;
930 	struct seg6_action_desc *desc;
931 	int i, err;
932 
933 	desc = __get_action_desc(slwt->action);
934 	if (!desc)
935 		return -EINVAL;
936 
937 	if (!desc->input)
938 		return -EOPNOTSUPP;
939 
940 	slwt->desc = desc;
941 	slwt->headroom += desc->static_headroom;
942 
943 	for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
944 		if (desc->attrs & (1 << i)) {
945 			if (!attrs[i])
946 				return -EINVAL;
947 
948 			param = &seg6_action_params[i];
949 
950 			err = param->parse(attrs, slwt);
951 			if (err < 0)
952 				return err;
953 		}
954 	}
955 
956 	return 0;
957 }
958 
seg6_local_build_state(struct nlattr * nla,unsigned int family,const void * cfg,struct lwtunnel_state ** ts,struct netlink_ext_ack * extack)959 static int seg6_local_build_state(struct nlattr *nla, unsigned int family,
960 				  const void *cfg, struct lwtunnel_state **ts,
961 				  struct netlink_ext_ack *extack)
962 {
963 	struct nlattr *tb[SEG6_LOCAL_MAX + 1];
964 	struct lwtunnel_state *newts;
965 	struct seg6_local_lwt *slwt;
966 	int err;
967 
968 	if (family != AF_INET6)
969 		return -EINVAL;
970 
971 	err = nla_parse_nested_deprecated(tb, SEG6_LOCAL_MAX, nla,
972 					  seg6_local_policy, extack);
973 
974 	if (err < 0)
975 		return err;
976 
977 	if (!tb[SEG6_LOCAL_ACTION])
978 		return -EINVAL;
979 
980 	newts = lwtunnel_state_alloc(sizeof(*slwt));
981 	if (!newts)
982 		return -ENOMEM;
983 
984 	slwt = seg6_local_lwtunnel(newts);
985 	slwt->action = nla_get_u32(tb[SEG6_LOCAL_ACTION]);
986 
987 	err = parse_nla_action(tb, slwt);
988 	if (err < 0)
989 		goto out_free;
990 
991 	newts->type = LWTUNNEL_ENCAP_SEG6_LOCAL;
992 	newts->flags = LWTUNNEL_STATE_INPUT_REDIRECT;
993 	newts->headroom = slwt->headroom;
994 
995 	*ts = newts;
996 
997 	return 0;
998 
999 out_free:
1000 	kfree(slwt->srh);
1001 	kfree(newts);
1002 	return err;
1003 }
1004 
seg6_local_destroy_state(struct lwtunnel_state * lwt)1005 static void seg6_local_destroy_state(struct lwtunnel_state *lwt)
1006 {
1007 	struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
1008 
1009 	kfree(slwt->srh);
1010 
1011 	if (slwt->desc->attrs & (1 << SEG6_LOCAL_BPF)) {
1012 		kfree(slwt->bpf.name);
1013 		bpf_prog_put(slwt->bpf.prog);
1014 	}
1015 
1016 	return;
1017 }
1018 
seg6_local_fill_encap(struct sk_buff * skb,struct lwtunnel_state * lwt)1019 static int seg6_local_fill_encap(struct sk_buff *skb,
1020 				 struct lwtunnel_state *lwt)
1021 {
1022 	struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
1023 	struct seg6_action_param *param;
1024 	int i, err;
1025 
1026 	if (nla_put_u32(skb, SEG6_LOCAL_ACTION, slwt->action))
1027 		return -EMSGSIZE;
1028 
1029 	for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
1030 		if (slwt->desc->attrs & (1 << i)) {
1031 			param = &seg6_action_params[i];
1032 			err = param->put(skb, slwt);
1033 			if (err < 0)
1034 				return err;
1035 		}
1036 	}
1037 
1038 	return 0;
1039 }
1040 
seg6_local_get_encap_size(struct lwtunnel_state * lwt)1041 static int seg6_local_get_encap_size(struct lwtunnel_state *lwt)
1042 {
1043 	struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
1044 	unsigned long attrs;
1045 	int nlsize;
1046 
1047 	nlsize = nla_total_size(4); /* action */
1048 
1049 	attrs = slwt->desc->attrs;
1050 
1051 	if (attrs & (1 << SEG6_LOCAL_SRH))
1052 		nlsize += nla_total_size((slwt->srh->hdrlen + 1) << 3);
1053 
1054 	if (attrs & (1 << SEG6_LOCAL_TABLE))
1055 		nlsize += nla_total_size(4);
1056 
1057 	if (attrs & (1 << SEG6_LOCAL_NH4))
1058 		nlsize += nla_total_size(4);
1059 
1060 	if (attrs & (1 << SEG6_LOCAL_NH6))
1061 		nlsize += nla_total_size(16);
1062 
1063 	if (attrs & (1 << SEG6_LOCAL_IIF))
1064 		nlsize += nla_total_size(4);
1065 
1066 	if (attrs & (1 << SEG6_LOCAL_OIF))
1067 		nlsize += nla_total_size(4);
1068 
1069 	if (attrs & (1 << SEG6_LOCAL_BPF))
1070 		nlsize += nla_total_size(sizeof(struct nlattr)) +
1071 		       nla_total_size(MAX_PROG_NAME) +
1072 		       nla_total_size(4);
1073 
1074 	return nlsize;
1075 }
1076 
seg6_local_cmp_encap(struct lwtunnel_state * a,struct lwtunnel_state * b)1077 static int seg6_local_cmp_encap(struct lwtunnel_state *a,
1078 				struct lwtunnel_state *b)
1079 {
1080 	struct seg6_local_lwt *slwt_a, *slwt_b;
1081 	struct seg6_action_param *param;
1082 	int i;
1083 
1084 	slwt_a = seg6_local_lwtunnel(a);
1085 	slwt_b = seg6_local_lwtunnel(b);
1086 
1087 	if (slwt_a->action != slwt_b->action)
1088 		return 1;
1089 
1090 	if (slwt_a->desc->attrs != slwt_b->desc->attrs)
1091 		return 1;
1092 
1093 	for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
1094 		if (slwt_a->desc->attrs & (1 << i)) {
1095 			param = &seg6_action_params[i];
1096 			if (param->cmp(slwt_a, slwt_b))
1097 				return 1;
1098 		}
1099 	}
1100 
1101 	return 0;
1102 }
1103 
1104 static const struct lwtunnel_encap_ops seg6_local_ops = {
1105 	.build_state	= seg6_local_build_state,
1106 	.destroy_state	= seg6_local_destroy_state,
1107 	.input		= seg6_local_input,
1108 	.fill_encap	= seg6_local_fill_encap,
1109 	.get_encap_size	= seg6_local_get_encap_size,
1110 	.cmp_encap	= seg6_local_cmp_encap,
1111 	.owner		= THIS_MODULE,
1112 };
1113 
seg6_local_init(void)1114 int __init seg6_local_init(void)
1115 {
1116 	return lwtunnel_encap_add_ops(&seg6_local_ops,
1117 				      LWTUNNEL_ENCAP_SEG6_LOCAL);
1118 }
1119 
seg6_local_exit(void)1120 void seg6_local_exit(void)
1121 {
1122 	lwtunnel_encap_del_ops(&seg6_local_ops, LWTUNNEL_ENCAP_SEG6_LOCAL);
1123 }
1124