]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/iproute_lwtunnel.c
Merge branch 'iproute2-master' into iproute2-next
[mirror_iproute2.git] / ip / iproute_lwtunnel.c
1 /*
2 * iproute_lwtunnel.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Roopa Prabhu, <roopa@cumulusnetworks.com>
10 * Thomas Graf <tgraf@suug.ch>
11 *
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <string.h>
19 #include <linux/ila.h>
20 #include <linux/lwtunnel.h>
21 #include <linux/mpls_iptunnel.h>
22 #include <errno.h>
23
24 #include "rt_names.h"
25 #include "bpf_util.h"
26 #include "utils.h"
27 #include "ip_common.h"
28 #include "ila_common.h"
29
30 #include <linux/seg6.h>
31 #include <linux/seg6_iptunnel.h>
32 #include <linux/seg6_hmac.h>
33 #include <linux/seg6_local.h>
34 #include <net/if.h>
35
36 static const char *format_encap_type(int type)
37 {
38 switch (type) {
39 case LWTUNNEL_ENCAP_MPLS:
40 return "mpls";
41 case LWTUNNEL_ENCAP_IP:
42 return "ip";
43 case LWTUNNEL_ENCAP_IP6:
44 return "ip6";
45 case LWTUNNEL_ENCAP_ILA:
46 return "ila";
47 case LWTUNNEL_ENCAP_BPF:
48 return "bpf";
49 case LWTUNNEL_ENCAP_SEG6:
50 return "seg6";
51 case LWTUNNEL_ENCAP_SEG6_LOCAL:
52 return "seg6local";
53 default:
54 return "unknown";
55 }
56 }
57
58 static void encap_type_usage(void)
59 {
60 int i;
61
62 fprintf(stderr, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n");
63
64 for (i = 1; i <= LWTUNNEL_ENCAP_MAX; i++)
65 fprintf(stderr, "%s %s\n", format_encap_type(i),
66 i == 1 ? "TYPE := " : " ");
67
68 exit(-1);
69 }
70
71 static int read_encap_type(const char *name)
72 {
73 if (strcmp(name, "mpls") == 0)
74 return LWTUNNEL_ENCAP_MPLS;
75 else if (strcmp(name, "ip") == 0)
76 return LWTUNNEL_ENCAP_IP;
77 else if (strcmp(name, "ip6") == 0)
78 return LWTUNNEL_ENCAP_IP6;
79 else if (strcmp(name, "ila") == 0)
80 return LWTUNNEL_ENCAP_ILA;
81 else if (strcmp(name, "bpf") == 0)
82 return LWTUNNEL_ENCAP_BPF;
83 else if (strcmp(name, "seg6") == 0)
84 return LWTUNNEL_ENCAP_SEG6;
85 else if (strcmp(name, "seg6local") == 0)
86 return LWTUNNEL_ENCAP_SEG6_LOCAL;
87 else if (strcmp(name, "help") == 0)
88 encap_type_usage();
89
90 return LWTUNNEL_ENCAP_NONE;
91 }
92
93 static void print_srh(FILE *fp, struct ipv6_sr_hdr *srh)
94 {
95 int i;
96
97 if (is_json_context())
98 open_json_array(PRINT_JSON, "segs");
99 else
100 fprintf(fp, "segs %d [ ", srh->first_segment + 1);
101
102 for (i = srh->first_segment; i >= 0; i--)
103 print_color_string(PRINT_ANY, COLOR_INET6,
104 NULL, "%s ",
105 rt_addr_n2a(AF_INET6, 16, &srh->segments[i]));
106
107 if (is_json_context())
108 close_json_array(PRINT_JSON, NULL);
109 else
110 fprintf(fp, "] ");
111
112 if (sr_has_hmac(srh)) {
113 unsigned int offset = ((srh->hdrlen + 1) << 3) - 40;
114 struct sr6_tlv_hmac *tlv;
115
116 tlv = (struct sr6_tlv_hmac *)((char *)srh + offset);
117 print_0xhex(PRINT_ANY, "hmac",
118 "hmac 0x%X ", ntohl(tlv->hmackeyid));
119 }
120 }
121
122 static const char *seg6_mode_types[] = {
123 [SEG6_IPTUN_MODE_INLINE] = "inline",
124 [SEG6_IPTUN_MODE_ENCAP] = "encap",
125 [SEG6_IPTUN_MODE_L2ENCAP] = "l2encap",
126 };
127
128 static const char *format_seg6mode_type(int mode)
129 {
130 if (mode < 0 || mode > ARRAY_SIZE(seg6_mode_types))
131 return "<unknown>";
132
133 return seg6_mode_types[mode];
134 }
135
136 static int read_seg6mode_type(const char *mode)
137 {
138 int i;
139
140 for (i = 0; i < ARRAY_SIZE(seg6_mode_types); i++) {
141 if (strcmp(mode, seg6_mode_types[i]) == 0)
142 return i;
143 }
144
145 return -1;
146 }
147
148 static void print_encap_seg6(FILE *fp, struct rtattr *encap)
149 {
150 struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
151 struct seg6_iptunnel_encap *tuninfo;
152
153 parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap);
154
155 if (!tb[SEG6_IPTUNNEL_SRH])
156 return;
157
158 tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
159 print_string(PRINT_ANY, "mode",
160 "mode %s ", format_seg6mode_type(tuninfo->mode));
161
162 print_srh(fp, tuninfo->srh);
163 }
164
165 static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
166 [SEG6_LOCAL_ACTION_END] = "End",
167 [SEG6_LOCAL_ACTION_END_X] = "End.X",
168 [SEG6_LOCAL_ACTION_END_T] = "End.T",
169 [SEG6_LOCAL_ACTION_END_DX2] = "End.DX2",
170 [SEG6_LOCAL_ACTION_END_DX6] = "End.DX6",
171 [SEG6_LOCAL_ACTION_END_DX4] = "End.DX4",
172 [SEG6_LOCAL_ACTION_END_DT6] = "End.DT6",
173 [SEG6_LOCAL_ACTION_END_DT4] = "End.DT4",
174 [SEG6_LOCAL_ACTION_END_B6] = "End.B6",
175 [SEG6_LOCAL_ACTION_END_B6_ENCAP] = "End.B6.Encaps",
176 [SEG6_LOCAL_ACTION_END_BM] = "End.BM",
177 [SEG6_LOCAL_ACTION_END_S] = "End.S",
178 [SEG6_LOCAL_ACTION_END_AS] = "End.AS",
179 [SEG6_LOCAL_ACTION_END_AM] = "End.AM",
180 };
181
182 static const char *format_action_type(int action)
183 {
184 if (action < 0 || action > SEG6_LOCAL_ACTION_MAX)
185 return "<invalid>";
186
187 return seg6_action_names[action] ?: "<unknown>";
188 }
189
190 static int read_action_type(const char *name)
191 {
192 int i;
193
194 for (i = 0; i < SEG6_LOCAL_ACTION_MAX + 1; i++) {
195 if (!seg6_action_names[i])
196 continue;
197
198 if (strcmp(seg6_action_names[i], name) == 0)
199 return i;
200 }
201
202 return SEG6_LOCAL_ACTION_UNSPEC;
203 }
204
205 static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
206 {
207 struct rtattr *tb[SEG6_LOCAL_MAX + 1];
208 int action;
209
210 parse_rtattr_nested(tb, SEG6_LOCAL_MAX, encap);
211
212 if (!tb[SEG6_LOCAL_ACTION])
213 return;
214
215 action = rta_getattr_u32(tb[SEG6_LOCAL_ACTION]);
216
217 print_string(PRINT_ANY, "action",
218 "action %s ", format_action_type(action));
219
220 if (tb[SEG6_LOCAL_SRH]) {
221 open_json_object("srh");
222 print_srh(fp, RTA_DATA(tb[SEG6_LOCAL_SRH]));
223 close_json_object();
224 }
225
226 if (tb[SEG6_LOCAL_TABLE])
227 print_uint(PRINT_ANY, "table",
228 "table %u ", rta_getattr_u32(tb[SEG6_LOCAL_TABLE]));
229
230 if (tb[SEG6_LOCAL_NH4]) {
231 print_string(PRINT_ANY, "nh4",
232 "nh4 %s ", rt_addr_n2a_rta(AF_INET, tb[SEG6_LOCAL_NH4]));
233 }
234
235 if (tb[SEG6_LOCAL_NH6]) {
236 print_string(PRINT_ANY, "nh6",
237 "nh6 %s ", rt_addr_n2a_rta(AF_INET6, tb[SEG6_LOCAL_NH6]));
238 }
239
240 if (tb[SEG6_LOCAL_IIF]) {
241 int iif = rta_getattr_u32(tb[SEG6_LOCAL_IIF]);
242
243 print_string(PRINT_ANY, "iif",
244 "iif %s ", ll_index_to_name(iif));
245 }
246
247 if (tb[SEG6_LOCAL_OIF]) {
248 int oif = rta_getattr_u32(tb[SEG6_LOCAL_OIF]);
249
250 print_string(PRINT_ANY, "oif",
251 "oif %s ", ll_index_to_name(oif));
252 }
253 }
254
255 static void print_encap_mpls(FILE *fp, struct rtattr *encap)
256 {
257 struct rtattr *tb[MPLS_IPTUNNEL_MAX+1];
258
259 parse_rtattr_nested(tb, MPLS_IPTUNNEL_MAX, encap);
260
261 if (tb[MPLS_IPTUNNEL_DST])
262 print_string(PRINT_ANY, "dst", " %s ",
263 format_host_rta(AF_MPLS, tb[MPLS_IPTUNNEL_DST]));
264 if (tb[MPLS_IPTUNNEL_TTL])
265 print_uint(PRINT_ANY, "ttl", "ttl %u ",
266 rta_getattr_u8(tb[MPLS_IPTUNNEL_TTL]));
267 }
268
269 static void print_encap_ip(FILE *fp, struct rtattr *encap)
270 {
271 struct rtattr *tb[LWTUNNEL_IP_MAX+1];
272
273 parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
274
275 if (tb[LWTUNNEL_IP_ID])
276 print_uint(PRINT_ANY, "id", "id %llu ",
277 ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID])));
278
279 if (tb[LWTUNNEL_IP_SRC])
280 print_color_string(PRINT_ANY, COLOR_INET,
281 "src", "src %s ",
282 rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_SRC]));
283
284 if (tb[LWTUNNEL_IP_DST])
285 print_color_string(PRINT_ANY, COLOR_INET,
286 "dst", "dst %s ",
287 rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_DST]));
288
289 if (tb[LWTUNNEL_IP_TTL])
290 print_uint(PRINT_ANY, "ttl",
291 "ttl %u ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL]));
292
293 if (tb[LWTUNNEL_IP_TOS])
294 print_uint(PRINT_ANY, "tos",
295 "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
296 }
297
298 static void print_encap_ila(FILE *fp, struct rtattr *encap)
299 {
300 struct rtattr *tb[ILA_ATTR_MAX+1];
301
302 parse_rtattr_nested(tb, ILA_ATTR_MAX, encap);
303
304 if (tb[ILA_ATTR_LOCATOR]) {
305 char abuf[ADDR64_BUF_SIZE];
306
307 addr64_n2a(rta_getattr_u64(tb[ILA_ATTR_LOCATOR]),
308 abuf, sizeof(abuf));
309 print_string(PRINT_ANY, "locator",
310 " %s ", abuf);
311 }
312
313 if (tb[ILA_ATTR_CSUM_MODE])
314 print_string(PRINT_ANY, "csum_mode",
315 " csum-mode %s ",
316 ila_csum_mode2name(rta_getattr_u8(tb[ILA_ATTR_CSUM_MODE])));
317
318 if (tb[ILA_ATTR_IDENT_TYPE])
319 print_string(PRINT_ANY, "ident_type",
320 " ident-type %s ",
321 ila_ident_type2name(rta_getattr_u8(tb[ILA_ATTR_IDENT_TYPE])));
322
323 if (tb[ILA_ATTR_HOOK_TYPE])
324 print_string(PRINT_ANY, "hook_type",
325 " hook-type %s ",
326 ila_hook_type2name(rta_getattr_u8(tb[ILA_ATTR_HOOK_TYPE])));
327 }
328
329 static void print_encap_ip6(FILE *fp, struct rtattr *encap)
330 {
331 struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
332
333 parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
334
335 if (tb[LWTUNNEL_IP6_ID])
336 print_uint(PRINT_ANY, "id", "id %llu ",
337 ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID])));
338
339 if (tb[LWTUNNEL_IP6_SRC])
340 print_color_string(PRINT_ANY, COLOR_INET6,
341 "src", "src %s ",
342 rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_SRC]));
343
344 if (tb[LWTUNNEL_IP6_DST])
345 print_color_string(PRINT_ANY, COLOR_INET6,
346 "dst", "dst %s ",
347 rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_DST]));
348
349 if (tb[LWTUNNEL_IP6_HOPLIMIT])
350 print_uint(PRINT_ANY, "hoplimit",
351 "hoplimit %u ",
352 rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT]));
353
354 if (tb[LWTUNNEL_IP6_TC])
355 print_uint(PRINT_ANY, "tc",
356 "tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
357 }
358
359 static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
360 const char *str)
361 {
362 struct rtattr *tb[LWT_BPF_PROG_MAX+1];
363 const char *progname = NULL;
364
365 parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
366
367 if (tb[LWT_BPF_PROG_NAME])
368 progname = rta_getattr_str(tb[LWT_BPF_PROG_NAME]);
369
370 if (is_json_context())
371 print_string(PRINT_JSON, str, NULL,
372 progname ? : "<unknown>");
373 else {
374 fprintf(fp, "%s ", str);
375 if (progname)
376 fprintf(fp, "%s ", progname);
377 }
378 }
379
380 static void print_encap_bpf(FILE *fp, struct rtattr *encap)
381 {
382 struct rtattr *tb[LWT_BPF_MAX+1];
383
384 parse_rtattr_nested(tb, LWT_BPF_MAX, encap);
385
386 if (tb[LWT_BPF_IN])
387 print_encap_bpf_prog(fp, tb[LWT_BPF_IN], "in");
388 if (tb[LWT_BPF_OUT])
389 print_encap_bpf_prog(fp, tb[LWT_BPF_OUT], "out");
390 if (tb[LWT_BPF_XMIT])
391 print_encap_bpf_prog(fp, tb[LWT_BPF_XMIT], "xmit");
392 if (tb[LWT_BPF_XMIT_HEADROOM])
393 print_uint(PRINT_ANY, "headroom",
394 " %u ", rta_getattr_u32(tb[LWT_BPF_XMIT_HEADROOM]));
395 }
396
397 void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
398 struct rtattr *encap)
399 {
400 int et;
401
402 if (!encap_type)
403 return;
404
405 et = rta_getattr_u16(encap_type);
406
407 print_string(PRINT_ANY, "encap", " encap %s ", format_encap_type(et));
408
409 switch (et) {
410 case LWTUNNEL_ENCAP_MPLS:
411 print_encap_mpls(fp, encap);
412 break;
413 case LWTUNNEL_ENCAP_IP:
414 print_encap_ip(fp, encap);
415 break;
416 case LWTUNNEL_ENCAP_ILA:
417 print_encap_ila(fp, encap);
418 break;
419 case LWTUNNEL_ENCAP_IP6:
420 print_encap_ip6(fp, encap);
421 break;
422 case LWTUNNEL_ENCAP_BPF:
423 print_encap_bpf(fp, encap);
424 break;
425 case LWTUNNEL_ENCAP_SEG6:
426 print_encap_seg6(fp, encap);
427 break;
428 case LWTUNNEL_ENCAP_SEG6_LOCAL:
429 print_encap_seg6local(fp, encap);
430 break;
431 }
432 }
433
434 static struct ipv6_sr_hdr *parse_srh(char *segbuf, int hmac, bool encap)
435 {
436 struct ipv6_sr_hdr *srh;
437 int nsegs = 0;
438 int srhlen;
439 char *s;
440 int i;
441
442 s = segbuf;
443 for (i = 0; *s; *s++ == ',' ? i++ : *s);
444 nsegs = i + 1;
445
446 if (!encap)
447 nsegs++;
448
449 srhlen = 8 + 16*nsegs;
450
451 if (hmac)
452 srhlen += 40;
453
454 srh = malloc(srhlen);
455 memset(srh, 0, srhlen);
456
457 srh->hdrlen = (srhlen >> 3) - 1;
458 srh->type = 4;
459 srh->segments_left = nsegs - 1;
460 srh->first_segment = nsegs - 1;
461
462 if (hmac)
463 srh->flags |= SR6_FLAG1_HMAC;
464
465 i = srh->first_segment;
466 for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) {
467 inet_prefix addr;
468
469 get_addr(&addr, s, AF_INET6);
470 memcpy(&srh->segments[i], addr.data, sizeof(struct in6_addr));
471 i--;
472 }
473
474 if (hmac) {
475 struct sr6_tlv_hmac *tlv;
476
477 tlv = (struct sr6_tlv_hmac *)((char *)srh + srhlen - 40);
478 tlv->tlvhdr.type = SR6_TLV_HMAC;
479 tlv->tlvhdr.len = 38;
480 tlv->hmackeyid = htonl(hmac);
481 }
482
483 return srh;
484 }
485
486 static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
487 char ***argvp)
488 {
489 int mode_ok = 0, segs_ok = 0, hmac_ok = 0;
490 struct seg6_iptunnel_encap *tuninfo;
491 struct ipv6_sr_hdr *srh;
492 char **argv = *argvp;
493 char segbuf[1024];
494 int argc = *argcp;
495 int encap = -1;
496 __u32 hmac = 0;
497 int srhlen;
498
499 while (argc > 0) {
500 if (strcmp(*argv, "mode") == 0) {
501 NEXT_ARG();
502 if (mode_ok++)
503 duparg2("mode", *argv);
504 encap = read_seg6mode_type(*argv);
505 if (encap < 0)
506 invarg("\"mode\" value is invalid\n", *argv);
507 } else if (strcmp(*argv, "segs") == 0) {
508 NEXT_ARG();
509 if (segs_ok++)
510 duparg2("segs", *argv);
511 if (encap == -1)
512 invarg("\"segs\" provided before \"mode\"\n",
513 *argv);
514
515 strlcpy(segbuf, *argv, 1024);
516 } else if (strcmp(*argv, "hmac") == 0) {
517 NEXT_ARG();
518 if (hmac_ok++)
519 duparg2("hmac", *argv);
520 get_u32(&hmac, *argv, 0);
521 } else {
522 break;
523 }
524 argc--; argv++;
525 }
526
527 srh = parse_srh(segbuf, hmac, encap);
528 srhlen = (srh->hdrlen + 1) << 3;
529
530 tuninfo = malloc(sizeof(*tuninfo) + srhlen);
531 memset(tuninfo, 0, sizeof(*tuninfo) + srhlen);
532
533 tuninfo->mode = encap;
534
535 memcpy(tuninfo->srh, srh, srhlen);
536
537 rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo,
538 sizeof(*tuninfo) + srhlen);
539
540 free(tuninfo);
541 free(srh);
542
543 *argcp = argc + 1;
544 *argvp = argv - 1;
545
546 return 0;
547 }
548
549 static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
550 char ***argvp)
551 {
552 int segs_ok = 0, hmac_ok = 0, table_ok = 0, nh4_ok = 0, nh6_ok = 0;
553 int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0;
554 __u32 action = 0, table, iif, oif;
555 struct ipv6_sr_hdr *srh;
556 char **argv = *argvp;
557 int argc = *argcp;
558 char segbuf[1024];
559 inet_prefix addr;
560 __u32 hmac = 0;
561
562 while (argc > 0) {
563 if (strcmp(*argv, "action") == 0) {
564 NEXT_ARG();
565 if (action_ok++)
566 duparg2("action", *argv);
567 action = read_action_type(*argv);
568 if (!action)
569 invarg("\"action\" value is invalid\n", *argv);
570 rta_addattr32(rta, len, SEG6_LOCAL_ACTION, action);
571 } else if (strcmp(*argv, "table") == 0) {
572 NEXT_ARG();
573 if (table_ok++)
574 duparg2("table", *argv);
575 get_u32(&table, *argv, 0);
576 rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table);
577 } else if (strcmp(*argv, "nh4") == 0) {
578 NEXT_ARG();
579 if (nh4_ok++)
580 duparg2("nh4", *argv);
581 get_addr(&addr, *argv, AF_INET);
582 rta_addattr_l(rta, len, SEG6_LOCAL_NH4, &addr.data,
583 addr.bytelen);
584 } else if (strcmp(*argv, "nh6") == 0) {
585 NEXT_ARG();
586 if (nh6_ok++)
587 duparg2("nh6", *argv);
588 get_addr(&addr, *argv, AF_INET6);
589 rta_addattr_l(rta, len, SEG6_LOCAL_NH6, &addr.data,
590 addr.bytelen);
591 } else if (strcmp(*argv, "iif") == 0) {
592 NEXT_ARG();
593 if (iif_ok++)
594 duparg2("iif", *argv);
595 iif = ll_name_to_index(*argv);
596 if (!iif)
597 exit(nodev(*argv));
598 rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif);
599 } else if (strcmp(*argv, "oif") == 0) {
600 NEXT_ARG();
601 if (oif_ok++)
602 duparg2("oif", *argv);
603 oif = ll_name_to_index(*argv);
604 if (!oif)
605 exit(nodev(*argv));
606 rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif);
607 } else if (strcmp(*argv, "srh") == 0) {
608 NEXT_ARG();
609 if (srh_ok++)
610 duparg2("srh", *argv);
611 if (strcmp(*argv, "segs") != 0)
612 invarg("missing \"segs\" attribute for srh\n",
613 *argv);
614 NEXT_ARG();
615 if (segs_ok++)
616 duparg2("segs", *argv);
617 strncpy(segbuf, *argv, 1024);
618 segbuf[1023] = 0;
619 if (!NEXT_ARG_OK())
620 break;
621 NEXT_ARG();
622 if (strcmp(*argv, "hmac") == 0) {
623 NEXT_ARG();
624 if (hmac_ok++)
625 duparg2("hmac", *argv);
626 get_u32(&hmac, *argv, 0);
627 } else {
628 continue;
629 }
630 } else {
631 break;
632 }
633 argc--; argv++;
634 }
635
636 if (!action) {
637 fprintf(stderr, "Missing action type\n");
638 exit(-1);
639 }
640
641 if (srh_ok) {
642 int srhlen;
643
644 srh = parse_srh(segbuf, hmac,
645 action == SEG6_LOCAL_ACTION_END_B6_ENCAP);
646 srhlen = (srh->hdrlen + 1) << 3;
647 rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen);
648 free(srh);
649 }
650
651 *argcp = argc + 1;
652 *argvp = argv - 1;
653
654 return 0;
655 }
656
657 static int parse_encap_mpls(struct rtattr *rta, size_t len,
658 int *argcp, char ***argvp)
659 {
660 inet_prefix addr;
661 int argc = *argcp;
662 char **argv = *argvp;
663 int ttl_ok = 0;
664
665 if (get_addr(&addr, *argv, AF_MPLS)) {
666 fprintf(stderr,
667 "Error: an inet address is expected rather than \"%s\".\n",
668 *argv);
669 exit(1);
670 }
671
672 rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data,
673 addr.bytelen);
674
675 argc--;
676 argv++;
677
678 while (argc > 0) {
679 if (strcmp(*argv, "ttl") == 0) {
680 __u8 ttl;
681
682 NEXT_ARG();
683 if (ttl_ok++)
684 duparg2("ttl", *argv);
685 if (get_u8(&ttl, *argv, 0))
686 invarg("\"ttl\" value is invalid\n", *argv);
687 rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl);
688 } else {
689 break;
690 }
691 argc--; argv++;
692 }
693
694 /* argv is currently the first unparsed argument,
695 * but the lwt_parse_encap() caller will move to the next,
696 * so step back
697 */
698 *argcp = argc + 1;
699 *argvp = argv - 1;
700
701 return 0;
702 }
703
704 static int parse_encap_ip(struct rtattr *rta, size_t len,
705 int *argcp, char ***argvp)
706 {
707 int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0;
708 char **argv = *argvp;
709 int argc = *argcp;
710
711 while (argc > 0) {
712 if (strcmp(*argv, "id") == 0) {
713 __u64 id;
714
715 NEXT_ARG();
716 if (id_ok++)
717 duparg2("id", *argv);
718 if (get_be64(&id, *argv, 0))
719 invarg("\"id\" value is invalid\n", *argv);
720 rta_addattr64(rta, len, LWTUNNEL_IP_ID, id);
721 } else if (strcmp(*argv, "dst") == 0) {
722 inet_prefix addr;
723
724 NEXT_ARG();
725 if (dst_ok++)
726 duparg2("dst", *argv);
727 get_addr(&addr, *argv, AF_INET);
728 rta_addattr_l(rta, len, LWTUNNEL_IP_DST,
729 &addr.data, addr.bytelen);
730 } else if (strcmp(*argv, "tos") == 0) {
731 __u32 tos;
732
733 NEXT_ARG();
734 if (tos_ok++)
735 duparg2("tos", *argv);
736 if (rtnl_dsfield_a2n(&tos, *argv))
737 invarg("\"tos\" value is invalid\n", *argv);
738 rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos);
739 } else if (strcmp(*argv, "ttl") == 0) {
740 __u8 ttl;
741
742 NEXT_ARG();
743 if (ttl_ok++)
744 duparg2("ttl", *argv);
745 if (get_u8(&ttl, *argv, 0))
746 invarg("\"ttl\" value is invalid\n", *argv);
747 rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
748 } else {
749 break;
750 }
751 argc--; argv++;
752 }
753
754 /* argv is currently the first unparsed argument,
755 * but the lwt_parse_encap() caller will move to the next,
756 * so step back
757 */
758 *argcp = argc + 1;
759 *argvp = argv - 1;
760
761 return 0;
762 }
763
764 static int parse_encap_ila(struct rtattr *rta, size_t len,
765 int *argcp, char ***argvp)
766 {
767 __u64 locator;
768 int argc = *argcp;
769 char **argv = *argvp;
770
771 if (get_addr64(&locator, *argv) < 0) {
772 fprintf(stderr, "Bad locator: %s\n", *argv);
773 exit(1);
774 }
775
776 argc--; argv++;
777
778 rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator);
779
780 while (argc > 0) {
781 if (strcmp(*argv, "csum-mode") == 0) {
782 int csum_mode;
783
784 NEXT_ARG();
785
786 csum_mode = ila_csum_name2mode(*argv);
787 if (csum_mode < 0)
788 invarg("\"csum-mode\" value is invalid\n",
789 *argv);
790
791 rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE,
792 (__u8)csum_mode);
793
794 argc--; argv++;
795 } else if (strcmp(*argv, "ident-type") == 0) {
796 int ident_type;
797
798 NEXT_ARG();
799
800 ident_type = ila_ident_name2type(*argv);
801 if (ident_type < 0)
802 invarg("\"ident-type\" value is invalid\n",
803 *argv);
804
805 rta_addattr8(rta, 1024, ILA_ATTR_IDENT_TYPE,
806 (__u8)ident_type);
807
808 argc--; argv++;
809 } else if (strcmp(*argv, "hook-type") == 0) {
810 int hook_type;
811
812 NEXT_ARG();
813
814 hook_type = ila_hook_name2type(*argv);
815 if (hook_type < 0)
816 invarg("\"hook-type\" value is invalid\n",
817 *argv);
818
819 rta_addattr8(rta, 1024, ILA_ATTR_HOOK_TYPE,
820 (__u8)hook_type);
821
822 argc--; argv++;
823 } else {
824 break;
825 }
826 }
827
828 /* argv is currently the first unparsed argument,
829 * but the lwt_parse_encap() caller will move to the next,
830 * so step back
831 */
832 *argcp = argc + 1;
833 *argvp = argv - 1;
834
835 return 0;
836 }
837
838 static int parse_encap_ip6(struct rtattr *rta, size_t len,
839 int *argcp, char ***argvp)
840 {
841 int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0;
842 char **argv = *argvp;
843 int argc = *argcp;
844
845 while (argc > 0) {
846 if (strcmp(*argv, "id") == 0) {
847 __u64 id;
848
849 NEXT_ARG();
850 if (id_ok++)
851 duparg2("id", *argv);
852 if (get_be64(&id, *argv, 0))
853 invarg("\"id\" value is invalid\n", *argv);
854 rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id);
855 } else if (strcmp(*argv, "dst") == 0) {
856 inet_prefix addr;
857
858 NEXT_ARG();
859 if (dst_ok++)
860 duparg2("dst", *argv);
861 get_addr(&addr, *argv, AF_INET6);
862 rta_addattr_l(rta, len, LWTUNNEL_IP6_DST,
863 &addr.data, addr.bytelen);
864 } else if (strcmp(*argv, "tc") == 0) {
865 __u32 tc;
866
867 NEXT_ARG();
868 if (tos_ok++)
869 duparg2("tc", *argv);
870 if (rtnl_dsfield_a2n(&tc, *argv))
871 invarg("\"tc\" value is invalid\n", *argv);
872 rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc);
873 } else if (strcmp(*argv, "hoplimit") == 0) {
874 __u8 hoplimit;
875
876 NEXT_ARG();
877 if (ttl_ok++)
878 duparg2("hoplimit", *argv);
879 if (get_u8(&hoplimit, *argv, 0))
880 invarg("\"hoplimit\" value is invalid\n",
881 *argv);
882 rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit);
883 } else {
884 break;
885 }
886 argc--; argv++;
887 }
888
889 /* argv is currently the first unparsed argument,
890 * but the lwt_parse_encap() caller will move to the next,
891 * so step back
892 */
893 *argcp = argc + 1;
894 *argvp = argv - 1;
895
896 return 0;
897 }
898
899 struct lwt_x {
900 struct rtattr *rta;
901 size_t len;
902 };
903
904 static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation)
905 {
906 struct lwt_x *x = lwt_ptr;
907
908 rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd);
909 rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation,
910 strlen(annotation) + 1);
911 }
912
913 static const struct bpf_cfg_ops bpf_cb_ops = {
914 .ebpf_cb = bpf_lwt_cb,
915 };
916
917 static int lwt_parse_bpf(struct rtattr *rta, size_t len,
918 int *argcp, char ***argvp,
919 int attr, const enum bpf_prog_type bpf_type)
920 {
921 struct bpf_cfg_in cfg = {
922 .type = bpf_type,
923 .argc = *argcp,
924 .argv = *argvp,
925 };
926 struct lwt_x x = {
927 .rta = rta,
928 .len = len,
929 };
930 struct rtattr *nest;
931 int err;
932
933 nest = rta_nest(rta, len, attr);
934 err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x);
935 if (err < 0) {
936 fprintf(stderr, "Failed to parse eBPF program: %s\n",
937 strerror(-err));
938 return -1;
939 }
940 rta_nest_end(rta, nest);
941
942 *argcp = cfg.argc;
943 *argvp = cfg.argv;
944
945 return 0;
946 }
947
948 static void lwt_bpf_usage(void)
949 {
950 fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");
951 fprintf(stderr, "BPF := obj FILE [ section NAME ] [ verbose ]\n");
952 exit(-1);
953 }
954
955 static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp,
956 char ***argvp)
957 {
958 char **argv = *argvp;
959 int argc = *argcp;
960 int headroom_set = 0;
961
962 while (argc > 0) {
963 if (strcmp(*argv, "in") == 0) {
964 NEXT_ARG();
965 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_IN,
966 BPF_PROG_TYPE_LWT_IN) < 0)
967 return -1;
968 } else if (strcmp(*argv, "out") == 0) {
969 NEXT_ARG();
970 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_OUT,
971 BPF_PROG_TYPE_LWT_OUT) < 0)
972 return -1;
973 } else if (strcmp(*argv, "xmit") == 0) {
974 NEXT_ARG();
975 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_XMIT,
976 BPF_PROG_TYPE_LWT_XMIT) < 0)
977 return -1;
978 } else if (strcmp(*argv, "headroom") == 0) {
979 unsigned int headroom;
980
981 NEXT_ARG();
982 if (get_unsigned(&headroom, *argv, 0) || headroom == 0)
983 invarg("headroom is invalid\n", *argv);
984 if (!headroom_set)
985 rta_addattr32(rta, 1024, LWT_BPF_XMIT_HEADROOM,
986 headroom);
987 headroom_set = 1;
988 } else if (strcmp(*argv, "help") == 0) {
989 lwt_bpf_usage();
990 } else {
991 break;
992 }
993 NEXT_ARG_FWD();
994 }
995
996 /* argv is currently the first unparsed argument,
997 * but the lwt_parse_encap() caller will move to the next,
998 * so step back
999 */
1000 *argcp = argc + 1;
1001 *argvp = argv - 1;
1002
1003 return 0;
1004 }
1005
1006 int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
1007 {
1008 struct rtattr *nest;
1009 int argc = *argcp;
1010 char **argv = *argvp;
1011 __u16 type;
1012
1013 NEXT_ARG();
1014 type = read_encap_type(*argv);
1015 if (!type)
1016 invarg("\"encap type\" value is invalid\n", *argv);
1017
1018 NEXT_ARG();
1019 if (argc <= 1) {
1020 fprintf(stderr,
1021 "Error: unexpected end of line after \"encap\"\n");
1022 exit(-1);
1023 }
1024
1025 nest = rta_nest(rta, 1024, RTA_ENCAP);
1026 switch (type) {
1027 case LWTUNNEL_ENCAP_MPLS:
1028 parse_encap_mpls(rta, len, &argc, &argv);
1029 break;
1030 case LWTUNNEL_ENCAP_IP:
1031 parse_encap_ip(rta, len, &argc, &argv);
1032 break;
1033 case LWTUNNEL_ENCAP_ILA:
1034 parse_encap_ila(rta, len, &argc, &argv);
1035 break;
1036 case LWTUNNEL_ENCAP_IP6:
1037 parse_encap_ip6(rta, len, &argc, &argv);
1038 break;
1039 case LWTUNNEL_ENCAP_BPF:
1040 if (parse_encap_bpf(rta, len, &argc, &argv) < 0)
1041 exit(-1);
1042 break;
1043 case LWTUNNEL_ENCAP_SEG6:
1044 parse_encap_seg6(rta, len, &argc, &argv);
1045 break;
1046 case LWTUNNEL_ENCAP_SEG6_LOCAL:
1047 parse_encap_seg6local(rta, len, &argc, &argv);
1048 break;
1049 default:
1050 fprintf(stderr, "Error: unsupported encap type\n");
1051 break;
1052 }
1053 rta_nest_end(rta, nest);
1054
1055 rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type);
1056
1057 *argcp = argc;
1058 *argvp = argv;
1059
1060 return 0;
1061 }