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