iproute2/ip/iplink.c
<<
>>
Prefs
   1/*
   2 * iplink.c             "ip link".
   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:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  10 *
  11 */
  12
  13#include <stdio.h>
  14#include <stdlib.h>
  15#include <unistd.h>
  16#include <fcntl.h>
  17#include <dlfcn.h>
  18#include <errno.h>
  19#include <sys/socket.h>
  20#include <linux/if.h>
  21#include <linux/if_packet.h>
  22#include <linux/if_ether.h>
  23#include <linux/sockios.h>
  24#include <netinet/in.h>
  25#include <arpa/inet.h>
  26#include <string.h>
  27#include <sys/ioctl.h>
  28#include <stdbool.h>
  29#include <linux/mpls.h>
  30
  31#include "rt_names.h"
  32#include "utils.h"
  33#include "ip_common.h"
  34#include "namespace.h"
  35
  36#define IPLINK_IOCTL_COMPAT     1
  37
  38#ifndef GSO_MAX_SIZE
  39#define GSO_MAX_SIZE            65536
  40#endif
  41#ifndef GSO_MAX_SEGS
  42#define GSO_MAX_SEGS            65535
  43#endif
  44
  45
  46static void usage(void) __attribute__((noreturn));
  47static int iplink_have_newlink(void);
  48
  49void iplink_usage(void)
  50{
  51        if (iplink_have_newlink()) {
  52                fprintf(stderr,
  53                        "Usage: ip link add [link DEV] [ name ] NAME\n"
  54                        "                   [ txqueuelen PACKETS ]\n"
  55                        "                   [ address LLADDR ]\n"
  56                        "                   [ broadcast LLADDR ]\n"
  57                        "                   [ mtu MTU ] [index IDX ]\n"
  58                        "                   [ numtxqueues QUEUE_COUNT ]\n"
  59                        "                   [ numrxqueues QUEUE_COUNT ]\n"
  60                        "                   type TYPE [ ARGS ]\n"
  61                        "\n"
  62                        "       ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"
  63                        "\n"
  64                        "       ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"
  65                        "                       [ { up | down } ]\n"
  66                        "                       [ type TYPE ARGS ]\n");
  67        } else
  68                fprintf(stderr,
  69                        "Usage: ip link set DEVICE [ { up | down } ]\n");
  70
  71        fprintf(stderr,
  72                "               [ arp { on | off } ]\n"
  73                "               [ dynamic { on | off } ]\n"
  74                "               [ multicast { on | off } ]\n"
  75                "               [ allmulticast { on | off } ]\n"
  76                "               [ promisc { on | off } ]\n"
  77                "               [ trailers { on | off } ]\n"
  78                "               [ carrier { on | off } ]\n"
  79                "               [ txqueuelen PACKETS ]\n"
  80                "               [ name NEWNAME ]\n"
  81                "               [ address LLADDR ]\n"
  82                "               [ broadcast LLADDR ]\n"
  83                "               [ mtu MTU ]\n"
  84                "               [ netns { PID | NAME } ]\n"
  85                "               [ link-netns NAME | link-netnsid ID ]\n"
  86                "               [ alias NAME ]\n"
  87                "               [ vf NUM [ mac LLADDR ]\n"
  88                "                        [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]\n"
  89                "                        [ rate TXRATE ]\n"
  90                "                        [ max_tx_rate TXRATE ]\n"
  91                "                        [ min_tx_rate TXRATE ]\n"
  92                "                        [ spoofchk { on | off} ]\n"
  93                "                        [ query_rss { on | off} ]\n"
  94                "                        [ state { auto | enable | disable} ]\n"
  95                "                        [ trust { on | off} ]\n"
  96                "                        [ node_guid EUI64 ]\n"
  97                "                        [ port_guid EUI64 ] ]\n"
  98                "               [ { xdp | xdpgeneric | xdpdrv | xdpoffload } { off |\n"
  99                "                         object FILE [ section NAME ] [ verbose ] |\n"
 100                "                         pinned FILE } ]\n"
 101                "               [ master DEVICE ][ vrf NAME ]\n"
 102                "               [ nomaster ]\n"
 103                "               [ addrgenmode { eui64 | none | stable_secret | random } ]\n"
 104                "               [ protodown { on | off } ]\n"
 105                "               [ protodown_reason PREASON { on | off } ]\n"
 106                "               [ gso_max_size BYTES ] | [ gso_max_segs PACKETS ]\n"
 107                "\n"
 108                "       ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n"
 109                "\n"
 110                "       ip link xstats type TYPE [ ARGS ]\n"
 111                "\n"
 112                "       ip link afstats [ dev DEVICE ]\n"
 113                "       ip link property add dev DEVICE [ altname NAME .. ]\n"
 114                "       ip link property del dev DEVICE [ altname NAME .. ]\n");
 115
 116        if (iplink_have_newlink()) {
 117                fprintf(stderr,
 118                        "\n"
 119                        "       ip link help [ TYPE ]\n"
 120                        "\n"
 121                        "TYPE := { vlan | veth | vcan | vxcan | dummy | ifb | macvlan | macvtap |\n"
 122                        "          bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
 123                        "          gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n"
 124                        "          vti | nlmon | team_slave | bond_slave | bridge_slave |\n"
 125                        "          ipvlan | ipvtap | geneve | bareudp | vrf | macsec | netdevsim | rmnet |\n"
 126                        "          xfrm }\n");
 127        }
 128        exit(-1);
 129}
 130
 131static void usage(void)
 132{
 133        iplink_usage();
 134}
 135
 136static int on_off(const char *msg, const char *realval)
 137{
 138        fprintf(stderr,
 139                "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
 140                msg, realval);
 141        return -1;
 142}
 143
 144static void *BODY;              /* cached dlopen(NULL) handle */
 145static struct link_util *linkutil_list;
 146
 147struct link_util *get_link_kind(const char *id)
 148{
 149        void *dlh;
 150        char buf[256];
 151        struct link_util *l;
 152
 153        for (l = linkutil_list; l; l = l->next)
 154                if (strcmp(l->id, id) == 0)
 155                        return l;
 156
 157        snprintf(buf, sizeof(buf), "%s/link_%s.so", get_ip_lib_dir(), id);
 158        dlh = dlopen(buf, RTLD_LAZY);
 159        if (dlh == NULL) {
 160                /* look in current binary, only open once */
 161                dlh = BODY;
 162                if (dlh == NULL) {
 163                        dlh = BODY = dlopen(NULL, RTLD_LAZY);
 164                        if (dlh == NULL)
 165                                return NULL;
 166                }
 167        }
 168
 169        snprintf(buf, sizeof(buf), "%s_link_util", id);
 170        l = dlsym(dlh, buf);
 171        if (l == NULL)
 172                return NULL;
 173
 174        l->next = linkutil_list;
 175        linkutil_list = l;
 176        return l;
 177}
 178
 179static int get_link_mode(const char *mode)
 180{
 181        if (strcasecmp(mode, "default") == 0)
 182                return IF_LINK_MODE_DEFAULT;
 183        if (strcasecmp(mode, "dormant") == 0)
 184                return IF_LINK_MODE_DORMANT;
 185        return -1;
 186}
 187
 188static int get_addr_gen_mode(const char *mode)
 189{
 190        if (strcasecmp(mode, "eui64") == 0)
 191                return IN6_ADDR_GEN_MODE_EUI64;
 192        if (strcasecmp(mode, "none") == 0)
 193                return IN6_ADDR_GEN_MODE_NONE;
 194        if (strcasecmp(mode, "stable_secret") == 0)
 195                return IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
 196        if (strcasecmp(mode, "random") == 0)
 197                return IN6_ADDR_GEN_MODE_RANDOM;
 198        return -1;
 199}
 200
 201#if IPLINK_IOCTL_COMPAT
 202static int have_rtnl_newlink = -1;
 203
 204static int accept_msg(struct rtnl_ctrl_data *ctrl,
 205                      struct nlmsghdr *n, void *arg)
 206{
 207        struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
 208
 209        if (n->nlmsg_type == NLMSG_ERROR &&
 210            (err->error == -EOPNOTSUPP || err->error == -EINVAL))
 211                have_rtnl_newlink = 0;
 212        else
 213                have_rtnl_newlink = 1;
 214        return -1;
 215}
 216
 217static int iplink_have_newlink(void)
 218{
 219        struct {
 220                struct nlmsghdr         n;
 221                struct ifinfomsg        i;
 222                char                    buf[1024];
 223        } req = {
 224                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
 225                .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
 226                .n.nlmsg_type = RTM_NEWLINK,
 227                .i.ifi_family = AF_UNSPEC,
 228        };
 229
 230        if (have_rtnl_newlink < 0) {
 231                if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
 232                        perror("request send failed");
 233                        exit(1);
 234                }
 235                rtnl_listen(&rth, accept_msg, NULL);
 236        }
 237        return have_rtnl_newlink;
 238}
 239#else /* IPLINK_IOCTL_COMPAT */
 240static int iplink_have_newlink(void)
 241{
 242        return 1;
 243}
 244#endif /* ! IPLINK_IOCTL_COMPAT */
 245
 246static int nl_get_ll_addr_len(const char *ifname)
 247{
 248        int len;
 249        int dev_index = ll_name_to_index(ifname);
 250        struct iplink_req req = {
 251                .n = {
 252                        .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
 253                        .nlmsg_type = RTM_GETLINK,
 254                        .nlmsg_flags = NLM_F_REQUEST
 255                },
 256                .i = {
 257                        .ifi_family = preferred_family,
 258                        .ifi_index = dev_index,
 259                }
 260        };
 261        struct nlmsghdr *answer;
 262        struct rtattr *tb[IFLA_MAX+1];
 263
 264        if (dev_index == 0)
 265                return -1;
 266
 267        if (rtnl_talk(&rth, &req.n, &answer) < 0)
 268                return -1;
 269
 270        len = answer->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
 271        if (len < 0) {
 272                free(answer);
 273                return -1;
 274        }
 275
 276        parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)),
 277                           len, NLA_F_NESTED);
 278        if (!tb[IFLA_ADDRESS]) {
 279                free(answer);
 280                return -1;
 281        }
 282
 283        len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
 284        free(answer);
 285        return len;
 286}
 287
 288static void iplink_parse_vf_vlan_info(int vf, int *argcp, char ***argvp,
 289                                      struct ifla_vf_vlan_info *ivvip)
 290{
 291        int argc = *argcp;
 292        char **argv = *argvp;
 293        unsigned int vci;
 294
 295        NEXT_ARG();
 296        if (get_unsigned(&vci, *argv, 0) || vci > 4095)
 297                invarg("Invalid \"vlan\" value\n", *argv);
 298
 299        ivvip->vlan = vci;
 300        ivvip->vf = vf;
 301        ivvip->qos = 0;
 302        ivvip->vlan_proto = htons(ETH_P_8021Q);
 303        if (NEXT_ARG_OK()) {
 304                NEXT_ARG();
 305                if (matches(*argv, "qos") == 0) {
 306                        NEXT_ARG();
 307                        if (get_unsigned(&ivvip->qos, *argv, 0))
 308                                invarg("Invalid \"qos\" value\n", *argv);
 309                } else {
 310                        /* rewind arg */
 311                        PREV_ARG();
 312                }
 313        }
 314        if (NEXT_ARG_OK()) {
 315                NEXT_ARG();
 316                if (matches(*argv, "proto") == 0) {
 317                        NEXT_ARG();
 318                        if (ll_proto_a2n(&ivvip->vlan_proto, *argv))
 319                                invarg("protocol is invalid\n", *argv);
 320                        if (ivvip->vlan_proto != htons(ETH_P_8021AD) &&
 321                            ivvip->vlan_proto != htons(ETH_P_8021Q)) {
 322                                SPRINT_BUF(b1);
 323                                SPRINT_BUF(b2);
 324                                char msg[64 + sizeof(b1) + sizeof(b2)];
 325
 326                                sprintf(msg,
 327                                        "Invalid \"vlan protocol\" value - supported %s, %s\n",
 328                                        ll_proto_n2a(htons(ETH_P_8021Q),
 329                                             b1, sizeof(b1)),
 330                                        ll_proto_n2a(htons(ETH_P_8021AD),
 331                                             b2, sizeof(b2)));
 332                                invarg(msg, *argv);
 333                        }
 334                } else {
 335                        /* rewind arg */
 336                        PREV_ARG();
 337                }
 338        }
 339
 340        *argcp = argc;
 341        *argvp = argv;
 342}
 343
 344static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
 345                           struct iplink_req *req, const char *dev)
 346{
 347        char new_rate_api = 0, count = 0, override_legacy_rate = 0;
 348        struct ifla_vf_rate tivt;
 349        int len, argc = *argcp;
 350        char **argv = *argvp;
 351        struct rtattr *vfinfo;
 352        int ret;
 353
 354        tivt.min_tx_rate = -1;
 355        tivt.max_tx_rate = -1;
 356
 357        vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
 358
 359        while (NEXT_ARG_OK()) {
 360                NEXT_ARG();
 361                count++;
 362                if (!matches(*argv, "max_tx_rate")) {
 363                        /* new API in use */
 364                        new_rate_api = 1;
 365                        /* override legacy rate */
 366                        override_legacy_rate = 1;
 367                } else if (!matches(*argv, "min_tx_rate")) {
 368                        /* new API in use */
 369                        new_rate_api = 1;
 370                }
 371        }
 372
 373        while (count--) {
 374                /* rewind arg */
 375                PREV_ARG();
 376        }
 377
 378        while (NEXT_ARG_OK()) {
 379                NEXT_ARG();
 380                if (matches(*argv, "mac") == 0) {
 381                        struct ifla_vf_mac ivm = { 0 };
 382                        int halen = nl_get_ll_addr_len(dev);
 383
 384                        NEXT_ARG();
 385                        ivm.vf = vf;
 386                        len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
 387                        if (len < 0)
 388                                return -1;
 389                        if (halen > 0 && len != halen) {
 390                                fprintf(stderr,
 391                                        "Invalid address length %d - must be %d bytes\n",
 392                                        len, halen);
 393                                return -1;
 394                        }
 395                        addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC,
 396                                  &ivm, sizeof(ivm));
 397                } else if (matches(*argv, "vlan") == 0) {
 398                        struct ifla_vf_vlan_info ivvi;
 399
 400                        iplink_parse_vf_vlan_info(vf, &argc, &argv, &ivvi);
 401                        /* support the old interface in case of older kernel*/
 402                        if (ivvi.vlan_proto == htons(ETH_P_8021Q)) {
 403                                struct ifla_vf_vlan ivv;
 404
 405                                ivv.vf = ivvi.vf;
 406                                ivv.vlan = ivvi.vlan;
 407                                ivv.qos = ivvi.qos;
 408                                addattr_l(&req->n, sizeof(*req),
 409                                          IFLA_VF_VLAN, &ivv, sizeof(ivv));
 410                        } else {
 411                                struct rtattr *vfvlanlist;
 412
 413                                vfvlanlist = addattr_nest(&req->n, sizeof(*req),
 414                                                          IFLA_VF_VLAN_LIST);
 415                                addattr_l(&req->n, sizeof(*req),
 416                                          IFLA_VF_VLAN_INFO, &ivvi,
 417                                          sizeof(ivvi));
 418
 419                                while (NEXT_ARG_OK()) {
 420                                        NEXT_ARG();
 421                                        if (matches(*argv, "vlan") != 0) {
 422                                                PREV_ARG();
 423                                                break;
 424                                        }
 425                                        iplink_parse_vf_vlan_info(vf, &argc,
 426                                                                  &argv, &ivvi);
 427                                        addattr_l(&req->n, sizeof(*req),
 428                                                  IFLA_VF_VLAN_INFO, &ivvi,
 429                                                  sizeof(ivvi));
 430                                }
 431                                addattr_nest_end(&req->n, vfvlanlist);
 432                        }
 433                } else if (matches(*argv, "rate") == 0) {
 434                        struct ifla_vf_tx_rate ivt;
 435
 436                        NEXT_ARG();
 437                        if (get_unsigned(&ivt.rate, *argv, 0))
 438                                invarg("Invalid \"rate\" value\n", *argv);
 439
 440                        ivt.vf = vf;
 441                        if (!new_rate_api)
 442                                addattr_l(&req->n, sizeof(*req),
 443                                          IFLA_VF_TX_RATE, &ivt, sizeof(ivt));
 444                        else if (!override_legacy_rate)
 445                                tivt.max_tx_rate = ivt.rate;
 446
 447                } else if (matches(*argv, "max_tx_rate") == 0) {
 448                        NEXT_ARG();
 449                        if (get_unsigned(&tivt.max_tx_rate, *argv, 0))
 450                                invarg("Invalid \"max tx rate\" value\n",
 451                                       *argv);
 452                        tivt.vf = vf;
 453
 454                } else if (matches(*argv, "min_tx_rate") == 0) {
 455                        NEXT_ARG();
 456                        if (get_unsigned(&tivt.min_tx_rate, *argv, 0))
 457                                invarg("Invalid \"min tx rate\" value\n",
 458                                       *argv);
 459                        tivt.vf = vf;
 460
 461                } else if (matches(*argv, "spoofchk") == 0) {
 462                        struct ifla_vf_spoofchk ivs;
 463
 464                        NEXT_ARG();
 465                        ivs.setting = parse_on_off("spoofchk", *argv, &ret);
 466                        if (ret)
 467                                return ret;
 468                        ivs.vf = vf;
 469                        addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK,
 470                                  &ivs, sizeof(ivs));
 471
 472                } else if (matches(*argv, "query_rss") == 0) {
 473                        struct ifla_vf_rss_query_en ivs;
 474
 475                        NEXT_ARG();
 476                        ivs.setting = parse_on_off("query_rss", *argv, &ret);
 477                        if (ret)
 478                                return ret;
 479                        ivs.vf = vf;
 480                        addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN,
 481                                  &ivs, sizeof(ivs));
 482
 483                } else if (matches(*argv, "trust") == 0) {
 484                        struct ifla_vf_trust ivt;
 485
 486                        NEXT_ARG();
 487                        ivt.setting = parse_on_off("trust", *argv, &ret);
 488                        if (ret)
 489                                return ret;
 490                        ivt.vf = vf;
 491                        addattr_l(&req->n, sizeof(*req), IFLA_VF_TRUST,
 492                                  &ivt, sizeof(ivt));
 493
 494                } else if (matches(*argv, "state") == 0) {
 495                        struct ifla_vf_link_state ivl;
 496
 497                        NEXT_ARG();
 498                        if (matches(*argv, "auto") == 0)
 499                                ivl.link_state = IFLA_VF_LINK_STATE_AUTO;
 500                        else if (matches(*argv, "enable") == 0)
 501                                ivl.link_state = IFLA_VF_LINK_STATE_ENABLE;
 502                        else if (matches(*argv, "disable") == 0)
 503                                ivl.link_state = IFLA_VF_LINK_STATE_DISABLE;
 504                        else
 505                                invarg("Invalid \"state\" value\n", *argv);
 506                        ivl.vf = vf;
 507                        addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE,
 508                                  &ivl, sizeof(ivl));
 509                } else if (matches(*argv, "node_guid") == 0) {
 510                        struct ifla_vf_guid ivg;
 511
 512                        NEXT_ARG();
 513                        ivg.vf = vf;
 514                        if (get_guid(&ivg.guid, *argv)) {
 515                                invarg("Invalid GUID format\n", *argv);
 516                                return -1;
 517                        }
 518                        addattr_l(&req->n, sizeof(*req), IFLA_VF_IB_NODE_GUID,
 519                                  &ivg, sizeof(ivg));
 520                } else if (matches(*argv, "port_guid") == 0) {
 521                        struct ifla_vf_guid ivg;
 522
 523                        NEXT_ARG();
 524                        ivg.vf = vf;
 525                        if (get_guid(&ivg.guid, *argv)) {
 526                                invarg("Invalid GUID format\n", *argv);
 527                                return -1;
 528                        }
 529                        addattr_l(&req->n, sizeof(*req), IFLA_VF_IB_PORT_GUID,
 530                                  &ivg, sizeof(ivg));
 531                } else {
 532                        /* rewind arg */
 533                        PREV_ARG();
 534                        break;
 535                }
 536        }
 537
 538        if (new_rate_api) {
 539                int tmin, tmax;
 540
 541                if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) {
 542                        ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev);
 543                        if (tivt.min_tx_rate == -1)
 544                                tivt.min_tx_rate = tmin;
 545                        if (tivt.max_tx_rate == -1)
 546                                tivt.max_tx_rate = tmax;
 547                }
 548
 549                if (tivt.max_tx_rate && tivt.min_tx_rate > tivt.max_tx_rate) {
 550                        fprintf(stderr,
 551                                "Invalid min_tx_rate %d - must be <= max_tx_rate %d\n",
 552                                tivt.min_tx_rate, tivt.max_tx_rate);
 553                        return -1;
 554                }
 555
 556                addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt,
 557                          sizeof(tivt));
 558        }
 559
 560        if (argc == *argcp)
 561                incomplete_command();
 562
 563        addattr_nest_end(&req->n, vfinfo);
 564
 565        *argcp = argc;
 566        *argvp = argv;
 567        return 0;
 568}
 569
 570int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
 571{
 572        char *name = NULL;
 573        char *dev = NULL;
 574        char *link = NULL;
 575        int ret, len;
 576        char abuf[32];
 577        int qlen = -1;
 578        int mtu = -1;
 579        int netns = -1;
 580        int vf = -1;
 581        int numtxqueues = -1;
 582        int numrxqueues = -1;
 583        int link_netnsid = -1;
 584        int index = 0;
 585        int group = -1;
 586        int addr_len = 0;
 587        int err;
 588
 589        ret = argc;
 590
 591        while (argc > 0) {
 592                if (strcmp(*argv, "up") == 0) {
 593                        req->i.ifi_change |= IFF_UP;
 594                        req->i.ifi_flags |= IFF_UP;
 595                } else if (strcmp(*argv, "down") == 0) {
 596                        req->i.ifi_change |= IFF_UP;
 597                        req->i.ifi_flags &= ~IFF_UP;
 598                } else if (strcmp(*argv, "name") == 0) {
 599                        NEXT_ARG();
 600                        if (name)
 601                                duparg("name", *argv);
 602                        if (check_ifname(*argv))
 603                                invarg("\"name\" not a valid ifname", *argv);
 604                        name = *argv;
 605                        if (!dev)
 606                                dev = name;
 607                } else if (strcmp(*argv, "index") == 0) {
 608                        NEXT_ARG();
 609                        if (index)
 610                                duparg("index", *argv);
 611                        index = atoi(*argv);
 612                        if (index <= 0)
 613                                invarg("Invalid \"index\" value", *argv);
 614                } else if (matches(*argv, "link") == 0) {
 615                        NEXT_ARG();
 616                        link = *argv;
 617                } else if (matches(*argv, "address") == 0) {
 618                        NEXT_ARG();
 619                        addr_len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
 620                        if (addr_len < 0)
 621                                return -1;
 622                        addattr_l(&req->n, sizeof(*req),
 623                                  IFLA_ADDRESS, abuf, addr_len);
 624                } else if (matches(*argv, "broadcast") == 0 ||
 625                           strcmp(*argv, "brd") == 0) {
 626                        NEXT_ARG();
 627                        len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
 628                        if (len < 0)
 629                                return -1;
 630                        addattr_l(&req->n, sizeof(*req),
 631                                  IFLA_BROADCAST, abuf, len);
 632                } else if (matches(*argv, "txqueuelen") == 0 ||
 633                           strcmp(*argv, "qlen") == 0 ||
 634                           matches(*argv, "txqlen") == 0) {
 635                        NEXT_ARG();
 636                        if (qlen != -1)
 637                                duparg("txqueuelen", *argv);
 638                        if (get_integer(&qlen,  *argv, 0))
 639                                invarg("Invalid \"txqueuelen\" value\n", *argv);
 640                        addattr_l(&req->n, sizeof(*req),
 641                                  IFLA_TXQLEN, &qlen, 4);
 642                } else if (strcmp(*argv, "mtu") == 0) {
 643                        NEXT_ARG();
 644                        if (mtu != -1)
 645                                duparg("mtu", *argv);
 646                        if (get_integer(&mtu, *argv, 0))
 647                                invarg("Invalid \"mtu\" value\n", *argv);
 648                        addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
 649                } else if (strcmp(*argv, "xdpgeneric") == 0 ||
 650                           strcmp(*argv, "xdpdrv") == 0 ||
 651                           strcmp(*argv, "xdpoffload") == 0 ||
 652                           strcmp(*argv, "xdp") == 0) {
 653                        bool generic = strcmp(*argv, "xdpgeneric") == 0;
 654                        bool drv = strcmp(*argv, "xdpdrv") == 0;
 655                        bool offload = strcmp(*argv, "xdpoffload") == 0;
 656
 657                        NEXT_ARG();
 658                        if (xdp_parse(&argc, &argv, req, dev,
 659                                      generic, drv, offload))
 660                                exit(-1);
 661
 662                        if (offload && name == dev)
 663                                dev = NULL;
 664                } else if (strcmp(*argv, "netns") == 0) {
 665                        NEXT_ARG();
 666                        if (netns != -1)
 667                                duparg("netns", *argv);
 668                        netns = netns_get_fd(*argv);
 669                        if (netns >= 0)
 670                                addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD,
 671                                          &netns, 4);
 672                        else if (get_integer(&netns, *argv, 0) == 0)
 673                                addattr_l(&req->n, sizeof(*req),
 674                                          IFLA_NET_NS_PID, &netns, 4);
 675                        else
 676                                invarg("Invalid \"netns\" value\n", *argv);
 677                } else if (strcmp(*argv, "multicast") == 0) {
 678                        NEXT_ARG();
 679                        req->i.ifi_change |= IFF_MULTICAST;
 680
 681                        if (strcmp(*argv, "on") == 0)
 682                                req->i.ifi_flags |= IFF_MULTICAST;
 683                        else if (strcmp(*argv, "off") == 0)
 684                                req->i.ifi_flags &= ~IFF_MULTICAST;
 685                        else
 686                                return on_off("multicast", *argv);
 687                } else if (strcmp(*argv, "allmulticast") == 0) {
 688                        NEXT_ARG();
 689                        req->i.ifi_change |= IFF_ALLMULTI;
 690
 691                        if (strcmp(*argv, "on") == 0)
 692                                req->i.ifi_flags |= IFF_ALLMULTI;
 693                        else if (strcmp(*argv, "off") == 0)
 694                                req->i.ifi_flags &= ~IFF_ALLMULTI;
 695                        else
 696                                return on_off("allmulticast", *argv);
 697                } else if (strcmp(*argv, "promisc") == 0) {
 698                        NEXT_ARG();
 699                        req->i.ifi_change |= IFF_PROMISC;
 700
 701                        if (strcmp(*argv, "on") == 0)
 702                                req->i.ifi_flags |= IFF_PROMISC;
 703                        else if (strcmp(*argv, "off") == 0)
 704                                req->i.ifi_flags &= ~IFF_PROMISC;
 705                        else
 706                                return on_off("promisc", *argv);
 707                } else if (strcmp(*argv, "trailers") == 0) {
 708                        NEXT_ARG();
 709                        req->i.ifi_change |= IFF_NOTRAILERS;
 710
 711                        if (strcmp(*argv, "off") == 0)
 712                                req->i.ifi_flags |= IFF_NOTRAILERS;
 713                        else if (strcmp(*argv, "on") == 0)
 714                                req->i.ifi_flags &= ~IFF_NOTRAILERS;
 715                        else
 716                                return on_off("trailers", *argv);
 717                } else if (strcmp(*argv, "arp") == 0) {
 718                        NEXT_ARG();
 719                        req->i.ifi_change |= IFF_NOARP;
 720
 721                        if (strcmp(*argv, "on") == 0)
 722                                req->i.ifi_flags &= ~IFF_NOARP;
 723                        else if (strcmp(*argv, "off") == 0)
 724                                req->i.ifi_flags |= IFF_NOARP;
 725                        else
 726                                return on_off("arp", *argv);
 727                } else if (strcmp(*argv, "carrier") == 0) {
 728                        int carrier;
 729
 730                        NEXT_ARG();
 731                        carrier = parse_on_off("carrier", *argv, &err);
 732                        if (err)
 733                                return err;
 734
 735                        addattr8(&req->n, sizeof(*req), IFLA_CARRIER, carrier);
 736                } else if (strcmp(*argv, "vf") == 0) {
 737                        struct rtattr *vflist;
 738
 739                        NEXT_ARG();
 740                        if (get_integer(&vf,  *argv, 0))
 741                                invarg("Invalid \"vf\" value\n", *argv);
 742
 743                        vflist = addattr_nest(&req->n, sizeof(*req),
 744                                              IFLA_VFINFO_LIST);
 745                        if (!dev)
 746                                missarg("dev");
 747
 748                        len = iplink_parse_vf(vf, &argc, &argv, req, dev);
 749                        if (len < 0)
 750                                return -1;
 751                        addattr_nest_end(&req->n, vflist);
 752
 753                        if (name == dev)
 754                                dev = NULL;
 755                } else if (matches(*argv, "master") == 0) {
 756                        int ifindex;
 757
 758                        NEXT_ARG();
 759                        ifindex = ll_name_to_index(*argv);
 760                        if (!ifindex)
 761                                invarg("Device does not exist\n", *argv);
 762                        addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
 763                                  &ifindex, 4);
 764                } else if (strcmp(*argv, "vrf") == 0) {
 765                        int ifindex;
 766
 767                        NEXT_ARG();
 768                        ifindex = ll_name_to_index(*argv);
 769                        if (!ifindex)
 770                                invarg("Not a valid VRF name\n", *argv);
 771                        if (!name_is_vrf(*argv))
 772                                invarg("Not a valid VRF name\n", *argv);
 773                        addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
 774                                  &ifindex, sizeof(ifindex));
 775                } else if (matches(*argv, "nomaster") == 0) {
 776                        int ifindex = 0;
 777
 778                        addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
 779                                  &ifindex, 4);
 780                } else if (matches(*argv, "dynamic") == 0) {
 781                        NEXT_ARG();
 782                        req->i.ifi_change |= IFF_DYNAMIC;
 783
 784                        if (strcmp(*argv, "on") == 0)
 785                                req->i.ifi_flags |= IFF_DYNAMIC;
 786                        else if (strcmp(*argv, "off") == 0)
 787                                req->i.ifi_flags &= ~IFF_DYNAMIC;
 788                        else
 789                                return on_off("dynamic", *argv);
 790                } else if (matches(*argv, "type") == 0) {
 791                        NEXT_ARG();
 792                        *type = *argv;
 793                        argc--; argv++;
 794                        break;
 795                } else if (matches(*argv, "alias") == 0) {
 796                        NEXT_ARG();
 797                        len = strlen(*argv);
 798                        if (len >= IFALIASZ)
 799                                invarg("alias too long\n", *argv);
 800                        addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
 801                                  *argv, len);
 802                } else if (strcmp(*argv, "group") == 0) {
 803                        NEXT_ARG();
 804                        if (group != -1)
 805                                duparg("group", *argv);
 806                        if (rtnl_group_a2n(&group, *argv))
 807                                invarg("Invalid \"group\" value\n", *argv);
 808                        addattr32(&req->n, sizeof(*req), IFLA_GROUP, group);
 809                } else if (strcmp(*argv, "mode") == 0) {
 810                        int mode;
 811
 812                        NEXT_ARG();
 813                        mode = get_link_mode(*argv);
 814                        if (mode < 0)
 815                                invarg("Invalid link mode\n", *argv);
 816                        addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
 817                } else if (strcmp(*argv, "state") == 0) {
 818                        int state;
 819
 820                        NEXT_ARG();
 821                        state = get_operstate(*argv);
 822                        if (state < 0)
 823                                invarg("Invalid operstate\n", *argv);
 824
 825                        addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
 826                } else if (matches(*argv, "numtxqueues") == 0) {
 827                        NEXT_ARG();
 828                        if (numtxqueues != -1)
 829                                duparg("numtxqueues", *argv);
 830                        if (get_integer(&numtxqueues, *argv, 0))
 831                                invarg("Invalid \"numtxqueues\" value\n",
 832                                       *argv);
 833                        addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
 834                                  &numtxqueues, 4);
 835                } else if (matches(*argv, "numrxqueues") == 0) {
 836                        NEXT_ARG();
 837                        if (numrxqueues != -1)
 838                                duparg("numrxqueues", *argv);
 839                        if (get_integer(&numrxqueues, *argv, 0))
 840                                invarg("Invalid \"numrxqueues\" value\n",
 841                                       *argv);
 842                        addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
 843                                  &numrxqueues, 4);
 844                } else if (matches(*argv, "addrgenmode") == 0) {
 845                        struct rtattr *afs, *afs6;
 846                        int mode;
 847
 848                        NEXT_ARG();
 849                        mode = get_addr_gen_mode(*argv);
 850                        if (mode < 0)
 851                                invarg("Invalid address generation mode\n",
 852                                       *argv);
 853                        afs = addattr_nest(&req->n, sizeof(*req), IFLA_AF_SPEC);
 854                        afs6 = addattr_nest(&req->n, sizeof(*req), AF_INET6);
 855                        addattr8(&req->n, sizeof(*req),
 856                                 IFLA_INET6_ADDR_GEN_MODE, mode);
 857                        addattr_nest_end(&req->n, afs6);
 858                        addattr_nest_end(&req->n, afs);
 859                } else if (matches(*argv, "link-netns") == 0) {
 860                        NEXT_ARG();
 861                        if (link_netnsid != -1)
 862                                duparg("link-netns/link-netnsid", *argv);
 863                        link_netnsid = get_netnsid_from_name(*argv);
 864                        /* No nsid? Try to assign one. */
 865                        if (link_netnsid < 0)
 866                                set_netnsid_from_name(*argv, -1);
 867                        link_netnsid = get_netnsid_from_name(*argv);
 868                        if (link_netnsid < 0)
 869                                invarg("Invalid \"link-netns\" value\n",
 870                                       *argv);
 871                        addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
 872                                  link_netnsid);
 873                } else if (matches(*argv, "link-netnsid") == 0) {
 874                        NEXT_ARG();
 875                        if (link_netnsid != -1)
 876                                duparg("link-netns/link-netnsid", *argv);
 877                        if (get_integer(&link_netnsid, *argv, 0))
 878                                invarg("Invalid \"link-netnsid\" value\n",
 879                                       *argv);
 880                        addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
 881                                  link_netnsid);
 882                } else if (strcmp(*argv, "protodown") == 0) {
 883                        unsigned int proto_down;
 884
 885                        NEXT_ARG();
 886                        proto_down = parse_on_off("protodown", *argv, &err);
 887                        if (err)
 888                                return err;
 889                        addattr8(&req->n, sizeof(*req), IFLA_PROTO_DOWN,
 890                                 proto_down);
 891                } else if (strcmp(*argv, "protodown_reason") == 0) {
 892                        struct rtattr *pr;
 893                        __u32 preason = 0, prvalue = 0, prmask = 0;
 894
 895                        NEXT_ARG();
 896                        if (protodown_reason_a2n(&preason, *argv))
 897                                invarg("invalid protodown reason\n", *argv);
 898                        NEXT_ARG();
 899                        prmask = 1 << preason;
 900                        if (matches(*argv, "on") == 0)
 901                                prvalue |= prmask;
 902                        else if (matches(*argv, "off") == 0)
 903                                prvalue &= ~prmask;
 904                        else
 905                                return on_off("protodown_reason", *argv);
 906                        pr = addattr_nest(&req->n, sizeof(*req),
 907                                          IFLA_PROTO_DOWN_REASON | NLA_F_NESTED);
 908                        addattr32(&req->n, sizeof(*req),
 909                                  IFLA_PROTO_DOWN_REASON_MASK, prmask);
 910                        addattr32(&req->n, sizeof(*req),
 911                                  IFLA_PROTO_DOWN_REASON_VALUE, prvalue);
 912                        addattr_nest_end(&req->n, pr);
 913                } else if (strcmp(*argv, "gso_max_size") == 0) {
 914                        unsigned int max_size;
 915
 916                        NEXT_ARG();
 917                        if (get_unsigned(&max_size, *argv, 0) ||
 918                            max_size > GSO_MAX_SIZE)
 919                                invarg("Invalid \"gso_max_size\" value\n",
 920                                       *argv);
 921                        addattr32(&req->n, sizeof(*req),
 922                                  IFLA_GSO_MAX_SIZE, max_size);
 923                } else if (strcmp(*argv, "gso_max_segs") == 0) {
 924                        unsigned int max_segs;
 925
 926                        NEXT_ARG();
 927                        if (get_unsigned(&max_segs, *argv, 0) ||
 928                            max_segs > GSO_MAX_SEGS)
 929                                invarg("Invalid \"gso_max_segs\" value\n",
 930                                       *argv);
 931                        addattr32(&req->n, sizeof(*req),
 932                                  IFLA_GSO_MAX_SEGS, max_segs);
 933                } else {
 934                        if (matches(*argv, "help") == 0)
 935                                usage();
 936
 937                        if (strcmp(*argv, "dev") == 0)
 938                                NEXT_ARG();
 939                        if (dev != name)
 940                                duparg2("dev", *argv);
 941                        if (check_altifname(*argv))
 942                                invarg("\"dev\" not a valid ifname", *argv);
 943                        dev = *argv;
 944                }
 945                argc--; argv++;
 946        }
 947
 948        ret -= argc;
 949
 950        /* Allow "ip link add dev" and "ip link add name" */
 951        if (!name)
 952                name = dev;
 953        else if (!dev)
 954                dev = name;
 955        else if (!strcmp(name, dev))
 956                name = dev;
 957
 958        if (dev && addr_len &&
 959            !(req->n.nlmsg_flags & NLM_F_CREATE)) {
 960                int halen = nl_get_ll_addr_len(dev);
 961
 962                if (halen >= 0 && halen != addr_len) {
 963                        fprintf(stderr,
 964                                "Invalid address length %d - must be %d bytes\n",
 965                                addr_len, halen);
 966                        return -1;
 967                }
 968        }
 969
 970        if (!(req->n.nlmsg_flags & NLM_F_CREATE) && index) {
 971                fprintf(stderr,
 972                        "index can be used only when creating devices.\n");
 973                exit(-1);
 974        }
 975
 976        if (group != -1) {
 977                if (!dev) {
 978                        if (argc) {
 979                                fprintf(stderr,
 980                                        "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
 981                                        *argv);
 982                                exit(-1);
 983                        }
 984                        if (req->n.nlmsg_flags & NLM_F_CREATE) {
 985                                fprintf(stderr,
 986                                        "group cannot be used when creating devices.\n");
 987                                exit(-1);
 988                        }
 989
 990                        *type = NULL;
 991                        return ret;
 992                }
 993        }
 994
 995        if (!(req->n.nlmsg_flags & NLM_F_CREATE)) {
 996                if (!dev) {
 997                        fprintf(stderr,
 998                                "Not enough information: \"dev\" argument is required.\n");
 999                        exit(-1);
1000                }
1001
1002                req->i.ifi_index = ll_name_to_index(dev);
1003                if (!req->i.ifi_index)
1004                        return nodev(dev);
1005
1006                /* Not renaming to the same name */
1007                if (name == dev)
1008                        name = NULL;
1009        } else {
1010                if (name != dev) {
1011                        fprintf(stderr,
1012                                "both \"name\" and \"dev\" cannot be used when creating devices.\n");
1013                        exit(-1);
1014                }
1015
1016                if (link) {
1017                        int ifindex;
1018
1019                        ifindex = ll_name_to_index(link);
1020                        if (!ifindex)
1021                                return nodev(link);
1022                        addattr32(&req->n, sizeof(*req), IFLA_LINK, ifindex);
1023                }
1024
1025                req->i.ifi_index = index;
1026        }
1027
1028        if (name) {
1029                addattr_l(&req->n, sizeof(*req),
1030                          IFLA_IFNAME, name, strlen(name) + 1);
1031        }
1032
1033        return ret;
1034}
1035
1036static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
1037{
1038        char *type = NULL;
1039        struct iplink_req req = {
1040                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
1041                .n.nlmsg_flags = NLM_F_REQUEST | flags,
1042                .n.nlmsg_type = cmd,
1043                .i.ifi_family = preferred_family,
1044        };
1045        int ret;
1046
1047        ret = iplink_parse(argc, argv, &req, &type);
1048        if (ret < 0)
1049                return ret;
1050
1051        if (type) {
1052                struct link_util *lu;
1053                struct rtattr *linkinfo;
1054                char *ulinep = strchr(type, '_');
1055                int iflatype;
1056
1057                linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
1058                addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
1059                         strlen(type));
1060
1061                lu = get_link_kind(type);
1062                if (ulinep && !strcmp(ulinep, "_slave"))
1063                        iflatype = IFLA_INFO_SLAVE_DATA;
1064                else
1065                        iflatype = IFLA_INFO_DATA;
1066
1067                argc -= ret;
1068                argv += ret;
1069
1070                if (lu && argc) {
1071                        struct rtattr *data;
1072
1073                        data = addattr_nest(&req.n, sizeof(req), iflatype);
1074
1075                        if (lu->parse_opt &&
1076                            lu->parse_opt(lu, argc, argv, &req.n))
1077                                return -1;
1078
1079                        addattr_nest_end(&req.n, data);
1080                } else if (argc) {
1081                        if (matches(*argv, "help") == 0)
1082                                usage();
1083                        fprintf(stderr,
1084                                "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
1085                                *argv);
1086                        return -1;
1087                }
1088                addattr_nest_end(&req.n, linkinfo);
1089        } else if (flags & NLM_F_CREATE) {
1090                fprintf(stderr,
1091                        "Not enough information: \"type\" argument is required\n");
1092                return -1;
1093        }
1094
1095        if (rtnl_talk(&rth, &req.n, NULL) < 0)
1096                return -2;
1097
1098        /* remove device from cache; next use can refresh with new data */
1099        ll_drop_by_index(req.i.ifi_index);
1100
1101        return 0;
1102}
1103
1104int iplink_get(char *name, __u32 filt_mask)
1105{
1106        struct iplink_req req = {
1107                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
1108                .n.nlmsg_flags = NLM_F_REQUEST,
1109                .n.nlmsg_type = RTM_GETLINK,
1110                .i.ifi_family = preferred_family,
1111        };
1112        struct nlmsghdr *answer;
1113
1114        if (name) {
1115                addattr_l(&req.n, sizeof(req),
1116                          !check_ifname(name) ? IFLA_IFNAME : IFLA_ALT_IFNAME,
1117                          name, strlen(name) + 1);
1118        }
1119        addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
1120
1121        if (rtnl_talk(&rth, &req.n, &answer) < 0)
1122                return -2;
1123
1124        open_json_object(NULL);
1125        print_linkinfo(answer, stdout);
1126        close_json_object();
1127
1128        free(answer);
1129        return 0;
1130}
1131
1132#if IPLINK_IOCTL_COMPAT
1133static int get_ctl_fd(void)
1134{
1135        int s_errno;
1136        int fd;
1137
1138        fd = socket(PF_INET, SOCK_DGRAM, 0);
1139        if (fd >= 0)
1140                return fd;
1141        s_errno = errno;
1142        fd = socket(PF_PACKET, SOCK_DGRAM, 0);
1143        if (fd >= 0)
1144                return fd;
1145        fd = socket(PF_INET6, SOCK_DGRAM, 0);
1146        if (fd >= 0)
1147                return fd;
1148        errno = s_errno;
1149        perror("Cannot create control socket");
1150        return -1;
1151}
1152
1153static int do_chflags(const char *dev, __u32 flags, __u32 mask)
1154{
1155        struct ifreq ifr;
1156        int fd;
1157        int err;
1158
1159        strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
1160        fd = get_ctl_fd();
1161        if (fd < 0)
1162                return -1;
1163        err = ioctl(fd, SIOCGIFFLAGS, &ifr);
1164        if (err) {
1165                perror("SIOCGIFFLAGS");
1166                close(fd);
1167                return -1;
1168        }
1169        if ((ifr.ifr_flags^flags)&mask) {
1170                ifr.ifr_flags &= ~mask;
1171                ifr.ifr_flags |= mask&flags;
1172                err = ioctl(fd, SIOCSIFFLAGS, &ifr);
1173                if (err)
1174                        perror("SIOCSIFFLAGS");
1175        }
1176        close(fd);
1177        return err;
1178}
1179
1180static int do_changename(const char *dev, const char *newdev)
1181{
1182        struct ifreq ifr;
1183        int fd;
1184        int err;
1185
1186        strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
1187        strlcpy(ifr.ifr_newname, newdev, IFNAMSIZ);
1188        fd = get_ctl_fd();
1189        if (fd < 0)
1190                return -1;
1191        err = ioctl(fd, SIOCSIFNAME, &ifr);
1192        if (err) {
1193                perror("SIOCSIFNAME");
1194                close(fd);
1195                return -1;
1196        }
1197        close(fd);
1198        return err;
1199}
1200
1201static int set_qlen(const char *dev, int qlen)
1202{
1203        struct ifreq ifr = { .ifr_qlen = qlen };
1204        int s;
1205
1206        s = get_ctl_fd();
1207        if (s < 0)
1208                return -1;
1209
1210        strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
1211        if (ioctl(s, SIOCSIFTXQLEN, &ifr) < 0) {
1212                perror("SIOCSIFXQLEN");
1213                close(s);
1214                return -1;
1215        }
1216        close(s);
1217
1218        return 0;
1219}
1220
1221static int set_mtu(const char *dev, int mtu)
1222{
1223        struct ifreq ifr = { .ifr_mtu = mtu };
1224        int s;
1225
1226        s = get_ctl_fd();
1227        if (s < 0)
1228                return -1;
1229
1230        strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
1231        if (ioctl(s, SIOCSIFMTU, &ifr) < 0) {
1232                perror("SIOCSIFMTU");
1233                close(s);
1234                return -1;
1235        }
1236        close(s);
1237
1238        return 0;
1239}
1240
1241static int get_address(const char *dev, int *htype)
1242{
1243        struct ifreq ifr = {};
1244        struct sockaddr_ll me = {
1245                .sll_family = AF_PACKET,
1246                .sll_protocol = htons(ETH_P_LOOP),
1247        };
1248        socklen_t alen;
1249        int s;
1250
1251        s = socket(PF_PACKET, SOCK_DGRAM, 0);
1252        if (s < 0) {
1253                perror("socket(PF_PACKET)");
1254                return -1;
1255        }
1256
1257        strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
1258        if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
1259                perror("SIOCGIFINDEX");
1260                close(s);
1261                return -1;
1262        }
1263
1264        me.sll_ifindex = ifr.ifr_ifindex;
1265        if (bind(s, (struct sockaddr *)&me, sizeof(me)) == -1) {
1266                perror("bind");
1267                close(s);
1268                return -1;
1269        }
1270
1271        alen = sizeof(me);
1272        if (getsockname(s, (struct sockaddr *)&me, &alen) == -1) {
1273                perror("getsockname");
1274                close(s);
1275                return -1;
1276        }
1277        close(s);
1278        *htype = me.sll_hatype;
1279        return me.sll_halen;
1280}
1281
1282static int parse_address(const char *dev, int hatype, int halen,
1283                char *lla, struct ifreq *ifr)
1284{
1285        int alen;
1286
1287        memset(ifr, 0, sizeof(*ifr));
1288        strlcpy(ifr->ifr_name, dev, IFNAMSIZ);
1289        ifr->ifr_hwaddr.sa_family = hatype;
1290        alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla);
1291        if (alen < 0)
1292                return -1;
1293        if (alen != halen) {
1294                fprintf(stderr,
1295                        "Wrong address (%s) length: expected %d bytes\n",
1296                        lla, halen);
1297                return -1;
1298        }
1299        return 0;
1300}
1301
1302static int set_address(struct ifreq *ifr, int brd)
1303{
1304        int s;
1305
1306        s = get_ctl_fd();
1307        if (s < 0)
1308                return -1;
1309        if (ioctl(s, brd?SIOCSIFHWBROADCAST:SIOCSIFHWADDR, ifr) < 0) {
1310                perror(brd?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
1311                close(s);
1312                return -1;
1313        }
1314        close(s);
1315        return 0;
1316}
1317
1318static int do_set(int argc, char **argv)
1319{
1320        char *dev = NULL;
1321        __u32 mask = 0;
1322        __u32 flags = 0;
1323        int qlen = -1;
1324        int mtu = -1;
1325        char *newaddr = NULL;
1326        char *newbrd = NULL;
1327        struct ifreq ifr0, ifr1;
1328        char *newname = NULL;
1329        int htype, halen;
1330
1331        while (argc > 0) {
1332                if (strcmp(*argv, "up") == 0) {
1333                        mask |= IFF_UP;
1334                        flags |= IFF_UP;
1335                } else if (strcmp(*argv, "down") == 0) {
1336                        mask |= IFF_UP;
1337                        flags &= ~IFF_UP;
1338                } else if (strcmp(*argv, "name") == 0) {
1339                        NEXT_ARG();
1340                        if (check_ifname(*argv))
1341                                invarg("\"name\" not a valid ifname", *argv);
1342                        newname = *argv;
1343                } else if (matches(*argv, "address") == 0) {
1344                        NEXT_ARG();
1345                        newaddr = *argv;
1346                } else if (matches(*argv, "broadcast") == 0 ||
1347                           strcmp(*argv, "brd") == 0) {
1348                        NEXT_ARG();
1349                        newbrd = *argv;
1350                } else if (matches(*argv, "txqueuelen") == 0 ||
1351                           strcmp(*argv, "qlen") == 0 ||
1352                           matches(*argv, "txqlen") == 0) {
1353                        NEXT_ARG();
1354                        if (qlen != -1)
1355                                duparg("txqueuelen", *argv);
1356                        if (get_integer(&qlen,  *argv, 0))
1357                                invarg("Invalid \"txqueuelen\" value\n", *argv);
1358                } else if (strcmp(*argv, "mtu") == 0) {
1359                        NEXT_ARG();
1360                        if (mtu != -1)
1361                                duparg("mtu", *argv);
1362                        if (get_integer(&mtu, *argv, 0))
1363                                invarg("Invalid \"mtu\" value\n", *argv);
1364                } else if (strcmp(*argv, "multicast") == 0) {
1365                        NEXT_ARG();
1366                        mask |= IFF_MULTICAST;
1367
1368                        if (strcmp(*argv, "on") == 0)
1369                                flags |= IFF_MULTICAST;
1370                        else if (strcmp(*argv, "off") == 0)
1371                                flags &= ~IFF_MULTICAST;
1372                        else
1373                                return on_off("multicast", *argv);
1374                } else if (strcmp(*argv, "allmulticast") == 0) {
1375                        NEXT_ARG();
1376                        mask |= IFF_ALLMULTI;
1377
1378                        if (strcmp(*argv, "on") == 0)
1379                                flags |= IFF_ALLMULTI;
1380                        else if (strcmp(*argv, "off") == 0)
1381                                flags &= ~IFF_ALLMULTI;
1382                        else
1383                                return on_off("allmulticast", *argv);
1384                } else if (strcmp(*argv, "promisc") == 0) {
1385                        NEXT_ARG();
1386                        mask |= IFF_PROMISC;
1387
1388                        if (strcmp(*argv, "on") == 0)
1389                                flags |= IFF_PROMISC;
1390                        else if (strcmp(*argv, "off") == 0)
1391                                flags &= ~IFF_PROMISC;
1392                        else
1393                                return on_off("promisc", *argv);
1394                } else if (strcmp(*argv, "trailers") == 0) {
1395                        NEXT_ARG();
1396                        mask |= IFF_NOTRAILERS;
1397
1398                        if (strcmp(*argv, "off") == 0)
1399                                flags |= IFF_NOTRAILERS;
1400                        else if (strcmp(*argv, "on") == 0)
1401                                flags &= ~IFF_NOTRAILERS;
1402                        else
1403                                return on_off("trailers", *argv);
1404                } else if (strcmp(*argv, "arp") == 0) {
1405                        NEXT_ARG();
1406                        mask |= IFF_NOARP;
1407
1408                        if (strcmp(*argv, "on") == 0)
1409                                flags &= ~IFF_NOARP;
1410                        else if (strcmp(*argv, "off") == 0)
1411                                flags |= IFF_NOARP;
1412                        else
1413                                return on_off("arp", *argv);
1414                } else if (matches(*argv, "dynamic") == 0) {
1415                        NEXT_ARG();
1416                        mask |= IFF_DYNAMIC;
1417
1418                        if (strcmp(*argv, "on") == 0)
1419                                flags |= IFF_DYNAMIC;
1420                        else if (strcmp(*argv, "off") == 0)
1421                                flags &= ~IFF_DYNAMIC;
1422                        else
1423                                return on_off("dynamic", *argv);
1424                } else {
1425                        if (strcmp(*argv, "dev") == 0)
1426                                NEXT_ARG();
1427                        else if (matches(*argv, "help") == 0)
1428                                usage();
1429
1430                        if (dev)
1431                                duparg2("dev", *argv);
1432                        if (check_ifname(*argv))
1433                                invarg("\"dev\" not a valid ifname", *argv);
1434                        dev = *argv;
1435                }
1436                argc--; argv++;
1437        }
1438
1439        if (!dev) {
1440                fprintf(stderr,
1441                        "Not enough of information: \"dev\" argument is required.\n");
1442                exit(-1);
1443        }
1444
1445        if (newaddr || newbrd) {
1446                halen = get_address(dev, &htype);
1447                if (halen < 0)
1448                        return -1;
1449                if (newaddr) {
1450                        if (parse_address(dev, htype, halen,
1451                                          newaddr, &ifr0) < 0)
1452                                return -1;
1453                }
1454                if (newbrd) {
1455                        if (parse_address(dev, htype, halen,
1456                                          newbrd, &ifr1) < 0)
1457                                return -1;
1458                }
1459        }
1460
1461        if (newname && strcmp(dev, newname)) {
1462                if (do_changename(dev, newname) < 0)
1463                        return -1;
1464                dev = newname;
1465        }
1466        if (qlen != -1) {
1467                if (set_qlen(dev, qlen) < 0)
1468                        return -1;
1469        }
1470        if (mtu != -1) {
1471                if (set_mtu(dev, mtu) < 0)
1472                        return -1;
1473        }
1474        if (newaddr || newbrd) {
1475                if (newbrd) {
1476                        if (set_address(&ifr1, 1) < 0)
1477                                return -1;
1478                }
1479                if (newaddr) {
1480                        if (set_address(&ifr0, 0) < 0)
1481                                return -1;
1482                }
1483        }
1484        if (mask)
1485                return do_chflags(dev, flags, mask);
1486        return 0;
1487}
1488#endif /* IPLINK_IOCTL_COMPAT */
1489
1490static void print_mpls_stats(FILE *fp, struct rtattr *attr)
1491{
1492        struct rtattr *mrtb[MPLS_STATS_MAX+1];
1493        struct mpls_link_stats *stats;
1494
1495        parse_rtattr(mrtb, MPLS_STATS_MAX, RTA_DATA(attr),
1496                     RTA_PAYLOAD(attr));
1497        if (!mrtb[MPLS_STATS_LINK])
1498                return;
1499
1500        stats = RTA_DATA(mrtb[MPLS_STATS_LINK]);
1501
1502        fprintf(fp, "    mpls:\n");
1503        fprintf(fp, "        RX: bytes  packets  errors  dropped  noroute\n");
1504        fprintf(fp, "        ");
1505        print_num(fp, 10, stats->rx_bytes);
1506        print_num(fp, 8, stats->rx_packets);
1507        print_num(fp, 7, stats->rx_errors);
1508        print_num(fp, 8, stats->rx_dropped);
1509        print_num(fp, 7, stats->rx_noroute);
1510        fprintf(fp, "\n");
1511        fprintf(fp, "        TX: bytes  packets  errors  dropped\n");
1512        fprintf(fp, "        ");
1513        print_num(fp, 10, stats->tx_bytes);
1514        print_num(fp, 8, stats->tx_packets);
1515        print_num(fp, 7, stats->tx_errors);
1516        print_num(fp, 7, stats->tx_dropped);
1517        fprintf(fp, "\n");
1518}
1519
1520static void print_af_stats_attr(FILE *fp, int ifindex, struct rtattr *attr)
1521{
1522        bool if_printed = false;
1523        struct rtattr *i;
1524        int rem;
1525
1526        rem = RTA_PAYLOAD(attr);
1527        for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
1528                if (preferred_family != AF_UNSPEC &&
1529                    i->rta_type != preferred_family)
1530                        continue;
1531
1532                if (!if_printed) {
1533                        fprintf(fp, "%u: %s\n", ifindex,
1534                                ll_index_to_name(ifindex));
1535                        if_printed = true;
1536                }
1537
1538                switch (i->rta_type) {
1539                case AF_MPLS:
1540                        print_mpls_stats(fp, i);
1541                        break;
1542                default:
1543                        fprintf(fp, "    unknown af(%d)\n", i->rta_type);
1544                        break;
1545                }
1546        }
1547}
1548
1549struct af_stats_ctx {
1550        FILE *fp;
1551        int ifindex;
1552};
1553
1554static int print_af_stats(struct nlmsghdr *n, void *arg)
1555{
1556        struct if_stats_msg *ifsm = NLMSG_DATA(n);
1557        struct rtattr *tb[IFLA_STATS_MAX+1];
1558        int len = n->nlmsg_len;
1559        struct af_stats_ctx *ctx = arg;
1560        FILE *fp = ctx->fp;
1561
1562        len -= NLMSG_LENGTH(sizeof(*ifsm));
1563        if (len < 0) {
1564                fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
1565                return -1;
1566        }
1567
1568        if (ctx->ifindex && ifsm->ifindex != ctx->ifindex)
1569                return 0;
1570
1571        parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
1572
1573        if (tb[IFLA_STATS_AF_SPEC])
1574                print_af_stats_attr(fp, ifsm->ifindex, tb[IFLA_STATS_AF_SPEC]);
1575
1576        fflush(fp);
1577        return 0;
1578}
1579
1580static int iplink_afstats(int argc, char **argv)
1581{
1582        __u32 filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_AF_SPEC);
1583        const char *filter_dev = NULL;
1584        struct af_stats_ctx ctx = {
1585                .fp = stdout,
1586                .ifindex = 0,
1587        };
1588
1589        while (argc > 0) {
1590                if (strcmp(*argv, "dev") == 0) {
1591                        NEXT_ARG();
1592                        if (filter_dev)
1593                                duparg2("dev", *argv);
1594                        filter_dev = *argv;
1595                } else if (matches(*argv, "help") == 0) {
1596                        usage();
1597                } else {
1598                        fprintf(stderr,
1599                                "Command \"%s\" is unknown, try \"ip link help\".\n",
1600                                *argv);
1601                        exit(-1);
1602                }
1603
1604                argv++; argc--;
1605        }
1606
1607        if (filter_dev) {
1608                ctx.ifindex = ll_name_to_index(filter_dev);
1609                if (ctx.ifindex <= 0) {
1610                        fprintf(stderr,
1611                                "Device \"%s\" does not exist.\n",
1612                                filter_dev);
1613                        return -1;
1614                }
1615        }
1616
1617        if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask) < 0) {
1618                perror("Cannont send dump request");
1619                return 1;
1620        }
1621
1622        if (rtnl_dump_filter(&rth, print_af_stats, &ctx) < 0) {
1623                fprintf(stderr, "Dump terminated\n");
1624                return 1;
1625        }
1626
1627        return 0;
1628}
1629
1630static int iplink_prop_mod(int argc, char **argv, struct iplink_req *req)
1631{
1632        struct rtattr *proplist;
1633        char *dev = NULL;
1634        char *name;
1635
1636        proplist = addattr_nest(&req->n, sizeof(*req),
1637                                IFLA_PROP_LIST | NLA_F_NESTED);
1638
1639        while (argc > 0) {
1640                if (matches(*argv, "altname") == 0) {
1641                        NEXT_ARG();
1642                        if (check_altifname(*argv))
1643                                invarg("not a valid altname", *argv);
1644                        name = *argv;
1645                        addattr_l(&req->n, sizeof(*req), IFLA_ALT_IFNAME,
1646                                  name, strlen(name) + 1);
1647                } else if (matches(*argv, "help") == 0) {
1648                        usage();
1649                } else {
1650                        if (strcmp(*argv, "dev") == 0)
1651                                NEXT_ARG();
1652                        if (dev)
1653                                duparg2("dev", *argv);
1654                        if (check_altifname(*argv))
1655                                invarg("\"dev\" not a valid ifname", *argv);
1656                        dev = *argv;
1657                }
1658                argv++; argc--;
1659        }
1660        addattr_nest_end(&req->n, proplist);
1661
1662        if (!dev) {
1663                fprintf(stderr, "Not enough of information: \"dev\" argument is required.\n");
1664                exit(-1);
1665        }
1666
1667        req->i.ifi_index = ll_name_to_index(dev);
1668        if (!req->i.ifi_index)
1669                return nodev(dev);
1670
1671        if (rtnl_talk(&rth, &req->n, NULL) < 0)
1672                return -2;
1673
1674        return 0;
1675}
1676
1677static int iplink_prop(int argc, char **argv)
1678{
1679        struct iplink_req req = {
1680                .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
1681                .n.nlmsg_flags = NLM_F_REQUEST,
1682                .i.ifi_family = preferred_family,
1683        };
1684
1685        if (argc <= 0) {
1686                usage();
1687                exit(-1);
1688        }
1689
1690        if (matches(*argv, "add") == 0) {
1691                req.n.nlmsg_flags |= NLM_F_EXCL | NLM_F_CREATE | NLM_F_APPEND;
1692                req.n.nlmsg_type = RTM_NEWLINKPROP;
1693        } else if (matches(*argv, "del") == 0) {
1694                req.n.nlmsg_type = RTM_DELLINKPROP;
1695        } else if (matches(*argv, "help") == 0) {
1696                usage();
1697        } else {
1698                fprintf(stderr, "Operator required\n");
1699                exit(-1);
1700        }
1701        return iplink_prop_mod(argc - 1, argv + 1, &req);
1702}
1703
1704static void do_help(int argc, char **argv)
1705{
1706        struct link_util *lu = NULL;
1707
1708        if (argc <= 0) {
1709                usage();
1710                return;
1711        }
1712
1713        lu = get_link_kind(*argv);
1714        if (lu && lu->print_help)
1715                lu->print_help(lu, argc-1, argv+1, stdout);
1716        else
1717                usage();
1718}
1719
1720int do_iplink(int argc, char **argv)
1721{
1722        if (argc < 1)
1723                return ipaddr_list_link(0, NULL);
1724
1725        if (iplink_have_newlink()) {
1726                if (matches(*argv, "add") == 0)
1727                        return iplink_modify(RTM_NEWLINK,
1728                                             NLM_F_CREATE|NLM_F_EXCL,
1729                                             argc-1, argv+1);
1730                if (matches(*argv, "set") == 0 ||
1731                    matches(*argv, "change") == 0)
1732                        return iplink_modify(RTM_NEWLINK, 0,
1733                                             argc-1, argv+1);
1734                if (matches(*argv, "replace") == 0)
1735                        return iplink_modify(RTM_NEWLINK,
1736                                             NLM_F_CREATE|NLM_F_REPLACE,
1737                                             argc-1, argv+1);
1738                if (matches(*argv, "delete") == 0)
1739                        return iplink_modify(RTM_DELLINK, 0,
1740                                             argc-1, argv+1);
1741        } else {
1742#if IPLINK_IOCTL_COMPAT
1743                if (matches(*argv, "set") == 0)
1744                        return do_set(argc-1, argv+1);
1745#endif
1746        }
1747
1748        if (matches(*argv, "show") == 0 ||
1749            matches(*argv, "lst") == 0 ||
1750            matches(*argv, "list") == 0)
1751                return ipaddr_list_link(argc-1, argv+1);
1752
1753        if (matches(*argv, "xstats") == 0)
1754                return iplink_ifla_xstats(argc-1, argv+1);
1755
1756        if (matches(*argv, "afstats") == 0) {
1757                iplink_afstats(argc-1, argv+1);
1758                return 0;
1759        }
1760
1761        if (matches(*argv, "property") == 0)
1762                return iplink_prop(argc-1, argv+1);
1763
1764        if (matches(*argv, "help") == 0) {
1765                do_help(argc-1, argv+1);
1766                return 0;
1767        }
1768
1769        fprintf(stderr, "Command \"%s\" is unknown, try \"ip link help\".\n",
1770                *argv);
1771        exit(-1);
1772}
1773