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