]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/iproute_lwtunnel.c
vdpa: add .gitignore
[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 if (rtnl_rttable_a2n(&table, *argv))
895 invarg("invalid table id\n", *argv);
896 ret = rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table);
897 } else if (strcmp(*argv, "vrftable") == 0) {
898 NEXT_ARG();
899 if (vrftable_ok++)
900 duparg2("vrftable", *argv);
901 if (rtnl_rttable_a2n(&vrftable, *argv))
902 invarg("invalid vrf table id\n", *argv);
903 ret = rta_addattr32(rta, len, SEG6_LOCAL_VRFTABLE,
904 vrftable);
905 } else if (strcmp(*argv, "nh4") == 0) {
906 NEXT_ARG();
907 if (nh4_ok++)
908 duparg2("nh4", *argv);
909 get_addr(&addr, *argv, AF_INET);
910 ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH4,
911 &addr.data, addr.bytelen);
912 } else if (strcmp(*argv, "nh6") == 0) {
913 NEXT_ARG();
914 if (nh6_ok++)
915 duparg2("nh6", *argv);
916 get_addr(&addr, *argv, AF_INET6);
917 ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH6,
918 &addr.data, addr.bytelen);
919 } else if (strcmp(*argv, "iif") == 0) {
920 NEXT_ARG();
921 if (iif_ok++)
922 duparg2("iif", *argv);
923 iif = ll_name_to_index(*argv);
924 if (!iif)
925 exit(nodev(*argv));
926 ret = rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif);
927 } else if (strcmp(*argv, "oif") == 0) {
928 NEXT_ARG();
929 if (oif_ok++)
930 duparg2("oif", *argv);
931 oif = ll_name_to_index(*argv);
932 if (!oif)
933 exit(nodev(*argv));
934 ret = rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif);
935 } else if (strcmp(*argv, "srh") == 0) {
936 NEXT_ARG();
937 if (srh_ok++)
938 duparg2("srh", *argv);
939 if (strcmp(*argv, "segs") != 0)
940 invarg("missing \"segs\" attribute for srh\n",
941 *argv);
942 NEXT_ARG();
943 if (segs_ok++)
944 duparg2("segs", *argv);
945 strncpy(segbuf, *argv, 1024);
946 segbuf[1023] = 0;
947 if (!NEXT_ARG_OK())
948 break;
949 NEXT_ARG();
950 if (strcmp(*argv, "hmac") == 0) {
951 NEXT_ARG();
952 if (hmac_ok++)
953 duparg2("hmac", *argv);
954 get_u32(&hmac, *argv, 0);
955 } else {
956 continue;
957 }
958 } else if (strcmp(*argv, "endpoint") == 0) {
959 NEXT_ARG();
960 if (bpf_ok++)
961 duparg2("endpoint", *argv);
962
963 if (lwt_parse_bpf(rta, len, &argc, &argv, SEG6_LOCAL_BPF,
964 BPF_PROG_TYPE_LWT_SEG6LOCAL) < 0)
965 exit(-1);
966 } else {
967 break;
968 }
969 if (ret)
970 return ret;
971 argc--; argv++;
972 }
973
974 if (!action) {
975 fprintf(stderr, "Missing action type\n");
976 exit(-1);
977 }
978
979 if (srh_ok) {
980 int srhlen;
981
982 srh = parse_srh(segbuf, hmac,
983 action == SEG6_LOCAL_ACTION_END_B6_ENCAP);
984 srhlen = (srh->hdrlen + 1) << 3;
985 ret = rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen);
986 free(srh);
987 }
988
989 *argcp = argc + 1;
990 *argvp = argv - 1;
991
992 return ret;
993 }
994
995 static int parse_encap_mpls(struct rtattr *rta, size_t len,
996 int *argcp, char ***argvp)
997 {
998 inet_prefix addr;
999 int argc = *argcp;
1000 char **argv = *argvp;
1001 int ttl_ok = 0;
1002
1003 if (get_addr(&addr, *argv, AF_MPLS)) {
1004 fprintf(stderr,
1005 "Error: an inet address is expected rather than \"%s\".\n",
1006 *argv);
1007 exit(1);
1008 }
1009
1010 if (rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST,
1011 &addr.data, addr.bytelen))
1012 return -1;
1013
1014 argc--;
1015 argv++;
1016
1017 while (argc > 0) {
1018 if (strcmp(*argv, "ttl") == 0) {
1019 __u8 ttl;
1020
1021 NEXT_ARG();
1022 if (ttl_ok++)
1023 duparg2("ttl", *argv);
1024 if (get_u8(&ttl, *argv, 0))
1025 invarg("\"ttl\" value is invalid\n", *argv);
1026 if (rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl))
1027 return -1;
1028 } else {
1029 break;
1030 }
1031 argc--; argv++;
1032 }
1033
1034 /* argv is currently the first unparsed argument,
1035 * but the lwt_parse_encap() caller will move to the next,
1036 * so step back
1037 */
1038 *argcp = argc + 1;
1039 *argvp = argv - 1;
1040
1041 return 0;
1042 }
1043
1044 static int lwtunnel_parse_geneve_opt(char *str, size_t len, struct rtattr *rta)
1045 {
1046 struct rtattr *nest;
1047 char *token;
1048 int i, err;
1049
1050 nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_GENEVE | NLA_F_NESTED);
1051 i = 1;
1052 token = strsep(&str, ":");
1053 while (token) {
1054 switch (i) {
1055 case LWTUNNEL_IP_OPT_GENEVE_CLASS:
1056 {
1057 __be16 opt_class;
1058
1059 if (!strlen(token))
1060 break;
1061 err = get_be16(&opt_class, token, 0);
1062 if (err)
1063 return err;
1064
1065 rta_addattr16(rta, len, i, opt_class);
1066 break;
1067 }
1068 case LWTUNNEL_IP_OPT_GENEVE_TYPE:
1069 {
1070 __u8 opt_type;
1071
1072 if (!strlen(token))
1073 break;
1074 err = get_u8(&opt_type, token, 0);
1075 if (err)
1076 return err;
1077
1078 rta_addattr8(rta, len, i, opt_type);
1079 break;
1080 }
1081 case LWTUNNEL_IP_OPT_GENEVE_DATA:
1082 {
1083 size_t token_len = strlen(token);
1084 __u8 *opts;
1085
1086 if (!token_len)
1087 break;
1088 opts = malloc(token_len / 2);
1089 if (!opts)
1090 return -1;
1091 if (hex2mem(token, opts, token_len / 2) < 0) {
1092 free(opts);
1093 return -1;
1094 }
1095 rta_addattr_l(rta, len, i, opts, token_len / 2);
1096 free(opts);
1097
1098 break;
1099 }
1100 default:
1101 fprintf(stderr, "Unknown \"geneve_opts\" type\n");
1102 return -1;
1103 }
1104
1105 token = strsep(&str, ":");
1106 i++;
1107 }
1108 rta_nest_end(rta, nest);
1109
1110 return 0;
1111 }
1112
1113 static int lwtunnel_parse_geneve_opts(char *str, size_t len, struct rtattr *rta)
1114 {
1115 char *token;
1116 int err;
1117
1118 token = strsep(&str, ",");
1119 while (token) {
1120 err = lwtunnel_parse_geneve_opt(token, len, rta);
1121 if (err)
1122 return err;
1123
1124 token = strsep(&str, ",");
1125 }
1126
1127 return 0;
1128 }
1129
1130 static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta)
1131 {
1132 struct rtattr *nest;
1133 __u32 gbp;
1134 int err;
1135
1136 nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_VXLAN | NLA_F_NESTED);
1137 err = get_u32(&gbp, str, 0);
1138 if (err)
1139 return err;
1140 rta_addattr32(rta, len, LWTUNNEL_IP_OPT_VXLAN_GBP, gbp);
1141
1142 rta_nest_end(rta, nest);
1143 return 0;
1144 }
1145
1146 static int lwtunnel_parse_erspan_opts(char *str, size_t len, struct rtattr *rta)
1147 {
1148 struct rtattr *nest;
1149 char *token;
1150 int i, err;
1151
1152 nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_ERSPAN | NLA_F_NESTED);
1153 i = 1;
1154 token = strsep(&str, ":");
1155 while (token) {
1156 switch (i) {
1157 case LWTUNNEL_IP_OPT_ERSPAN_VER:
1158 {
1159 __u8 opt_type;
1160
1161 if (!strlen(token))
1162 break;
1163 err = get_u8(&opt_type, token, 0);
1164 if (err)
1165 return err;
1166
1167 rta_addattr8(rta, len, i, opt_type);
1168 break;
1169 }
1170 case LWTUNNEL_IP_OPT_ERSPAN_INDEX:
1171 {
1172 __be32 opt_class;
1173
1174 if (!strlen(token))
1175 break;
1176 err = get_be32(&opt_class, token, 0);
1177 if (err)
1178 return err;
1179
1180 rta_addattr32(rta, len, i, opt_class);
1181 break;
1182 }
1183 case LWTUNNEL_IP_OPT_ERSPAN_DIR:
1184 {
1185 __u8 opt_type;
1186
1187 if (!strlen(token))
1188 break;
1189 err = get_u8(&opt_type, token, 0);
1190 if (err)
1191 return err;
1192
1193 rta_addattr8(rta, len, i, opt_type);
1194 break;
1195 }
1196 case LWTUNNEL_IP_OPT_ERSPAN_HWID:
1197 {
1198 __u8 opt_type;
1199
1200 if (!strlen(token))
1201 break;
1202 err = get_u8(&opt_type, token, 0);
1203 if (err)
1204 return err;
1205
1206 rta_addattr8(rta, len, i, opt_type);
1207 break;
1208 }
1209 default:
1210 fprintf(stderr, "Unknown \"geneve_opts\" type\n");
1211 return -1;
1212 }
1213
1214 token = strsep(&str, ":");
1215 i++;
1216 }
1217
1218 rta_nest_end(rta, nest);
1219 return 0;
1220 }
1221
1222 static int parse_encap_ip(struct rtattr *rta, size_t len,
1223 int *argcp, char ***argvp)
1224 {
1225 int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
1226 int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0;
1227 char **argv = *argvp;
1228 int argc = *argcp;
1229 int ret = 0;
1230 __u16 flags = 0;
1231
1232 while (argc > 0) {
1233 if (strcmp(*argv, "id") == 0) {
1234 __u64 id;
1235
1236 NEXT_ARG();
1237 if (id_ok++)
1238 duparg2("id", *argv);
1239 if (get_be64(&id, *argv, 0))
1240 invarg("\"id\" value is invalid\n", *argv);
1241 ret = rta_addattr64(rta, len, LWTUNNEL_IP_ID, id);
1242 } else if (strcmp(*argv, "dst") == 0) {
1243 inet_prefix addr;
1244
1245 NEXT_ARG();
1246 if (dst_ok++)
1247 duparg2("dst", *argv);
1248 get_addr(&addr, *argv, AF_INET);
1249 ret = rta_addattr_l(rta, len, LWTUNNEL_IP_DST,
1250 &addr.data, addr.bytelen);
1251 } else if (strcmp(*argv, "src") == 0) {
1252 inet_prefix addr;
1253
1254 NEXT_ARG();
1255 if (src_ok++)
1256 duparg2("src", *argv);
1257 get_addr(&addr, *argv, AF_INET);
1258 ret = rta_addattr_l(rta, len, LWTUNNEL_IP_SRC,
1259 &addr.data, addr.bytelen);
1260 } else if (strcmp(*argv, "tos") == 0) {
1261 __u32 tos;
1262
1263 NEXT_ARG();
1264 if (tos_ok++)
1265 duparg2("tos", *argv);
1266 if (rtnl_dsfield_a2n(&tos, *argv))
1267 invarg("\"tos\" value is invalid\n", *argv);
1268 ret = rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos);
1269 } else if (strcmp(*argv, "ttl") == 0) {
1270 __u8 ttl;
1271
1272 NEXT_ARG();
1273 if (ttl_ok++)
1274 duparg2("ttl", *argv);
1275 if (get_u8(&ttl, *argv, 0))
1276 invarg("\"ttl\" value is invalid\n", *argv);
1277 ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
1278 } else if (strcmp(*argv, "geneve_opts") == 0) {
1279 struct rtattr *nest;
1280
1281 if (opts_ok++)
1282 duparg2("opts", *argv);
1283
1284 NEXT_ARG();
1285
1286 nest = rta_nest(rta, len,
1287 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1288 ret = lwtunnel_parse_geneve_opts(*argv, len, rta);
1289 if (ret)
1290 invarg("\"geneve_opts\" value is invalid\n",
1291 *argv);
1292 rta_nest_end(rta, nest);
1293 } else if (strcmp(*argv, "vxlan_opts") == 0) {
1294 struct rtattr *nest;
1295
1296 if (opts_ok++)
1297 duparg2("opts", *argv);
1298
1299 NEXT_ARG();
1300
1301 nest = rta_nest(rta, len,
1302 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1303 ret = lwtunnel_parse_vxlan_opts(*argv, len, rta);
1304 if (ret)
1305 invarg("\"vxlan_opts\" value is invalid\n",
1306 *argv);
1307 rta_nest_end(rta, nest);
1308 } else if (strcmp(*argv, "erspan_opts") == 0) {
1309 struct rtattr *nest;
1310
1311 if (opts_ok++)
1312 duparg2("opts", *argv);
1313
1314 NEXT_ARG();
1315
1316 nest = rta_nest(rta, len,
1317 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1318 ret = lwtunnel_parse_erspan_opts(*argv, len, rta);
1319 if (ret)
1320 invarg("\"erspan_opts\" value is invalid\n",
1321 *argv);
1322 rta_nest_end(rta, nest);
1323 } else if (strcmp(*argv, "key") == 0) {
1324 if (key_ok++)
1325 duparg2("key", *argv);
1326 flags |= TUNNEL_KEY;
1327 } else if (strcmp(*argv, "csum") == 0) {
1328 if (csum_ok++)
1329 duparg2("csum", *argv);
1330 flags |= TUNNEL_CSUM;
1331 } else if (strcmp(*argv, "seq") == 0) {
1332 if (seq_ok++)
1333 duparg2("seq", *argv);
1334 flags |= TUNNEL_SEQ;
1335 } else {
1336 break;
1337 }
1338 if (ret)
1339 break;
1340 argc--; argv++;
1341 }
1342
1343 if (flags)
1344 ret = rta_addattr16(rta, len, LWTUNNEL_IP_FLAGS, flags);
1345
1346 /* argv is currently the first unparsed argument,
1347 * but the lwt_parse_encap() caller will move to the next,
1348 * so step back
1349 */
1350 *argcp = argc + 1;
1351 *argvp = argv - 1;
1352
1353 return ret;
1354 }
1355
1356 static int parse_encap_ila(struct rtattr *rta, size_t len,
1357 int *argcp, char ***argvp)
1358 {
1359 __u64 locator;
1360 int argc = *argcp;
1361 char **argv = *argvp;
1362 int ret = 0;
1363
1364 if (get_addr64(&locator, *argv) < 0) {
1365 fprintf(stderr, "Bad locator: %s\n", *argv);
1366 exit(1);
1367 }
1368
1369 argc--; argv++;
1370
1371 if (rta_addattr64(rta, len, ILA_ATTR_LOCATOR, locator))
1372 return -1;
1373
1374 while (argc > 0) {
1375 if (strcmp(*argv, "csum-mode") == 0) {
1376 int csum_mode;
1377
1378 NEXT_ARG();
1379
1380 csum_mode = ila_csum_name2mode(*argv);
1381 if (csum_mode < 0)
1382 invarg("\"csum-mode\" value is invalid\n",
1383 *argv);
1384
1385 ret = rta_addattr8(rta, len, ILA_ATTR_CSUM_MODE,
1386 (__u8)csum_mode);
1387
1388 argc--; argv++;
1389 } else if (strcmp(*argv, "ident-type") == 0) {
1390 int ident_type;
1391
1392 NEXT_ARG();
1393
1394 ident_type = ila_ident_name2type(*argv);
1395 if (ident_type < 0)
1396 invarg("\"ident-type\" value is invalid\n",
1397 *argv);
1398
1399 ret = rta_addattr8(rta, len, ILA_ATTR_IDENT_TYPE,
1400 (__u8)ident_type);
1401
1402 argc--; argv++;
1403 } else if (strcmp(*argv, "hook-type") == 0) {
1404 int hook_type;
1405
1406 NEXT_ARG();
1407
1408 hook_type = ila_hook_name2type(*argv);
1409 if (hook_type < 0)
1410 invarg("\"hook-type\" value is invalid\n",
1411 *argv);
1412
1413 ret = rta_addattr8(rta, len, ILA_ATTR_HOOK_TYPE,
1414 (__u8)hook_type);
1415
1416 argc--; argv++;
1417 } else {
1418 break;
1419 }
1420 if (ret)
1421 break;
1422 }
1423
1424 /* argv is currently the first unparsed argument,
1425 * but the lwt_parse_encap() caller will move to the next,
1426 * so step back
1427 */
1428 *argcp = argc + 1;
1429 *argvp = argv - 1;
1430
1431 return ret;
1432 }
1433
1434 static int parse_encap_ip6(struct rtattr *rta, size_t len,
1435 int *argcp, char ***argvp)
1436 {
1437 int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
1438 int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0;
1439 char **argv = *argvp;
1440 int argc = *argcp;
1441 int ret = 0;
1442 __u16 flags = 0;
1443
1444 while (argc > 0) {
1445 if (strcmp(*argv, "id") == 0) {
1446 __u64 id;
1447
1448 NEXT_ARG();
1449 if (id_ok++)
1450 duparg2("id", *argv);
1451 if (get_be64(&id, *argv, 0))
1452 invarg("\"id\" value is invalid\n", *argv);
1453 ret = rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id);
1454 } else if (strcmp(*argv, "dst") == 0) {
1455 inet_prefix addr;
1456
1457 NEXT_ARG();
1458 if (dst_ok++)
1459 duparg2("dst", *argv);
1460 get_addr(&addr, *argv, AF_INET6);
1461 ret = rta_addattr_l(rta, len, LWTUNNEL_IP6_DST,
1462 &addr.data, addr.bytelen);
1463 } else if (strcmp(*argv, "src") == 0) {
1464 inet_prefix addr;
1465
1466 NEXT_ARG();
1467 if (src_ok++)
1468 duparg2("src", *argv);
1469 get_addr(&addr, *argv, AF_INET6);
1470 ret = rta_addattr_l(rta, len, LWTUNNEL_IP6_SRC,
1471 &addr.data, addr.bytelen);
1472 } else if (strcmp(*argv, "tc") == 0) {
1473 __u32 tc;
1474
1475 NEXT_ARG();
1476 if (tos_ok++)
1477 duparg2("tc", *argv);
1478 if (rtnl_dsfield_a2n(&tc, *argv))
1479 invarg("\"tc\" value is invalid\n", *argv);
1480 ret = rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc);
1481 } else if (strcmp(*argv, "hoplimit") == 0) {
1482 __u8 hoplimit;
1483
1484 NEXT_ARG();
1485 if (ttl_ok++)
1486 duparg2("hoplimit", *argv);
1487 if (get_u8(&hoplimit, *argv, 0))
1488 invarg("\"hoplimit\" value is invalid\n",
1489 *argv);
1490 ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT,
1491 hoplimit);
1492 } else if (strcmp(*argv, "geneve_opts") == 0) {
1493 struct rtattr *nest;
1494
1495 if (opts_ok++)
1496 duparg2("opts", *argv);
1497
1498 NEXT_ARG();
1499
1500 nest = rta_nest(rta, len,
1501 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1502 ret = lwtunnel_parse_geneve_opts(*argv, len, rta);
1503 if (ret)
1504 invarg("\"geneve_opts\" value is invalid\n",
1505 *argv);
1506 rta_nest_end(rta, nest);
1507 } else if (strcmp(*argv, "vxlan_opts") == 0) {
1508 struct rtattr *nest;
1509
1510 if (opts_ok++)
1511 duparg2("opts", *argv);
1512
1513 NEXT_ARG();
1514
1515 nest = rta_nest(rta, len,
1516 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1517 ret = lwtunnel_parse_vxlan_opts(*argv, len, rta);
1518 if (ret)
1519 invarg("\"vxlan_opts\" value is invalid\n",
1520 *argv);
1521 rta_nest_end(rta, nest);
1522 } else if (strcmp(*argv, "erspan_opts") == 0) {
1523 struct rtattr *nest;
1524
1525 if (opts_ok++)
1526 duparg2("opts", *argv);
1527
1528 NEXT_ARG();
1529
1530 nest = rta_nest(rta, len,
1531 LWTUNNEL_IP_OPTS | NLA_F_NESTED);
1532 ret = lwtunnel_parse_erspan_opts(*argv, len, rta);
1533 if (ret)
1534 invarg("\"erspan_opts\" value is invalid\n",
1535 *argv);
1536 rta_nest_end(rta, nest);
1537 } else if (strcmp(*argv, "key") == 0) {
1538 if (key_ok++)
1539 duparg2("key", *argv);
1540 flags |= TUNNEL_KEY;
1541 } else if (strcmp(*argv, "csum") == 0) {
1542 if (csum_ok++)
1543 duparg2("csum", *argv);
1544 flags |= TUNNEL_CSUM;
1545 } else if (strcmp(*argv, "seq") == 0) {
1546 if (seq_ok++)
1547 duparg2("seq", *argv);
1548 flags |= TUNNEL_SEQ;
1549 } else {
1550 break;
1551 }
1552 if (ret)
1553 break;
1554 argc--; argv++;
1555 }
1556
1557 if (flags)
1558 ret = rta_addattr16(rta, len, LWTUNNEL_IP6_FLAGS, flags);
1559
1560 /* argv is currently the first unparsed argument,
1561 * but the lwt_parse_encap() caller will move to the next,
1562 * so step back
1563 */
1564 *argcp = argc + 1;
1565 *argvp = argv - 1;
1566
1567 return ret;
1568 }
1569
1570 static void lwt_bpf_usage(void)
1571 {
1572 fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");
1573 fprintf(stderr, "BPF := obj FILE [ section NAME ] [ verbose ]\n");
1574 exit(-1);
1575 }
1576
1577 static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp,
1578 char ***argvp)
1579 {
1580 char **argv = *argvp;
1581 int argc = *argcp;
1582 int headroom_set = 0;
1583
1584 while (argc > 0) {
1585 if (strcmp(*argv, "in") == 0) {
1586 NEXT_ARG();
1587 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_IN,
1588 BPF_PROG_TYPE_LWT_IN) < 0)
1589 return -1;
1590 } else if (strcmp(*argv, "out") == 0) {
1591 NEXT_ARG();
1592 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_OUT,
1593 BPF_PROG_TYPE_LWT_OUT) < 0)
1594 return -1;
1595 } else if (strcmp(*argv, "xmit") == 0) {
1596 NEXT_ARG();
1597 if (lwt_parse_bpf(rta, len, &argc, &argv, LWT_BPF_XMIT,
1598 BPF_PROG_TYPE_LWT_XMIT) < 0)
1599 return -1;
1600 } else if (strcmp(*argv, "headroom") == 0) {
1601 unsigned int headroom;
1602
1603 NEXT_ARG();
1604 if (get_unsigned(&headroom, *argv, 0) || headroom == 0)
1605 invarg("headroom is invalid\n", *argv);
1606 if (!headroom_set)
1607 rta_addattr32(rta, len, LWT_BPF_XMIT_HEADROOM,
1608 headroom);
1609 headroom_set = 1;
1610 } else if (strcmp(*argv, "help") == 0) {
1611 lwt_bpf_usage();
1612 } else {
1613 break;
1614 }
1615 NEXT_ARG_FWD();
1616 }
1617
1618 /* argv is currently the first unparsed argument,
1619 * but the lwt_parse_encap() caller will move to the next,
1620 * so step back
1621 */
1622 *argcp = argc + 1;
1623 *argvp = argv - 1;
1624
1625 return 0;
1626 }
1627
1628 int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp,
1629 int encap_attr, int encap_type_attr)
1630 {
1631 struct rtattr *nest;
1632 int argc = *argcp;
1633 char **argv = *argvp;
1634 __u16 type;
1635 int ret = 0;
1636
1637 NEXT_ARG();
1638 type = read_encap_type(*argv);
1639 if (!type)
1640 invarg("\"encap type\" value is invalid\n", *argv);
1641
1642 NEXT_ARG();
1643 if (argc <= 1) {
1644 fprintf(stderr,
1645 "Error: unexpected end of line after \"encap\"\n");
1646 exit(-1);
1647 }
1648
1649 nest = rta_nest(rta, len, encap_attr);
1650 switch (type) {
1651 case LWTUNNEL_ENCAP_MPLS:
1652 ret = parse_encap_mpls(rta, len, &argc, &argv);
1653 break;
1654 case LWTUNNEL_ENCAP_IP:
1655 ret = parse_encap_ip(rta, len, &argc, &argv);
1656 break;
1657 case LWTUNNEL_ENCAP_ILA:
1658 ret = parse_encap_ila(rta, len, &argc, &argv);
1659 break;
1660 case LWTUNNEL_ENCAP_IP6:
1661 ret = parse_encap_ip6(rta, len, &argc, &argv);
1662 break;
1663 case LWTUNNEL_ENCAP_BPF:
1664 if (parse_encap_bpf(rta, len, &argc, &argv) < 0)
1665 exit(-1);
1666 break;
1667 case LWTUNNEL_ENCAP_SEG6:
1668 ret = parse_encap_seg6(rta, len, &argc, &argv);
1669 break;
1670 case LWTUNNEL_ENCAP_SEG6_LOCAL:
1671 ret = parse_encap_seg6local(rta, len, &argc, &argv);
1672 break;
1673 case LWTUNNEL_ENCAP_RPL:
1674 ret = parse_encap_rpl(rta, len, &argc, &argv);
1675 break;
1676 default:
1677 fprintf(stderr, "Error: unsupported encap type\n");
1678 break;
1679 }
1680 if (ret)
1681 return ret;
1682
1683 rta_nest_end(rta, nest);
1684
1685 ret = rta_addattr16(rta, len, encap_type_attr, type);
1686
1687 *argcp = argc;
1688 *argvp = argv;
1689
1690 return ret;
1691 }