iproute2/ip/iproute_lwtunnel.c
<<
>>
Prefs
   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
  38static const char *format_encap_type(int type)
  39{
  40        switch (type) {
  41        case LWTUNNEL_ENCAP_MPLS:
  42                return "mpls";
  43        case LWTUNNEL_ENCAP_IP:
  44                return "ip";
  45        case LWTUNNEL_ENCAP_IP6:
  46                return "ip6";
  47        case LWTUNNEL_ENCAP_ILA:
  48                return "ila";
  49        case LWTUNNEL_ENCAP_BPF:
  50                return "bpf";
  51        case LWTUNNEL_ENCAP_SEG6:
  52                return "seg6";
  53        case LWTUNNEL_ENCAP_SEG6_LOCAL:
  54                return "seg6local";
  55        case LWTUNNEL_ENCAP_RPL:
  56                return "rpl";
  57        default:
  58                return "unknown";
  59        }
  60}
  61
  62static void encap_type_usage(void)
  63{
  64        int i;
  65
  66        fprintf(stderr, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n");
  67
  68        for (i = 1; i <= LWTUNNEL_ENCAP_MAX; i++)
  69                fprintf(stderr, "%s %s\n", format_encap_type(i),
  70                        i == 1 ? "TYPE := " : "      ");
  71
  72        exit(-1);
  73}
  74
  75static int read_encap_type(const char *name)
  76{
  77        if (strcmp(name, "mpls") == 0)
  78                return LWTUNNEL_ENCAP_MPLS;
  79        else if (strcmp(name, "ip") == 0)
  80                return LWTUNNEL_ENCAP_IP;
  81        else if (strcmp(name, "ip6") == 0)
  82                return LWTUNNEL_ENCAP_IP6;
  83        else if (strcmp(name, "ila") == 0)
  84                return LWTUNNEL_ENCAP_ILA;
  85        else if (strcmp(name, "bpf") == 0)
  86                return LWTUNNEL_ENCAP_BPF;
  87        else if (strcmp(name, "seg6") == 0)
  88                return LWTUNNEL_ENCAP_SEG6;
  89        else if (strcmp(name, "seg6local") == 0)
  90                return LWTUNNEL_ENCAP_SEG6_LOCAL;
  91        else if (strcmp(name, "rpl") == 0)
  92                return LWTUNNEL_ENCAP_RPL;
  93        else if (strcmp(name, "help") == 0)
  94                encap_type_usage();
  95
  96        return LWTUNNEL_ENCAP_NONE;
  97}
  98
  99static void print_srh(FILE *fp, struct ipv6_sr_hdr *srh)
 100{
 101        int i;
 102
 103        if (is_json_context())
 104                open_json_array(PRINT_JSON, "segs");
 105        else
 106                fprintf(fp, "segs %d [ ", srh->first_segment + 1);
 107
 108        for (i = srh->first_segment; i >= 0; i--)
 109                print_color_string(PRINT_ANY, COLOR_INET6,
 110                                   NULL, "%s ",
 111                                   rt_addr_n2a(AF_INET6, 16, &srh->segments[i]));
 112
 113        if (is_json_context())
 114                close_json_array(PRINT_JSON, NULL);
 115        else
 116                fprintf(fp, "] ");
 117
 118        if (sr_has_hmac(srh)) {
 119                unsigned int offset = ((srh->hdrlen + 1) << 3) - 40;
 120                struct sr6_tlv_hmac *tlv;
 121
 122                tlv = (struct sr6_tlv_hmac *)((char *)srh + offset);
 123                print_0xhex(PRINT_ANY, "hmac",
 124                            "hmac %llX ", ntohl(tlv->hmackeyid));
 125        }
 126}
 127
 128static const char *seg6_mode_types[] = {
 129        [SEG6_IPTUN_MODE_INLINE]        = "inline",
 130        [SEG6_IPTUN_MODE_ENCAP]         = "encap",
 131        [SEG6_IPTUN_MODE_L2ENCAP]       = "l2encap",
 132};
 133
 134static const char *format_seg6mode_type(int mode)
 135{
 136        if (mode < 0 || mode > ARRAY_SIZE(seg6_mode_types))
 137                return "<unknown>";
 138
 139        return seg6_mode_types[mode];
 140}
 141
 142static int read_seg6mode_type(const char *mode)
 143{
 144        int i;
 145
 146        for (i = 0; i < ARRAY_SIZE(seg6_mode_types); i++) {
 147                if (strcmp(mode, seg6_mode_types[i]) == 0)
 148                        return i;
 149        }
 150
 151        return -1;
 152}
 153
 154static void print_encap_seg6(FILE *fp, struct rtattr *encap)
 155{
 156        struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
 157        struct seg6_iptunnel_encap *tuninfo;
 158
 159        parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap);
 160
 161        if (!tb[SEG6_IPTUNNEL_SRH])
 162                return;
 163
 164        tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
 165        print_string(PRINT_ANY, "mode",
 166                     "mode %s ", format_seg6mode_type(tuninfo->mode));
 167
 168        print_srh(fp, tuninfo->srh);
 169}
 170
 171static void print_rpl_srh(FILE *fp, struct ipv6_rpl_sr_hdr *srh)
 172{
 173        int i;
 174
 175        if (is_json_context())
 176                open_json_array(PRINT_JSON, "segs");
 177        else
 178                fprintf(fp, "segs %d [ ", srh->segments_left);
 179
 180        for (i = srh->segments_left - 1; i >= 0; i--) {
 181                print_color_string(PRINT_ANY, COLOR_INET6,
 182                                   NULL, "%s ",
 183                                   rt_addr_n2a(AF_INET6, 16, &srh->rpl_segaddr[i]));
 184        }
 185
 186        if (is_json_context())
 187                close_json_array(PRINT_JSON, NULL);
 188        else
 189                fprintf(fp, "] ");
 190}
 191
 192static void print_encap_rpl(FILE *fp, struct rtattr *encap)
 193{
 194        struct rtattr *tb[RPL_IPTUNNEL_MAX + 1];
 195        struct ipv6_rpl_sr_hdr *srh;
 196
 197        parse_rtattr_nested(tb, RPL_IPTUNNEL_MAX, encap);
 198
 199        if (!tb[RPL_IPTUNNEL_SRH])
 200                return;
 201
 202        srh = RTA_DATA(tb[RPL_IPTUNNEL_SRH]);
 203
 204        print_rpl_srh(fp, srh);
 205}
 206
 207static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
 208        [SEG6_LOCAL_ACTION_END]                 = "End",
 209        [SEG6_LOCAL_ACTION_END_X]               = "End.X",
 210        [SEG6_LOCAL_ACTION_END_T]               = "End.T",
 211        [SEG6_LOCAL_ACTION_END_DX2]             = "End.DX2",
 212        [SEG6_LOCAL_ACTION_END_DX6]             = "End.DX6",
 213        [SEG6_LOCAL_ACTION_END_DX4]             = "End.DX4",
 214        [SEG6_LOCAL_ACTION_END_DT6]             = "End.DT6",
 215        [SEG6_LOCAL_ACTION_END_DT4]             = "End.DT4",
 216        [SEG6_LOCAL_ACTION_END_B6]              = "End.B6",
 217        [SEG6_LOCAL_ACTION_END_B6_ENCAP]        = "End.B6.Encaps",
 218        [SEG6_LOCAL_ACTION_END_BM]              = "End.BM",
 219        [SEG6_LOCAL_ACTION_END_S]               = "End.S",
 220        [SEG6_LOCAL_ACTION_END_AS]              = "End.AS",
 221        [SEG6_LOCAL_ACTION_END_AM]              = "End.AM",
 222        [SEG6_LOCAL_ACTION_END_BPF]             = "End.BPF",
 223};
 224
 225static 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
 233static 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
 248static 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
 269static 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
 330static 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
 344static 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
 383static 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
 403static 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
 435static 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
 448static 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
 491static 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
 522static 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
 566static 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
 583void 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
 623static 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
 675static 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
 736out:
 737        free(tuninfo);
 738        free(srh);
 739
 740        return ret;
 741}
 742
 743static 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
 774static 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
 810out:
 811        free(srh);
 812
 813        return ret;
 814}
 815
 816struct lwt_x {
 817        struct rtattr *rta;
 818        size_t len;
 819};
 820
 821static 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
 830static const struct bpf_cfg_ops bpf_cb_ops = {
 831        .ebpf_cb = bpf_lwt_cb,
 832};
 833
 834static 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
 865static 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
 995static 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
1044static 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
1113static 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
1130static 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
1146static 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
1222static 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
1356static 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
1434static 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
1570static 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
1577static 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
1628int 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}
1692