1
2
3
4
5
6
7
8
9
10
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/rpl.h>
33#include <linux/rpl_iptunnel.h>
34#include <linux/seg6_hmac.h>
35#include <linux/seg6_local.h>
36#include <linux/if_tunnel.h>
37#include <linux/ioam6.h>
38#include <linux/ioam6_iptunnel.h>
39
40static const char *format_encap_type(int type)
41{
42 switch (type) {
43 case LWTUNNEL_ENCAP_MPLS:
44 return "mpls";
45 case LWTUNNEL_ENCAP_IP:
46 return "ip";
47 case LWTUNNEL_ENCAP_IP6:
48 return "ip6";
49 case LWTUNNEL_ENCAP_ILA:
50 return "ila";
51 case LWTUNNEL_ENCAP_BPF:
52 return "bpf";
53 case LWTUNNEL_ENCAP_SEG6:
54 return "seg6";
55 case LWTUNNEL_ENCAP_SEG6_LOCAL:
56 return "seg6local";
57 case LWTUNNEL_ENCAP_RPL:
58 return "rpl";
59 case LWTUNNEL_ENCAP_IOAM6:
60 return "ioam6";
61 default:
62 return "unknown";
63 }
64}
65
66static void encap_type_usage(void)
67{
68 int i;
69
70 fprintf(stderr, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n");
71
72 for (i = 1; i <= LWTUNNEL_ENCAP_MAX; i++)
73 fprintf(stderr, "%s %s\n", format_encap_type(i),
74 i == 1 ? "TYPE := " : " ");
75
76 exit(-1);
77}
78
79static int read_encap_type(const char *name)
80{
81 if (strcmp(name, "mpls") == 0)
82 return LWTUNNEL_ENCAP_MPLS;
83 else if (strcmp(name, "ip") == 0)
84 return LWTUNNEL_ENCAP_IP;
85 else if (strcmp(name, "ip6") == 0)
86 return LWTUNNEL_ENCAP_IP6;
87 else if (strcmp(name, "ila") == 0)
88 return LWTUNNEL_ENCAP_ILA;
89 else if (strcmp(name, "bpf") == 0)
90 return LWTUNNEL_ENCAP_BPF;
91 else if (strcmp(name, "seg6") == 0)
92 return LWTUNNEL_ENCAP_SEG6;
93 else if (strcmp(name, "seg6local") == 0)
94 return LWTUNNEL_ENCAP_SEG6_LOCAL;
95 else if (strcmp(name, "rpl") == 0)
96 return LWTUNNEL_ENCAP_RPL;
97 else if (strcmp(name, "ioam6") == 0)
98 return LWTUNNEL_ENCAP_IOAM6;
99 else if (strcmp(name, "help") == 0)
100 encap_type_usage();
101
102 return LWTUNNEL_ENCAP_NONE;
103}
104
105static void print_srh(FILE *fp, struct ipv6_sr_hdr *srh)
106{
107 int i;
108
109 if (is_json_context())
110 open_json_array(PRINT_JSON, "segs");
111 else
112 fprintf(fp, "segs %d [ ", srh->first_segment + 1);
113
114 for (i = srh->first_segment; i >= 0; i--)
115 print_color_string(PRINT_ANY, COLOR_INET6,
116 NULL, "%s ",
117 rt_addr_n2a(AF_INET6, 16, &srh->segments[i]));
118
119 if (is_json_context())
120 close_json_array(PRINT_JSON, NULL);
121 else
122 fprintf(fp, "] ");
123
124 if (sr_has_hmac(srh)) {
125 unsigned int offset = ((srh->hdrlen + 1) << 3) - 40;
126 struct sr6_tlv_hmac *tlv;
127
128 tlv = (struct sr6_tlv_hmac *)((char *)srh + offset);
129 print_0xhex(PRINT_ANY, "hmac",
130 "hmac %llX ", ntohl(tlv->hmackeyid));
131 }
132}
133
134static const char *seg6_mode_types[] = {
135 [SEG6_IPTUN_MODE_INLINE] = "inline",
136 [SEG6_IPTUN_MODE_ENCAP] = "encap",
137 [SEG6_IPTUN_MODE_L2ENCAP] = "l2encap",
138};
139
140static const char *format_seg6mode_type(int mode)
141{
142 if (mode < 0 || mode > ARRAY_SIZE(seg6_mode_types))
143 return "<unknown>";
144
145 return seg6_mode_types[mode];
146}
147
148static int read_seg6mode_type(const char *mode)
149{
150 int i;
151
152 for (i = 0; i < ARRAY_SIZE(seg6_mode_types); i++) {
153 if (strcmp(mode, seg6_mode_types[i]) == 0)
154 return i;
155 }
156
157 return -1;
158}
159
160static void print_encap_seg6(FILE *fp, struct rtattr *encap)
161{
162 struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
163 struct seg6_iptunnel_encap *tuninfo;
164
165 parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap);
166
167 if (!tb[SEG6_IPTUNNEL_SRH])
168 return;
169
170 tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
171 print_string(PRINT_ANY, "mode",
172 "mode %s ", format_seg6mode_type(tuninfo->mode));
173
174 print_srh(fp, tuninfo->srh);
175}
176
177static void print_rpl_srh(FILE *fp, struct ipv6_rpl_sr_hdr *srh)
178{
179 int i;
180
181 if (is_json_context())
182 open_json_array(PRINT_JSON, "segs");
183 else
184 fprintf(fp, "segs %d [ ", srh->segments_left);
185
186 for (i = srh->segments_left - 1; i >= 0; i--) {
187 print_color_string(PRINT_ANY, COLOR_INET6,
188 NULL, "%s ",
189 rt_addr_n2a(AF_INET6, 16, &srh->rpl_segaddr[i]));
190 }
191
192 if (is_json_context())
193 close_json_array(PRINT_JSON, NULL);
194 else
195 fprintf(fp, "] ");
196}
197
198static void print_encap_rpl(FILE *fp, struct rtattr *encap)
199{
200 struct rtattr *tb[RPL_IPTUNNEL_MAX + 1];
201 struct ipv6_rpl_sr_hdr *srh;
202
203 parse_rtattr_nested(tb, RPL_IPTUNNEL_MAX, encap);
204
205 if (!tb[RPL_IPTUNNEL_SRH])
206 return;
207
208 srh = RTA_DATA(tb[RPL_IPTUNNEL_SRH]);
209
210 print_rpl_srh(fp, srh);
211}
212
213static void print_encap_ioam6(FILE *fp, struct rtattr *encap)
214{
215 struct rtattr *tb[IOAM6_IPTUNNEL_MAX + 1];
216 struct ioam6_trace_hdr *trace;
217
218 parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap);
219
220 if (!tb[IOAM6_IPTUNNEL_TRACE])
221 return;
222
223 trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]);
224
225 print_null(PRINT_ANY, "trace", "trace ", NULL);
226 print_null(PRINT_ANY, "prealloc", "prealloc ", NULL);
227 print_hex(PRINT_ANY, "type", "type %#08x ", ntohl(trace->type_be32) >> 8);
228 print_uint(PRINT_ANY, "ns", "ns %u ", ntohs(trace->namespace_id));
229 print_uint(PRINT_ANY, "size", "size %u ", trace->remlen * 4);
230}
231
232static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
233 [SEG6_LOCAL_ACTION_END] = "End",
234 [SEG6_LOCAL_ACTION_END_X] = "End.X",
235 [SEG6_LOCAL_ACTION_END_T] = "End.T",
236 [SEG6_LOCAL_ACTION_END_DX2] = "End.DX2",
237 [SEG6_LOCAL_ACTION_END_DX6] = "End.DX6",
238 [SEG6_LOCAL_ACTION_END_DX4] = "End.DX4",
239 [SEG6_LOCAL_ACTION_END_DT6] = "End.DT6",
240 [SEG6_LOCAL_ACTION_END_DT4] = "End.DT4",
241 [SEG6_LOCAL_ACTION_END_B6] = "End.B6",
242 [SEG6_LOCAL_ACTION_END_B6_ENCAP] = "End.B6.Encaps",
243 [SEG6_LOCAL_ACTION_END_BM] = "End.BM",
244 [SEG6_LOCAL_ACTION_END_S] = "End.S",
245 [SEG6_LOCAL_ACTION_END_AS] = "End.AS",
246 [SEG6_LOCAL_ACTION_END_AM] = "End.AM",
247 [SEG6_LOCAL_ACTION_END_BPF] = "End.BPF",
248 [SEG6_LOCAL_ACTION_END_DT46] = "End.DT46",
249};
250
251static const char *format_action_type(int action)
252{
253 if (action < 0 || action > SEG6_LOCAL_ACTION_MAX)
254 return "<invalid>";
255
256 return seg6_action_names[action] ?: "<unknown>";
257}
258
259static int read_action_type(const char *name)
260{
261 int i;
262
263 for (i = 0; i < SEG6_LOCAL_ACTION_MAX + 1; i++) {
264 if (!seg6_action_names[i])
265 continue;
266
267 if (strcmp(seg6_action_names[i], name) == 0)
268 return i;
269 }
270
271 return SEG6_LOCAL_ACTION_UNSPEC;
272}
273
274static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
275 const char *str)
276{
277 struct rtattr *tb[LWT_BPF_PROG_MAX+1];
278 const char *progname = NULL;
279
280 parse_rtattr_nested(tb, LWT_BPF_PROG_MAX, encap);
281
282 if (tb[LWT_BPF_PROG_NAME])
283 progname = rta_getattr_str(tb[LWT_BPF_PROG_NAME]);
284
285 if (is_json_context())
286 print_string(PRINT_JSON, str, NULL,
287 progname ? : "<unknown>");
288 else {
289 fprintf(fp, "%s ", str);
290 if (progname)
291 fprintf(fp, "%s ", progname);
292 }
293}
294
295static void print_seg6_local_counters(FILE *fp, struct rtattr *encap)
296{
297 struct rtattr *tb[SEG6_LOCAL_CNT_MAX + 1];
298 __u64 packets = 0, bytes = 0, errors = 0;
299
300 parse_rtattr_nested(tb, SEG6_LOCAL_CNT_MAX, encap);
301
302 if (tb[SEG6_LOCAL_CNT_PACKETS])
303 packets = rta_getattr_u64(tb[SEG6_LOCAL_CNT_PACKETS]);
304
305 if (tb[SEG6_LOCAL_CNT_BYTES])
306 bytes = rta_getattr_u64(tb[SEG6_LOCAL_CNT_BYTES]);
307
308 if (tb[SEG6_LOCAL_CNT_ERRORS])
309 errors = rta_getattr_u64(tb[SEG6_LOCAL_CNT_ERRORS]);
310
311 if (is_json_context()) {
312 open_json_object("stats64");
313
314 print_u64(PRINT_JSON, "packets", NULL, packets);
315 print_u64(PRINT_JSON, "bytes", NULL, bytes);
316 print_u64(PRINT_JSON, "errors", NULL, errors);
317
318 close_json_object();
319 } else {
320 print_string(PRINT_FP, NULL, "%s ", "packets");
321 print_num(fp, 1, packets);
322
323 print_string(PRINT_FP, NULL, "%s ", "bytes");
324 print_num(fp, 1, bytes);
325
326 print_string(PRINT_FP, NULL, "%s ", "errors");
327 print_num(fp, 1, errors);
328 }
329}
330
331static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
332{
333 struct rtattr *tb[SEG6_LOCAL_MAX + 1];
334 int action;
335
336 SPRINT_BUF(b1);
337
338 parse_rtattr_nested(tb, SEG6_LOCAL_MAX, encap);
339
340 if (!tb[SEG6_LOCAL_ACTION])
341 return;
342
343 action = rta_getattr_u32(tb[SEG6_LOCAL_ACTION]);
344
345 print_string(PRINT_ANY, "action",
346 "action %s ", format_action_type(action));
347
348 if (tb[SEG6_LOCAL_SRH]) {
349 open_json_object("srh");
350 print_srh(fp, RTA_DATA(tb[SEG6_LOCAL_SRH]));
351 close_json_object();
352 }
353
354 if (tb[SEG6_LOCAL_TABLE])
355 print_string(PRINT_ANY, "table", "table %s ",
356 rtnl_rttable_n2a(rta_getattr_u32(tb[SEG6_LOCAL_TABLE]),
357 b1, sizeof(b1)));
358
359 if (tb[SEG6_LOCAL_VRFTABLE])
360 print_string(PRINT_ANY, "vrftable", "vrftable %s ",
361 rtnl_rttable_n2a(rta_getattr_u32(tb[SEG6_LOCAL_VRFTABLE]),
362 b1, sizeof(b1)));
363
364 if (tb[SEG6_LOCAL_NH4]) {
365 print_string(PRINT_ANY, "nh4",
366 "nh4 %s ", rt_addr_n2a_rta(AF_INET, tb[SEG6_LOCAL_NH4]));
367 }
368
369 if (tb[SEG6_LOCAL_NH6]) {
370 print_string(PRINT_ANY, "nh6",
371 "nh6 %s ", rt_addr_n2a_rta(AF_INET6, tb[SEG6_LOCAL_NH6]));
372 }
373
374 if (tb[SEG6_LOCAL_IIF]) {
375 int iif = rta_getattr_u32(tb[SEG6_LOCAL_IIF]);
376
377 print_string(PRINT_ANY, "iif",
378 "iif %s ", ll_index_to_name(iif));
379 }
380
381 if (tb[SEG6_LOCAL_OIF]) {
382 int oif = rta_getattr_u32(tb[SEG6_LOCAL_OIF]);
383
384 print_string(PRINT_ANY, "oif",
385 "oif %s ", ll_index_to_name(oif));
386 }
387
388 if (tb[SEG6_LOCAL_BPF])
389 print_encap_bpf_prog(fp, tb[SEG6_LOCAL_BPF], "endpoint");
390
391 if (tb[SEG6_LOCAL_COUNTERS] && show_stats)
392 print_seg6_local_counters(fp, tb[SEG6_LOCAL_COUNTERS]);
393}
394
395static void print_encap_mpls(FILE *fp, struct rtattr *encap)
396{
397 struct rtattr *tb[MPLS_IPTUNNEL_MAX+1];
398
399 parse_rtattr_nested(tb, MPLS_IPTUNNEL_MAX, encap);
400
401 if (tb[MPLS_IPTUNNEL_DST])
402 print_string(PRINT_ANY, "dst", " %s ",
403 format_host_rta(AF_MPLS, tb[MPLS_IPTUNNEL_DST]));
404 if (tb[MPLS_IPTUNNEL_TTL])
405 print_uint(PRINT_ANY, "ttl", "ttl %u ",
406 rta_getattr_u8(tb[MPLS_IPTUNNEL_TTL]));
407}
408
409static void lwtunnel_print_geneve_opts(struct rtattr *attr)
410{
411 struct rtattr *tb[LWTUNNEL_IP_OPT_GENEVE_MAX + 1];
412 struct rtattr *i = RTA_DATA(attr);
413 int rem = RTA_PAYLOAD(attr);
414 char *name = "geneve_opts";
415 int data_len, offset = 0;
416 char data[rem * 2 + 1];
417 __u16 class;
418 __u8 type;
419
420 print_nl();
421 print_string(PRINT_FP, name, "\t%s ", name);
422 open_json_array(PRINT_JSON, name);
423
424 while (rem) {
425 parse_rtattr(tb, LWTUNNEL_IP_OPT_GENEVE_MAX, i, rem);
426 class = rta_getattr_be16(tb[LWTUNNEL_IP_OPT_GENEVE_CLASS]);
427 type = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_GENEVE_TYPE]);
428 data_len = RTA_PAYLOAD(tb[LWTUNNEL_IP_OPT_GENEVE_DATA]);
429 hexstring_n2a(RTA_DATA(tb[LWTUNNEL_IP_OPT_GENEVE_DATA]),
430 data_len, data, sizeof(data));
431 offset += data_len + 20;
432 rem -= data_len + 20;
433 i = RTA_DATA(attr) + offset;
434
435 open_json_object(NULL);
436 print_uint(PRINT_ANY, "class", "%u", class);
437 print_uint(PRINT_ANY, "type", ":%u", type);
438 if (rem)
439 print_string(PRINT_ANY, "data", ":%s,", data);
440 else
441 print_string(PRINT_ANY, "data", ":%s ", data);
442 close_json_object();
443 }
444
445 close_json_array(PRINT_JSON, name);
446}
447
448static void lwtunnel_print_vxlan_opts(struct rtattr *attr)
449{
450 struct rtattr *tb[LWTUNNEL_IP_OPT_VXLAN_MAX + 1];
451 struct rtattr *i = RTA_DATA(attr);
452 int rem = RTA_PAYLOAD(attr);
453 char *name = "vxlan_opts";
454 __u32 gbp;
455
456 parse_rtattr(tb, LWTUNNEL_IP_OPT_VXLAN_MAX, i, rem);
457 gbp = rta_getattr_u32(tb[LWTUNNEL_IP_OPT_VXLAN_GBP]);
458
459 print_nl();
460 print_string(PRINT_FP, name, "\t%s ", name);
461 open_json_array(PRINT_JSON, name);
462 open_json_object(NULL);
463 print_uint(PRINT_ANY, "gbp", "%u ", gbp);
464 close_json_object();
465 close_json_array(PRINT_JSON, name);
466}
467
468static void lwtunnel_print_erspan_opts(struct rtattr *attr)
469{
470 struct rtattr *tb[LWTUNNEL_IP_OPT_ERSPAN_MAX + 1];
471 struct rtattr *i = RTA_DATA(attr);
472 char *name = "erspan_opts";
473 __u8 ver, hwid, dir;
474 __u32 idx;
475
476 parse_rtattr(tb, LWTUNNEL_IP_OPT_ERSPAN_MAX, i, RTA_PAYLOAD(attr));
477 ver = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_VER]);
478 if (ver == 1) {
479 idx = rta_getattr_be32(tb[LWTUNNEL_IP_OPT_ERSPAN_INDEX]);
480 dir = 0;
481 hwid = 0;
482 } else {
483 idx = 0;
484 dir = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_DIR]);
485 hwid = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_HWID]);
486 }
487
488 print_nl();
489 print_string(PRINT_FP, name, "\t%s ", name);
490 open_json_array(PRINT_JSON, name);
491 open_json_object(NULL);
492 print_uint(PRINT_ANY, "ver", "%u", ver);
493 print_uint(PRINT_ANY, "index", ":%u", idx);
494 print_uint(PRINT_ANY, "dir", ":%u", dir);
495 print_uint(PRINT_ANY, "hwid", ":%u ", hwid);
496 close_json_object();
497 close_json_array(PRINT_JSON, name);
498}
499
500static void lwtunnel_print_opts(struct rtattr *attr)
501{
502 struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1];
503
504 parse_rtattr_nested(tb_opt, LWTUNNEL_IP_OPTS_MAX, attr);
505 if (tb_opt[LWTUNNEL_IP_OPTS_GENEVE])
506 lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]);
507 else if (tb_opt[LWTUNNEL_IP_OPTS_VXLAN])
508 lwtunnel_print_vxlan_opts(tb_opt[LWTUNNEL_IP_OPTS_VXLAN]);
509 else if (tb_opt[LWTUNNEL_IP_OPTS_ERSPAN])
510 lwtunnel_print_erspan_opts(tb_opt[LWTUNNEL_IP_OPTS_ERSPAN]);
511}
512
513static void print_encap_ip(FILE *fp, struct rtattr *encap)
514{
515 struct rtattr *tb[LWTUNNEL_IP_MAX+1];
516 __u16 flags;
517
518 parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
519
520 if (tb[LWTUNNEL_IP_ID])
521 print_u64(PRINT_ANY, "id", "id %llu ",
522 ntohll(rta_getattr_u64(tb[LWTUNNEL_IP_ID])));
523
524 if (tb[LWTUNNEL_IP_SRC])
525 print_color_string(PRINT_ANY, COLOR_INET,
526 "src", "src %s ",
527 rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_SRC]));
528
529 if (tb[LWTUNNEL_IP_DST])
530 print_color_string(PRINT_ANY, COLOR_INET,
531 "dst", "dst %s ",
532 rt_addr_n2a_rta(AF_INET, tb[LWTUNNEL_IP_DST]));
533
534 if (tb[LWTUNNEL_IP_TTL])
535 print_uint(PRINT_ANY, "ttl",
536 "ttl %u ", rta_getattr_u8(tb[LWTUNNEL_IP_TTL]));
537
538 if (tb[LWTUNNEL_IP_TOS])
539 print_uint(PRINT_ANY, "tos",
540 "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
541
542 if (tb[LWTUNNEL_IP_FLAGS]) {
543 flags = rta_getattr_u16(tb[LWTUNNEL_IP_FLAGS]);
544 if (flags & TUNNEL_KEY)
545 print_bool(PRINT_ANY, "key", "key ", true);
546 if (flags & TUNNEL_CSUM)
547 print_bool(PRINT_ANY, "csum", "csum ", true);
548 if (flags & TUNNEL_SEQ)
549 print_bool(PRINT_ANY, "seq", "seq ", true);
550 }
551
552 if (tb[LWTUNNEL_IP_OPTS])
553 lwtunnel_print_opts(tb[LWTUNNEL_IP_OPTS]);
554}
555
556static void print_encap_ila(FILE *fp, struct rtattr *encap)
557{
558 struct rtattr *tb[ILA_ATTR_MAX+1];
559
560 parse_rtattr_nested(tb, ILA_ATTR_MAX, encap);
561
562 if (tb[ILA_ATTR_LOCATOR]) {
563 char abuf[ADDR64_BUF_SIZE];
564
565 addr64_n2a(rta_getattr_u64(tb[ILA_ATTR_LOCATOR]),
566 abuf, sizeof(abuf));
567 print_string(PRINT_ANY, "locator",
568 " %s ", abuf);
569 }
570
571 if (tb[ILA_ATTR_CSUM_MODE])
572 print_string(PRINT_ANY, "csum_mode",
573 " csum-mode %s ",
574 ila_csum_mode2name(rta_getattr_u8(tb[ILA_ATTR_CSUM_MODE])));
575
576 if (tb[ILA_ATTR_IDENT_TYPE])
577 print_string(PRINT_ANY, "ident_type",
578 " ident-type %s ",
579 ila_ident_type2name(rta_getattr_u8(tb[ILA_ATTR_IDENT_TYPE])));
580
581 if (tb[ILA_ATTR_HOOK_TYPE])
582 print_string(PRINT_ANY, "hook_type",
583 " hook-type %s ",
584 ila_hook_type2name(rta_getattr_u8(tb[ILA_ATTR_HOOK_TYPE])));
585}
586
587static void print_encap_ip6(FILE *fp, struct rtattr *encap)
588{
589 struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
590 __u16 flags;
591
592 parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
593
594 if (tb[LWTUNNEL_IP6_ID])
595 print_u64(PRINT_ANY, "id", "id %llu ",
596 ntohll(rta_getattr_u64(tb[LWTUNNEL_IP6_ID])));
597
598 if (tb[LWTUNNEL_IP6_SRC])
599 print_color_string(PRINT_ANY, COLOR_INET6,
600 "src", "src %s ",
601 rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_SRC]));
602
603 if (tb[LWTUNNEL_IP6_DST])
604 print_color_string(PRINT_ANY, COLOR_INET6,
605 "dst", "dst %s ",
606 rt_addr_n2a_rta(AF_INET6, tb[LWTUNNEL_IP6_DST]));
607
608 if (tb[LWTUNNEL_IP6_HOPLIMIT])
609 print_u64(PRINT_ANY, "hoplimit",
610 "hoplimit %u ",
611 rta_getattr_u8(tb[LWTUNNEL_IP6_HOPLIMIT]));
612
613 if (tb[LWTUNNEL_IP6_TC])
614 print_uint(PRINT_ANY, "tc",
615 "tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
616
617 if (tb[LWTUNNEL_IP6_FLAGS]) {
618 flags = rta_getattr_u16(tb[LWTUNNEL_IP6_FLAGS]);
619 if (flags & TUNNEL_KEY)
620 print_bool(PRINT_ANY, "key", "key ", true);
621 if (flags & TUNNEL_CSUM)
622 print_bool(PRINT_ANY, "csum", "csum ", true);
623 if (flags & TUNNEL_SEQ)
624 print_bool(PRINT_ANY, "seq", "seq ", true);
625 }
626
627 if (tb[LWTUNNEL_IP6_OPTS])
628 lwtunnel_print_opts(tb[LWTUNNEL_IP6_OPTS]);
629}
630
631static void print_encap_bpf(FILE *fp, struct rtattr *encap)
632{
633 struct rtattr *tb[LWT_BPF_MAX+1];
634
635 parse_rtattr_nested(tb, LWT_BPF_MAX, encap);
636
637 if (tb[LWT_BPF_IN])
638 print_encap_bpf_prog(fp, tb[LWT_BPF_IN], "in");
639 if (tb[LWT_BPF_OUT])
640 print_encap_bpf_prog(fp, tb[LWT_BPF_OUT], "out");
641 if (tb[LWT_BPF_XMIT])
642 print_encap_bpf_prog(fp, tb[LWT_BPF_XMIT], "xmit");
643 if (tb[LWT_BPF_XMIT_HEADROOM])
644 print_uint(PRINT_ANY, "headroom",
645 " %u ", rta_getattr_u32(tb[LWT_BPF_XMIT_HEADROOM]));
646}
647
648void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
649 struct rtattr *encap)
650{
651 int et;
652
653 if (!encap_type)
654 return;
655
656 et = rta_getattr_u16(encap_type);
657
658 print_string(PRINT_ANY, "encap", " encap %s ", format_encap_type(et));
659
660 switch (et) {
661 case LWTUNNEL_ENCAP_MPLS:
662 print_encap_mpls(fp, encap);
663 break;
664 case LWTUNNEL_ENCAP_IP:
665 print_encap_ip(fp, encap);
666 break;
667 case LWTUNNEL_ENCAP_ILA:
668 print_encap_ila(fp, encap);
669 break;
670 case LWTUNNEL_ENCAP_IP6:
671 print_encap_ip6(fp, encap);
672 break;
673 case LWTUNNEL_ENCAP_BPF:
674 print_encap_bpf(fp, encap);
675 break;
676 case LWTUNNEL_ENCAP_SEG6:
677 print_encap_seg6(fp, encap);
678 break;
679 case LWTUNNEL_ENCAP_SEG6_LOCAL:
680 print_encap_seg6local(fp, encap);
681 break;
682 case LWTUNNEL_ENCAP_RPL:
683 print_encap_rpl(fp, encap);
684 break;
685 case LWTUNNEL_ENCAP_IOAM6:
686 print_encap_ioam6(fp, encap);
687 break;
688 }
689}
690
691static struct ipv6_sr_hdr *parse_srh(char *segbuf, int hmac, bool encap)
692{
693 struct ipv6_sr_hdr *srh;
694 int nsegs = 0;
695 int srhlen;
696 char *s;
697 int i;
698
699 s = segbuf;
700 for (i = 0; *s; *s++ == ',' ? i++ : *s);
701 nsegs = i + 1;
702
703 if (!encap)
704 nsegs++;
705
706 srhlen = 8 + 16*nsegs;
707
708 if (hmac)
709 srhlen += 40;
710
711 srh = malloc(srhlen);
712 memset(srh, 0, srhlen);
713
714 srh->hdrlen = (srhlen >> 3) - 1;
715 srh->type = 4;
716 srh->segments_left = nsegs - 1;
717 srh->first_segment = nsegs - 1;
718
719 if (hmac)
720 srh->flags |= SR6_FLAG1_HMAC;
721
722 i = srh->first_segment;
723 for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) {
724 inet_prefix addr;
725
726 get_addr(&addr, s, AF_INET6);
727 memcpy(&srh->segments[i], addr.data, sizeof(struct in6_addr));
728 i--;
729 }
730
731 if (hmac) {
732 struct sr6_tlv_hmac *tlv;
733
734 tlv = (struct sr6_tlv_hmac *)((char *)srh + srhlen - 40);
735 tlv->tlvhdr.type = SR6_TLV_HMAC;
736 tlv->tlvhdr.len = 38;
737 tlv->hmackeyid = htonl(hmac);
738 }
739
740 return srh;
741}
742
743static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
744 char ***argvp)
745{
746 int mode_ok = 0, segs_ok = 0, hmac_ok = 0;
747 struct seg6_iptunnel_encap *tuninfo;
748 struct ipv6_sr_hdr *srh;
749 char **argv = *argvp;
750 char segbuf[1024] = "";
751 int argc = *argcp;
752 int encap = -1;
753 __u32 hmac = 0;
754 int ret = 0;
755 int srhlen;
756
757 while (argc > 0) {
758 if (strcmp(*argv, "mode") == 0) {
759 NEXT_ARG();
760 if (mode_ok++)
761 duparg2("mode", *argv);
762 encap = read_seg6mode_type(*argv);
763 if (encap < 0)
764 invarg("\"mode\" value is invalid\n", *argv);
765 } else if (strcmp(*argv, "segs") == 0) {
766 NEXT_ARG();
767 if (segs_ok++)
768 duparg2("segs", *argv);
769 if (encap == -1)
770 invarg("\"segs\" provided before \"mode\"\n",
771 *argv);
772
773 strlcpy(segbuf, *argv, 1024);
774 } else if (strcmp(*argv, "hmac") == 0) {
775 NEXT_ARG();
776 if (hmac_ok++)
777 duparg2("hmac", *argv);
778 get_u32(&hmac, *argv, 0);
779 } else {
780 break;
781 }
782 argc--; argv++;
783 }
784
785 srh = parse_srh(segbuf, hmac, encap);
786 srhlen = (srh->hdrlen + 1) << 3;
787
788 tuninfo = malloc(sizeof(*tuninfo) + srhlen);
789 memset(tuninfo, 0, sizeof(*tuninfo) + srhlen);
790
791 tuninfo->mode = encap;
792
793 memcpy(tuninfo->srh, srh, srhlen);
794
795 if (rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo,
796 sizeof(*tuninfo) + srhlen)) {
797 ret = -1;
798 goto out;
799 }
800
801 *argcp = argc + 1;
802 *argvp = argv - 1;
803
804out:
805 free(tuninfo);
806 free(srh);
807
808 return ret;
809}
810
811static struct ipv6_rpl_sr_hdr *parse_rpl_srh(char *segbuf)
812{
813 struct ipv6_rpl_sr_hdr *srh;
814 int nsegs = 0;
815 int srhlen;
816 char *s;
817 int i;
818
819 s = segbuf;
820 for (i = 0; *s; *s++ == ',' ? i++ : *s);
821 nsegs = i + 1;
822
823 srhlen = 8 + 16 * nsegs;
824
825 srh = calloc(1, srhlen);
826
827 srh->hdrlen = (srhlen >> 3) - 1;
828 srh->type = 3;
829 srh->segments_left = nsegs;
830
831 for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) {
832 inet_prefix addr;
833
834 get_addr(&addr, s, AF_INET6);
835 memcpy(&srh->rpl_segaddr[i], addr.data, sizeof(struct in6_addr));
836 i--;
837 }
838
839 return srh;
840}
841
842static int parse_encap_rpl(struct rtattr *rta, size_t len, int *argcp,
843 char ***argvp)
844{
845 struct ipv6_rpl_sr_hdr *srh;
846 char **argv = *argvp;
847 char segbuf[1024] = "";
848 int argc = *argcp;
849 int segs_ok = 0;
850 int ret = 0;
851 int srhlen;
852
853 while (argc > 0) {
854 if (strcmp(*argv, "segs") == 0) {
855 NEXT_ARG();
856 if (segs_ok++)
857 duparg2("segs", *argv);
858
859 strlcpy(segbuf, *argv, 1024);
860 } else {
861 break;
862 }
863 argc--; argv++;
864 }
865
866 srh = parse_rpl_srh(segbuf);
867 srhlen = (srh->hdrlen + 1) << 3;
868
869 if (rta_addattr_l(rta, len, RPL_IPTUNNEL_SRH, srh,
870 srhlen)) {
871 ret = -1;
872 goto out;
873 }
874
875 *argcp = argc + 1;
876 *argvp = argv - 1;
877
878out:
879 free(srh);
880
881 return ret;
882}
883
884static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp,
885 char ***argvp)
886{
887 struct ioam6_trace_hdr *trace;
888 char **argv = *argvp;
889 int argc = *argcp;
890 int ns_found = 0;
891 __u16 size = 0;
892 __u32 type = 0;
893 __u16 ns;
894
895 trace = calloc(1, sizeof(*trace));
896 if (!trace)
897 return -1;
898
899 if (strcmp(*argv, "trace"))
900 missarg("trace");
901
902 NEXT_ARG();
903 if (strcmp(*argv, "prealloc"))
904 missarg("prealloc");
905
906 while (NEXT_ARG_OK()) {
907 NEXT_ARG_FWD();
908
909 if (strcmp(*argv, "type") == 0) {
910 NEXT_ARG();
911
912 if (type)
913 duparg2("type", *argv);
914
915 if (get_u32(&type, *argv, 0) || !type)
916 invarg("Invalid type", *argv);
917
918 trace->type_be32 = htonl(type << 8);
919
920 } else if (strcmp(*argv, "ns") == 0) {
921 NEXT_ARG();
922
923 if (ns_found++)
924 duparg2("ns", *argv);
925
926 if (!type)
927 missarg("type");
928
929 if (get_u16(&ns, *argv, 0))
930 invarg("Invalid namespace ID", *argv);
931
932 trace->namespace_id = htons(ns);
933
934 } else if (strcmp(*argv, "size") == 0) {
935 NEXT_ARG();
936
937 if (size)
938 duparg2("size", *argv);
939
940 if (!type)
941 missarg("type");
942 if (!ns_found)
943 missarg("ns");
944
945 if (get_u16(&size, *argv, 0) || !size)
946 invarg("Invalid size", *argv);
947
948 if (size % 4)
949 invarg("Size must be a 4-octet multiple", *argv);
950 if (size > IOAM6_TRACE_DATA_SIZE_MAX)
951 invarg("Size too big", *argv);
952
953 trace->remlen = (__u8)(size / 4);
954
955 } else {
956 break;
957 }
958 }
959
960 if (!type)
961 missarg("type");
962 if (!ns_found)
963 missarg("ns");
964 if (!size)
965 missarg("size");
966
967 if (rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace,
968 sizeof(*trace))) {
969 free(trace);
970 return -1;
971 }
972
973 *argcp = argc + 1;
974 *argvp = argv - 1;
975
976 free(trace);
977 return 0;
978}
979
980struct lwt_x {
981 struct rtattr *rta;
982 size_t len;
983};
984
985static void bpf_lwt_cb(void *lwt_ptr, int fd, const char *annotation)
986{
987 struct lwt_x *x = lwt_ptr;
988
989 rta_addattr32(x->rta, x->len, LWT_BPF_PROG_FD, fd);
990 rta_addattr_l(x->rta, x->len, LWT_BPF_PROG_NAME, annotation,
991 strlen(annotation) + 1);
992}
993
994static const struct bpf_cfg_ops bpf_cb_ops = {
995 .ebpf_cb = bpf_lwt_cb,
996};
997
998static int lwt_parse_bpf(struct rtattr *rta, size_t len,
999 int *argcp, char ***argvp,
1000 int attr, const enum bpf_prog_type bpf_type)
1001{
1002 struct bpf_cfg_in cfg = {
1003 .type = bpf_type,
1004 .argc = *argcp,
1005 .argv = *argvp,
1006 };
1007 struct lwt_x x = {
1008 .rta = rta,
1009 .len = len,
1010 };
1011 struct rtattr *nest;
1012 int err;
1013
1014 nest = rta_nest(rta, len, attr);
1015 err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x);
1016 if (err < 0) {
1017 fprintf(stderr, "Failed to parse eBPF program: %s\n",
1018 strerror(-err));
1019 return -1;
1020 }
1021 rta_nest_end(rta, nest);
1022
1023 *argcp = cfg.argc;
1024 *argvp = cfg.argv;
1025
1026 return 0;
1027}
1028
1029
1030
1031
1032static int seg6local_fill_counters(struct rtattr *rta, size_t len, int attr)
1033{
1034 struct rtattr *nest;
1035 int ret;
1036
1037 nest = rta_nest(rta, len, attr);
1038
1039 ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_PACKETS, 0);
1040 if (ret < 0)
1041 return ret;
1042
1043 ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_BYTES, 0);
1044 if (ret < 0)
1045 return ret;
1046
1047 ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_ERRORS, 0);
1048 if (ret < 0)
1049 return ret;
1050
1051 rta_nest_end(rta, nest);
1052 return 0;
1053}
1054
1055static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
1056 char ***argvp)
1057{
1058 int segs_ok = 0, hmac_ok = 0, table_ok = 0, vrftable_ok = 0;
1059 int action_ok = 0, srh_ok = 0, bpf_ok = 0, counters_ok = 0;
1060 int nh4_ok = 0, nh6_ok = 0, iif_ok = 0, oif_ok = 0;
1061 __u32 action = 0, table, vrftable, iif, oif;
1062 struct ipv6_sr_hdr *srh;
1063 char **argv = *argvp;
1064 int argc = *argcp;
1065 char segbuf[1024];
1066 inet_prefix addr;
1067 __u32 hmac = 0;
1068 int ret = 0;
1069
1070 while (argc > 0) {
1071 if (strcmp(*argv, "action") == 0) {
1072 NEXT_ARG();
1073 if (action_ok++)
1074 duparg2("action", *argv);
1075 action = read_action_type(*argv);
1076 if (!action)
1077 invarg("\"action\" value is invalid\n", *argv);
1078 ret = rta_addattr32(rta, len, SEG6_LOCAL_ACTION,
1079 action);
1080 } else if (strcmp(*argv, "table") == 0) {
1081 NEXT_ARG();
1082 if (table_ok++)
1083 duparg2("table", *argv);
1084 if (rtnl_rttable_a2n(&table, *argv))
1085 invarg("invalid table id\n", *argv);
1086 ret = rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table);
1087 } else if (strcmp(*argv, "vrftable") == 0) {
1088 NEXT_ARG();
1089 if (vrftable_ok++)
1090 duparg2("vrftable", *argv);
1091 if (rtnl_rttable_a2n(&vrftable, *argv))
1092 invarg("invalid vrf table id\n", *argv);
1093 ret = rta_addattr32(rta, len, SEG6_LOCAL_VRFTABLE,
1094 vrftable);
1095 } else if (strcmp(*argv, "nh4") == 0) {
1096 NEXT_ARG();
1097 if (nh4_ok++)
1098 duparg2("nh4", *argv);
1099 get_addr(&addr, *argv, AF_INET);
1100 ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH4,
1101 &addr.data, addr.bytelen);
1102 } else if (strcmp(*argv, "nh6") == 0) {
1103 NEXT_ARG();
1104 if (nh6_ok++)
1105 duparg2("nh6", *argv);
1106 get_addr(&addr, *argv, AF_INET6);
1107 ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH6,
1108 &addr.data, addr.bytelen);
1109 } else if (strcmp(*argv, "iif") == 0) {
1110 NEXT_ARG();
1111 if (iif_ok++)
1112 duparg2("iif", *argv);
1113 iif = ll_name_to_index(*argv);
1114 if (!iif)
1115 exit(nodev(*argv));
1116 ret = rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif);
1117 } else if (strcmp(*argv, "oif") == 0) {
1118 NEXT_ARG();
1119 if (oif_ok++)
1120 duparg2("oif", *argv);
1121 oif = ll_name_to_index(*argv);
1122 if (!oif)
1123 exit(nodev(*argv));
1124 ret = rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif);
1125 } else if (strcmp(*argv, "count") == 0) {
1126 if (counters_ok++)
1127 duparg2("count", *argv);
1128 ret = seg6local_fill_counters(rta, len,
1129 SEG6_LOCAL_COUNTERS);
1130 } else if (strcmp(*argv, "srh") == 0) {
1131 NEXT_ARG();
1132 if (srh_ok++)
1133 duparg2("srh", *argv);
1134 if (strcmp(*argv, "segs") != 0)
1135 invarg("missing \"segs\" attribute for srh\n",
1136 *argv);
1137 NEXT_ARG();
1138 if (segs_ok++)
1139 duparg2("segs", *argv);
1140 strncpy(segbuf, *argv, 1024);
1141 segbuf[1023] = 0;
1142 if (!NEXT_ARG_OK())
1143 break;
1144 NEXT_ARG();
1145 if (strcmp(*argv, "hmac") == 0) {
1146 NEXT_ARG();
1147 if (hmac_ok++)
1148 duparg2("hmac", *argv);
1149 get_u32(&hmac, *argv, 0);
1150 } else {
1151 continue;
1152 }
1153 } else if (strcmp(*argv, "endpoint") == 0) {
1154 NEXT_ARG();
1155 if (bpf_ok++)
1156 duparg2("endpoint", *argv);
1157
1158 if (lwt_parse_bpf(rta, len, &argc, &argv, SEG6_LOCAL_BPF,
1159 BPF_PROG_TYPE_LWT_SEG6LOCAL) < 0)
1160 exit(-1);
1161 } else {
1162 break;
1163 }
1164 if (ret)
1165 return ret;
1166 argc--; argv++;
1167 }
1168
1169 if (!action) {
1170 fprintf(stderr, "Missing action type\n");
1171 exit(-1);
1172 }
1173
1174 if (srh_ok) {
1175 int srhlen;
1176
1177 srh = parse_srh(segbuf, hmac,
1178 action == SEG6_LOCAL_ACTION_END_B6_ENCAP);
1179 srhlen = (srh->hdrlen + 1) << 3;
1180 ret = rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen);
1181 free(srh);
1182 }
1183
1184 *argcp = argc + 1;
1185 *argvp = argv - 1;
1186
1187 return ret;
1188}
1189
1190static int parse_encap_mpls(struct rtattr *rta, size_t len,
1191 int *argcp, char ***argvp)
1192{
1193 inet_prefix addr;
1194 int argc = *argcp;
1195 char **argv = *argvp;
1196 int ttl_ok = 0;
1197
1198 if (get_addr(&addr, *argv, AF_MPLS)) {
1199 fprintf(stderr,
1200 "Error: an inet address is expected rather than \"%s\".\n",
1201 *argv);
1202 exit(1);
1203 }
1204
1205 if (rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST,
1206 &addr.data, addr.bytelen))
1207 return -1;
1208
1209 argc--;
1210 argv++;
1211
1212 while (argc > 0) {
1213 if (strcmp(*argv, "ttl") == 0) {
1214 __u8 ttl;
1215
1216 NEXT_ARG();
1217 if (ttl_ok++)
1218 duparg2("ttl", *argv);
1219 if (get_u8(&ttl, *argv, 0))
1220 invarg("\"ttl\" value is invalid\n", *argv);
1221 if (rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl))
1222 return -1;
1223 } else {
1224 break;
1225 }
1226 argc--; argv++;
1227 }
1228
1229
1230
1231
1232
1233 *argcp = argc + 1;
1234 *argvp = argv - 1;
1235
1236 return 0;
1237}
1238
1239static int lwtunnel_parse_geneve_opt(char *str, size_t len, struct rtattr *rta)
1240{
1241 struct rtattr *nest;
1242 char *token;
1243 int i, err;
1244
1245 nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_GENEVE | NLA_F_NESTED);
1246 i = 1;
1247 token = strsep(&str, ":");
1248 while (token) {
1249 switch (i) {
1250 case LWTUNNEL_IP_OPT_GENEVE_CLASS:
1251 {
1252 __be16 opt_class;
1253
1254 if (!strlen(token))
1255 break;
1256 err = get_be16(&opt_class, token, 0);
1257 if (err)
1258 return err;
1259
1260 rta_addattr16(rta, len, i, opt_class);
1261 break;
1262 }
1263 case LWTUNNEL_IP_OPT_GENEVE_TYPE:
1264 {
1265 __u8 opt_type;
1266
1267 if (!strlen(token))
1268 break;
1269 err = get_u8(&opt_type, token, 0);
1270 if (err)
1271 return err;
1272
1273 rta_addattr8(rta, len, i, opt_type);
1274 break;
1275 }
1276 case LWTUNNEL_IP_OPT_GENEVE_DATA:
1277 {
1278 size_t token_len = strlen(token);
1279 __u8 *opts;
1280
1281 if (!token_len)
1282 break;
1283 opts = malloc(token_len / 2);
1284 if (!opts)
1285 return -1;
1286 if (hex2mem(token, opts, token_len / 2) < 0) {
1287 free(opts);
1288 return -1;
1289 }
1290 rta_addattr_l(rta, len, i, opts, token_len / 2);
1291 free(opts);
1292
1293 break;
1294 }
1295 default:
1296 fprintf(stderr, "Unknown \"geneve_opts\" type\n");
1297 return -1;
1298 }
1299
1300 token = strsep(&str, ":");
1301 i++;
1302 }
1303 rta_nest_end(rta, nest);
1304
1305 return 0;
1306}
1307
1308static int lwtunnel_parse_geneve_opts(char *str, size_t len, struct rtattr *rta)
1309{
1310 char *token;
1311 int err;
1312
1313 token = strsep(&str, ",");
1314 while (token) {
1315 err = lwtunnel_parse_geneve_opt(token, len, rta);
1316 if (err)
1317 return err;
1318
1319 token = strsep(&str, ",");
1320 }
1321
1322 return 0;
1323}
1324
1325static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta)
1326{
1327 struct rtattr *nest;
1328 __u32 gbp;
1329 int err;
1330
1331 nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_VXLAN | NLA_F_NESTED);
1332 err = get_u32(&gbp, str, 0);
1333 if (err)
1334 return err;
1335 rta_addattr32(rta, len, LWTUNNEL_IP_OPT_VXLAN_GBP, gbp);
1336
1337 rta_nest_end(rta, nest);
1338 return 0;
1339}
1340
1341static int lwtunnel_parse_erspan_opts(char *str, size_t len, struct rtattr *rta)
1342{
1343 struct rtattr *nest;
1344 char *token;
1345 int i, err;
1346
1347 nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_ERSPAN | NLA_F_NESTED);
1348 i = 1;
1349 token = strsep(&str, ":");
1350 while (token) {
1351 switch (i) {
1352 case LWTUNNEL_IP_OPT_ERSPAN_VER:
1353 {
1354 __u8 opt_type;
1355
1356 if (!strlen(token))
1357 break;
1358 err = get_u8(&opt_type, token, 0);
1359 if (err)
1360 return err;
1361
1362 rta_addattr8(rta, len, i, opt_type);
1363 break;
1364 }
1365 case LWTUNNEL_IP_OPT_ERSPAN_INDEX:
1366 {
1367 __be32 opt_class;
1368
1369 if (!strlen(token))
1370 break;
1371 err = get_be32(&opt_class, token, 0);
1372 if (err)
1373 return err;
1374
1375 rta_addattr32(rta, len, i, opt_class);
1376 break;
1377 }
1378 case LWTUNNEL_IP_OPT_ERSPAN_DIR:
1379 {
1380 __u8 opt_type;
1381
1382 if (!strlen(token))
1383 break;
1384 err = get_u8(&opt_type, token, 0);
1385 if (err)
1386 return err;
1387
1388 rta_addattr8(rta, len, i, opt_type);
1389 break;
1390 }
1391 case LWTUNNEL_IP_OPT_ERSPAN_HWID:
1392 {
1393 __u8 opt_type;
1394
1395 if (!strlen(token))
1396 break;
1397 err = get_u8(&opt_type, token, 0);
1398 if (err)
1399 return err;
1400
1401 rta_addattr8(rta, len, i, opt_type);
1402 break;
1403 }
1404 default:
1405 fprintf(stderr, "Unknown \"geneve_opts\" type\n");
1406 return -1;
1407 }
1408
1409 token = strsep(&str, ":");
1410 i++;
1411 }
1412
1413 rta_nest_end(rta, nest);
1414 return 0;
1415}
1416
1417static int parse_encap_ip(struct rtattr *rta, size_t len,
1418 int *argcp, char ***argvp)
1419{
1420 int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
1421 int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0;
1422 char **argv = *argvp;
1423 int argc = *argcp;
1424 int ret = 0;
1425 __u16 flags = 0;
1426
1427 while (argc > 0) {
1428 if (strcmp(*argv, "id") == 0) {
1429 __u64 id;
1430
1431 NEXT_ARG();
1432 if (id_ok++)
1433 duparg2("id", *argv);
1434 if (get_be64(&id, *argv, 0))
1435 invarg("\"id\" value is invalid\n", *argv);
1436 ret = rta_addattr64(rta, len, LWTUNNEL_IP_ID, id);
1437 } else if (strcmp(*argv, "dst") == 0) {
1438 inet_prefix addr;
1439
1440 NEXT_ARG();
1441 if (dst_ok++)
1442 duparg2("dst", *argv);
1443 get_addr(&addr, *argv, AF_INET);
1444 ret = rta_addattr_l(rta, len, LWTUNNEL_IP_DST,
1445 &addr.data, addr.bytelen);
1446 } else if (strcmp(*argv, "src") == 0) {
1447 inet_prefix addr;
1448
1449 NEXT_ARG();
1450 if (src_ok++)
1451 duparg2("src", *argv);
1452 get_addr(&addr, *argv, AF_INET);
1453 ret = rta_addattr_l(rta, len, LWTUNNEL_IP_SRC,
1454 &addr.data, addr.bytelen);
1455 } else if (strcmp(*argv, "tos") == 0) {
1456 __u32 tos;
1457
1458 NEXT_ARG();
1459 if (tos_ok++)
1460 duparg2("tos", *argv);
1461 if (rtnl_dsfield_a2n(&tos, *argv))
1462 invarg("\"tos\" value is invalid\n", *argv);
1463 ret = rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos);
1464 } else if (strcmp(*argv, "ttl") == 0) {
1465 __u8 ttl;
1466
1467 NEXT_ARG();
1468 if (ttl_ok++)
1469 duparg2("ttl", *argv);
1470 if (get_u8(&ttl, *argv, 0))
1471 invarg("\"ttl\" value is invalid\n", *argv);
1472 ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
1473 } else if (strcmp(*argv, "geneve_opts") == 0) {
1474 struct rtattr *nest;
1475
1476 if (opts_ok++)
1477 duparg2("opts", *argv);
1478
1479 NEXT_ARG();
1480
1481 nest = rta_nest(rta, len,
1482 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1483 ret = lwtunnel_parse_geneve_opts(*argv, len, rta);
1484 if (ret)
1485 invarg("\"geneve_opts\" value is invalid\n",
1486 *argv);
1487 rta_nest_end(rta, nest);
1488 } else if (strcmp(*argv, "vxlan_opts") == 0) {
1489 struct rtattr *nest;
1490
1491 if (opts_ok++)
1492 duparg2("opts", *argv);
1493
1494 NEXT_ARG();
1495
1496 nest = rta_nest(rta, len,
1497 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1498 ret = lwtunnel_parse_vxlan_opts(*argv, len, rta);
1499 if (ret)
1500 invarg("\"vxlan_opts\" value is invalid\n",
1501 *argv);
1502 rta_nest_end(rta, nest);
1503 } else if (strcmp(*argv, "erspan_opts") == 0) {
1504 struct rtattr *nest;
1505
1506 if (opts_ok++)
1507 duparg2("opts", *argv);
1508
1509 NEXT_ARG();
1510
1511 nest = rta_nest(rta, len,
1512 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1513 ret = lwtunnel_parse_erspan_opts(*argv, len, rta);
1514 if (ret)
1515 invarg("\"erspan_opts\" value is invalid\n",
1516 *argv);
1517 rta_nest_end(rta, nest);
1518 } else if (strcmp(*argv, "key") == 0) {
1519 if (key_ok++)
1520 duparg2("key", *argv);
1521 flags |= TUNNEL_KEY;
1522 } else if (strcmp(*argv, "csum") == 0) {
1523 if (csum_ok++)
1524 duparg2("csum", *argv);
1525 flags |= TUNNEL_CSUM;
1526 } else if (strcmp(*argv, "seq") == 0) {
1527 if (seq_ok++)
1528 duparg2("seq", *argv);
1529 flags |= TUNNEL_SEQ;
1530 } else {
1531 break;
1532 }
1533 if (ret)
1534 break;
1535 argc--; argv++;
1536 }
1537
1538 if (flags)
1539 ret = rta_addattr16(rta, len, LWTUNNEL_IP_FLAGS, flags);
1540
1541
1542
1543
1544
1545 *argcp = argc + 1;
1546 *argvp = argv - 1;
1547
1548 return ret;
1549}
1550
1551static int parse_encap_ila(struct rtattr *rta, size_t len,
1552 int *argcp, char ***argvp)
1553{
1554 __u64 locator;
1555 int argc = *argcp;
1556 char **argv = *argvp;
1557 int ret = 0;
1558
1559 if (get_addr64(&locator, *argv) < 0) {
1560 fprintf(stderr, "Bad locator: %s\n", *argv);
1561 exit(1);
1562 }
1563
1564 argc--; argv++;
1565
1566 if (rta_addattr64(rta, len, ILA_ATTR_LOCATOR, locator))
1567 return -1;
1568
1569 while (argc > 0) {
1570 if (strcmp(*argv, "csum-mode") == 0) {
1571 int csum_mode;
1572
1573 NEXT_ARG();
1574
1575 csum_mode = ila_csum_name2mode(*argv);
1576 if (csum_mode < 0)
1577 invarg("\"csum-mode\" value is invalid\n",
1578 *argv);
1579
1580 ret = rta_addattr8(rta, len, ILA_ATTR_CSUM_MODE,
1581 (__u8)csum_mode);
1582
1583 argc--; argv++;
1584 } else if (strcmp(*argv, "ident-type") == 0) {
1585 int ident_type;
1586
1587 NEXT_ARG();
1588
1589 ident_type = ila_ident_name2type(*argv);
1590 if (ident_type < 0)
1591 invarg("\"ident-type\" value is invalid\n",
1592 *argv);
1593
1594 ret = rta_addattr8(rta, len, ILA_ATTR_IDENT_TYPE,
1595 (__u8)ident_type);
1596
1597 argc--; argv++;
1598 } else if (strcmp(*argv, "hook-type") == 0) {
1599 int hook_type;
1600
1601 NEXT_ARG();
1602
1603 hook_type = ila_hook_name2type(*argv);
1604 if (hook_type < 0)
1605 invarg("\"hook-type\" value is invalid\n",
1606 *argv);
1607
1608 ret = rta_addattr8(rta, len, ILA_ATTR_HOOK_TYPE,
1609 (__u8)hook_type);
1610
1611 argc--; argv++;
1612 } else {
1613 break;
1614 }
1615 if (ret)
1616 break;
1617 }
1618
1619
1620
1621
1622
1623 *argcp = argc + 1;
1624 *argvp = argv - 1;
1625
1626 return ret;
1627}
1628
1629static int parse_encap_ip6(struct rtattr *rta, size_t len,
1630 int *argcp, char ***argvp)
1631{
1632 int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
1633 int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0;
1634 char **argv = *argvp;
1635 int argc = *argcp;
1636 int ret = 0;
1637 __u16 flags = 0;
1638
1639 while (argc > 0) {
1640 if (strcmp(*argv, "id") == 0) {
1641 __u64 id;
1642
1643 NEXT_ARG();
1644 if (id_ok++)
1645 duparg2("id", *argv);
1646 if (get_be64(&id, *argv, 0))
1647 invarg("\"id\" value is invalid\n", *argv);
1648 ret = rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id);
1649 } else if (strcmp(*argv, "dst") == 0) {
1650 inet_prefix addr;
1651
1652 NEXT_ARG();
1653 if (dst_ok++)
1654 duparg2("dst", *argv);
1655 get_addr(&addr, *argv, AF_INET6);
1656 ret = rta_addattr_l(rta, len, LWTUNNEL_IP6_DST,
1657 &addr.data, addr.bytelen);
1658 } else if (strcmp(*argv, "src") == 0) {
1659 inet_prefix addr;
1660
1661 NEXT_ARG();
1662 if (src_ok++)
1663 duparg2("src", *argv);
1664 get_addr(&addr, *argv, AF_INET6);
1665 ret = rta_addattr_l(rta, len, LWTUNNEL_IP6_SRC,
1666 &addr.data, addr.bytelen);
1667 } else if (strcmp(*argv, "tc") == 0) {
1668 __u32 tc;
1669
1670 NEXT_ARG();
1671 if (tos_ok++)
1672 duparg2("tc", *argv);
1673 if (rtnl_dsfield_a2n(&tc, *argv))
1674 invarg("\"tc\" value is invalid\n", *argv);
1675 ret = rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc);
1676 } else if (strcmp(*argv, "hoplimit") == 0) {
1677 __u8 hoplimit;
1678
1679 NEXT_ARG();
1680 if (ttl_ok++)
1681 duparg2("hoplimit", *argv);
1682 if (get_u8(&hoplimit, *argv, 0))
1683 invarg("\"hoplimit\" value is invalid\n",
1684 *argv);
1685 ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT,
1686 hoplimit);
1687 } else if (strcmp(*argv, "geneve_opts") == 0) {
1688 struct rtattr *nest;
1689
1690 if (opts_ok++)
1691 duparg2("opts", *argv);
1692
1693 NEXT_ARG();
1694
1695 nest = rta_nest(rta, len,
1696 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1697 ret = lwtunnel_parse_geneve_opts(*argv, len, rta);
1698 if (ret)
1699 invarg("\"geneve_opts\" value is invalid\n",
1700 *argv);
1701 rta_nest_end(rta, nest);
1702 } else if (strcmp(*argv, "vxlan_opts") == 0) {
1703 struct rtattr *nest;
1704
1705 if (opts_ok++)
1706 duparg2("opts", *argv);
1707
1708 NEXT_ARG();
1709
1710 nest = rta_nest(rta, len,
1711 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1712 ret = lwtunnel_parse_vxlan_opts(*argv, len, rta);
1713 if (ret)
1714 invarg("\"vxlan_opts\" value is invalid\n",
1715 *argv);
1716 rta_nest_end(rta, nest);
1717 } else if (strcmp(*argv, "erspan_opts") == 0) {
1718 struct rtattr *nest;
1719
1720 if (opts_ok++)
1721 duparg2("opts", *argv);
1722
1723 NEXT_ARG();
1724
1725 nest = rta_nest(rta, len,
1726 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1727 ret = lwtunnel_parse_erspan_opts(*argv, len, rta);
1728 if (ret)
1729 invarg("\"erspan_opts\" value is invalid\n",
1730 *argv);
1731 rta_nest_end(rta, nest);
1732 } else if (strcmp(*argv, "key") == 0) {
1733 if (key_ok++)
1734 duparg2("key", *argv);
1735 flags |= TUNNEL_KEY;
1736 } else if (strcmp(*argv, "csum") == 0) {
1737 if (csum_ok++)
1738 duparg2("csum", *argv);
1739 flags |= TUNNEL_CSUM;
1740 } else if (strcmp(*argv, "seq") == 0) {
1741 if (seq_ok++)
1742 duparg2("seq", *argv);
1743 flags |= TUNNEL_SEQ;
1744 } else {
1745 break;
1746 }
1747 if (ret)
1748 break;
1749 argc--; argv++;
1750 }
1751
1752 if (flags)
1753 ret = rta_addattr16(rta, len, LWTUNNEL_IP6_FLAGS, flags);
1754
1755
1756
1757
1758
1759 *argcp = argc + 1;
1760 *argvp = argv - 1;
1761
1762 return ret;
1763}
1764
1765static void lwt_bpf_usage(void)
1766{
1767 fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");
1768 fprintf(stderr, "BPF := obj FILE [ section NAME ] [ verbose ]\n");
1769 exit(-1);
1770}
1771
1772static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp,
1773 char ***argvp)
1774{
1775 char **argv = *argvp;
1776 int argc = *argcp;
1777 int headroom_set = 0;
1778
1779 while (argc > 0) {
1780 if (strcmp(*argv, "in") == 0) {
1781 NEXT_ARG();
1782 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_IN,
1783 BPF_PROG_TYPE_LWT_IN) < 0)
1784 return -1;
1785 } else if (strcmp(*argv, "out") == 0) {
1786 NEXT_ARG();
1787 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_OUT,
1788 BPF_PROG_TYPE_LWT_OUT) < 0)
1789 return -1;
1790 } else if (strcmp(*argv, "xmit") == 0) {
1791 NEXT_ARG();
1792 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_XMIT,
1793 BPF_PROG_TYPE_LWT_XMIT) < 0)
1794 return -1;
1795 } else if (strcmp(*argv, "headroom") == 0) {
1796 unsigned int headroom;
1797
1798 NEXT_ARG();
1799 if (get_unsigned(&headroom, *argv, 0) || headroom == 0)
1800 invarg("headroom is invalid\n", *argv);
1801 if (!headroom_set)
1802 rta_addattr32(rta, len, LWT_BPF_XMIT_HEADROOM,
1803 headroom);
1804 headroom_set = 1;
1805 } else if (strcmp(*argv, "help") == 0) {
1806 lwt_bpf_usage();
1807 } else {
1808 break;
1809 }
1810 NEXT_ARG_FWD();
1811 }
1812
1813
1814
1815
1816
1817 *argcp = argc + 1;
1818 *argvp = argv - 1;
1819
1820 return 0;
1821}
1822
1823int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp,
1824 int encap_attr, int encap_type_attr)
1825{
1826 struct rtattr *nest;
1827 int argc = *argcp;
1828 char **argv = *argvp;
1829 __u16 type;
1830 int ret = 0;
1831
1832 NEXT_ARG();
1833 type = read_encap_type(*argv);
1834 if (!type)
1835 invarg("\"encap type\" value is invalid\n", *argv);
1836
1837 NEXT_ARG();
1838 if (argc <= 1) {
1839 fprintf(stderr,
1840 "Error: unexpected end of line after \"encap\"\n");
1841 exit(-1);
1842 }
1843
1844 nest = rta_nest(rta, len, encap_attr);
1845 switch (type) {
1846 case LWTUNNEL_ENCAP_MPLS:
1847 ret = parse_encap_mpls(rta, len, &argc, &argv);
1848 break;
1849 case LWTUNNEL_ENCAP_IP:
1850 ret = parse_encap_ip(rta, len, &argc, &argv);
1851 break;
1852 case LWTUNNEL_ENCAP_ILA:
1853 ret = parse_encap_ila(rta, len, &argc, &argv);
1854 break;
1855 case LWTUNNEL_ENCAP_IP6:
1856 ret = parse_encap_ip6(rta, len, &argc, &argv);
1857 break;
1858 case LWTUNNEL_ENCAP_BPF:
1859 if (parse_encap_bpf(rta, len, &argc, &argv) < 0)
1860 exit(-1);
1861 break;
1862 case LWTUNNEL_ENCAP_SEG6:
1863 ret = parse_encap_seg6(rta, len, &argc, &argv);
1864 break;
1865 case LWTUNNEL_ENCAP_SEG6_LOCAL:
1866 ret = parse_encap_seg6local(rta, len, &argc, &argv);
1867 break;
1868 case LWTUNNEL_ENCAP_RPL:
1869 ret = parse_encap_rpl(rta, len, &argc, &argv);
1870 break;
1871 case LWTUNNEL_ENCAP_IOAM6:
1872 ret = parse_encap_ioam6(rta, len, &argc, &argv);
1873 break;
1874 default:
1875 fprintf(stderr, "Error: unsupported encap type\n");
1876 break;
1877 }
1878 if (ret)
1879 return ret;
1880
1881 rta_nest_end(rta, nest);
1882
1883 ret = rta_addattr16(rta, len, encap_type_attr, type);
1884
1885 *argcp = argc;
1886 *argvp = argv;
1887
1888 return ret;
1889}
1890