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