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