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