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