Home | History | Annotate | Download | only in ip
      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 (at) ms2.inr.ac.ru>
     10  *
     11  */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <unistd.h>
     16 #include <syslog.h>
     17 #include <fcntl.h>
     18 #include <dlfcn.h>
     19 #include <errno.h>
     20 #include <sys/socket.h>
     21 #include <linux/if.h>
     22 #include <linux/if_packet.h>
     23 #include <linux/if_ether.h>
     24 #include <linux/sockios.h>
     25 #include <netinet/in.h>
     26 #include <arpa/inet.h>
     27 #include <string.h>
     28 #include <sys/ioctl.h>
     29 #include <linux/sockios.h>
     30 #include <stdbool.h>
     31 
     32 #include "rt_names.h"
     33 #include "utils.h"
     34 #include "ip_common.h"
     35 #include "namespace.h"
     36 
     37 #define IPLINK_IOCTL_COMPAT	1
     38 #ifndef LIBDIR
     39 #define LIBDIR "/usr/lib"
     40 #endif
     41 
     42 static void usage(void) __attribute__((noreturn));
     43 static int iplink_have_newlink(void);
     44 
     45 void iplink_usage(void)
     46 {
     47 	if (iplink_have_newlink()) {
     48 		fprintf(stderr, "Usage: ip link add [link DEV] [ name ] NAME\n");
     49 		fprintf(stderr, "                   [ txqueuelen PACKETS ]\n");
     50 		fprintf(stderr, "                   [ address LLADDR ]\n");
     51 		fprintf(stderr, "                   [ broadcast LLADDR ]\n");
     52 		fprintf(stderr, "                   [ mtu MTU ] [index IDX ]\n");
     53 		fprintf(stderr, "                   [ numtxqueues QUEUE_COUNT ]\n");
     54 		fprintf(stderr, "                   [ numrxqueues QUEUE_COUNT ]\n");
     55 		fprintf(stderr, "                   type TYPE [ ARGS ]\n");
     56 		fprintf(stderr, "       ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n");
     57 		fprintf(stderr, "\n");
     58 		fprintf(stderr, "       ip link set { DEVICE | dev DEVICE | group DEVGROUP } [ { up | down } ]\n");
     59 	} else
     60 		fprintf(stderr, "Usage: ip link set DEVICE [ { up | down } ]\n");
     61 
     62 	fprintf(stderr, "	                  [ arp { on | off } ]\n");
     63 	fprintf(stderr, "	                  [ dynamic { on | off } ]\n");
     64 	fprintf(stderr, "	                  [ multicast { on | off } ]\n");
     65 	fprintf(stderr, "	                  [ allmulticast { on | off } ]\n");
     66 	fprintf(stderr, "	                  [ promisc { on | off } ]\n");
     67 	fprintf(stderr, "	                  [ trailers { on | off } ]\n");
     68 	fprintf(stderr, "	                  [ txqueuelen PACKETS ]\n");
     69 	fprintf(stderr, "	                  [ name NEWNAME ]\n");
     70 	fprintf(stderr, "	                  [ address LLADDR ]\n");
     71 	fprintf(stderr, "	                  [ broadcast LLADDR ]\n");
     72 	fprintf(stderr, "	                  [ mtu MTU ]\n");
     73 	fprintf(stderr, "	                  [ netns PID ]\n");
     74 	fprintf(stderr, "	                  [ netns NAME ]\n");
     75 	fprintf(stderr, "	                  [ link-netnsid ID ]\n");
     76 	fprintf(stderr, "			  [ alias NAME ]\n");
     77 	fprintf(stderr, "	                  [ vf NUM [ mac LLADDR ]\n");
     78 	fprintf(stderr, "				   [ vlan VLANID [ qos VLAN-QOS ] ]\n");
     79 
     80 	fprintf(stderr, "				   [ rate TXRATE ] ]\n");
     81 
     82 	fprintf(stderr, "				   [ spoofchk { on | off} ] ]\n");
     83 	fprintf(stderr, "				   [ query_rss { on | off} ] ]\n");
     84 	fprintf(stderr, "				   [ state { auto | enable | disable} ] ]\n");
     85 	fprintf(stderr, "			  [ master DEVICE ]\n");
     86 	fprintf(stderr, "			  [ nomaster ]\n");
     87 	fprintf(stderr, "			  [ addrgenmode { eui64 | none | stable_secret | random } ]\n");
     88 	fprintf(stderr, "	                  [ protodown { on | off } ]\n");
     89 	fprintf(stderr, "       ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n");
     90 
     91 	if (iplink_have_newlink()) {
     92 		fprintf(stderr, "       ip link help [ TYPE ]\n");
     93 		fprintf(stderr, "\n");
     94 		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
     95 		fprintf(stderr, "          bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n");
     96 		fprintf(stderr, "          gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n");
     97 		fprintf(stderr, "          bond_slave | ipvlan | geneve | bridge_slave | vrf }\n");
     98 	}
     99 	exit(-1);
    100 }
    101 
    102 static void usage(void)
    103 {
    104 	iplink_usage();
    105 }
    106 
    107 static int on_off(const char *msg, const char *realval)
    108 {
    109 	fprintf(stderr,
    110 		"Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
    111 		msg, realval);
    112 	return -1;
    113 }
    114 
    115 static void *BODY;		/* cached dlopen(NULL) handle */
    116 static struct link_util *linkutil_list;
    117 
    118 static struct link_util *__get_link_kind(const char *id, bool slave)
    119 {
    120 	void *dlh;
    121 	char buf[256];
    122 	struct link_util *l;
    123 
    124 	for (l = linkutil_list; l; l = l->next)
    125 		if (strcmp(l->id, id) == 0 &&
    126 		    l->slave == slave)
    127 			return l;
    128 
    129 	snprintf(buf, sizeof(buf), LIBDIR "/ip/link_%s.so", id);
    130 	dlh = dlopen(buf, RTLD_LAZY);
    131 	if (dlh == NULL) {
    132 		/* look in current binary, only open once */
    133 		dlh = BODY;
    134 		if (dlh == NULL) {
    135 			dlh = BODY = dlopen(NULL, RTLD_LAZY);
    136 			if (dlh == NULL)
    137 				return NULL;
    138 		}
    139 	}
    140 
    141 	if (slave)
    142 		snprintf(buf, sizeof(buf), "%s_slave_link_util", id);
    143 	else
    144 		snprintf(buf, sizeof(buf), "%s_link_util", id);
    145 	l = dlsym(dlh, buf);
    146 	if (l == NULL)
    147 		return NULL;
    148 
    149 	l->next = linkutil_list;
    150 	linkutil_list = l;
    151 	return l;
    152 }
    153 
    154 struct link_util *get_link_kind(const char *id)
    155 {
    156 	return __get_link_kind(id, false);
    157 }
    158 
    159 struct link_util *get_link_slave_kind(const char *id)
    160 {
    161 	return __get_link_kind(id, true);
    162 }
    163 
    164 static int get_link_mode(const char *mode)
    165 {
    166 	if (strcasecmp(mode, "default") == 0)
    167 		return IF_LINK_MODE_DEFAULT;
    168 	if (strcasecmp(mode, "dormant") == 0)
    169 		return IF_LINK_MODE_DORMANT;
    170 	return -1;
    171 }
    172 
    173 static int get_addr_gen_mode(const char *mode)
    174 {
    175 	if (strcasecmp(mode, "eui64") == 0)
    176 		return IN6_ADDR_GEN_MODE_EUI64;
    177 	if (strcasecmp(mode, "none") == 0)
    178 		return IN6_ADDR_GEN_MODE_NONE;
    179 	if (strcasecmp(mode, "stable_secret") == 0)
    180 		return IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
    181 	if (strcasecmp(mode, "random") == 0)
    182 		return IN6_ADDR_GEN_MODE_RANDOM;
    183 	return -1;
    184 }
    185 
    186 #if IPLINK_IOCTL_COMPAT
    187 static int have_rtnl_newlink = -1;
    188 
    189 static int accept_msg(const struct sockaddr_nl *who,
    190 		      struct rtnl_ctrl_data *ctrl,
    191 		      struct nlmsghdr *n, void *arg)
    192 {
    193 	struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
    194 
    195 	if (n->nlmsg_type == NLMSG_ERROR &&
    196 	    (err->error == -EOPNOTSUPP || err->error == -EINVAL))
    197 		have_rtnl_newlink = 0;
    198 	else
    199 		have_rtnl_newlink = 1;
    200 	return -1;
    201 }
    202 
    203 static int iplink_have_newlink(void)
    204 {
    205 	struct {
    206 		struct nlmsghdr		n;
    207 		struct ifinfomsg	i;
    208 		char			buf[1024];
    209 	} req;
    210 
    211 	if (have_rtnl_newlink < 0) {
    212 		memset(&req, 0, sizeof(req));
    213 
    214 		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    215 		req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
    216 		req.n.nlmsg_type = RTM_NEWLINK;
    217 		req.i.ifi_family = AF_UNSPEC;
    218 
    219 		if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
    220 			perror("request send failed");
    221 			exit(1);
    222 		}
    223 		rtnl_listen(&rth, accept_msg, NULL);
    224 	}
    225 	return have_rtnl_newlink;
    226 }
    227 #else /* IPLINK_IOCTL_COMPAT */
    228 static int iplink_have_newlink(void)
    229 {
    230 	return 1;
    231 }
    232 #endif /* ! IPLINK_IOCTL_COMPAT */
    233 
    234 struct iplink_req {
    235 	struct nlmsghdr		n;
    236 	struct ifinfomsg	i;
    237 	char			buf[1024];
    238 };
    239 
    240 static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
    241 			   struct iplink_req *req, int dev_index)
    242 {
    243 	char new_rate_api = 0, count = 0, override_legacy_rate = 0;
    244 	struct ifla_vf_rate tivt;
    245 	int len, argc = *argcp;
    246 	char **argv = *argvp;
    247 	struct rtattr *vfinfo;
    248 
    249 	tivt.min_tx_rate = -1;
    250 	tivt.max_tx_rate = -1;
    251 
    252 	vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
    253 
    254 	while (NEXT_ARG_OK()) {
    255 		NEXT_ARG();
    256 		count++;
    257 		if (!matches(*argv, "max_tx_rate")) {
    258 			/* new API in use */
    259 			new_rate_api = 1;
    260 			/* override legacy rate */
    261 			override_legacy_rate = 1;
    262 		} else if (!matches(*argv, "min_tx_rate")) {
    263 			/* new API in use */
    264 			new_rate_api = 1;
    265 		}
    266 	}
    267 
    268 	while (count--) {
    269 		/* rewind arg */
    270 		PREV_ARG();
    271 	}
    272 
    273 	while (NEXT_ARG_OK()) {
    274 		NEXT_ARG();
    275 		if (matches(*argv, "mac") == 0) {
    276 			struct ifla_vf_mac ivm;
    277 
    278 			NEXT_ARG();
    279 			ivm.vf = vf;
    280 			len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
    281 			if (len < 0)
    282 				return -1;
    283 			addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm));
    284 		} else if (matches(*argv, "vlan") == 0) {
    285 			struct ifla_vf_vlan ivv;
    286 
    287 			NEXT_ARG();
    288 			if (get_unsigned(&ivv.vlan, *argv, 0))
    289 				invarg("Invalid \"vlan\" value\n", *argv);
    290 
    291 			ivv.vf = vf;
    292 			ivv.qos = 0;
    293 			if (NEXT_ARG_OK()) {
    294 				NEXT_ARG();
    295 				if (matches(*argv, "qos") == 0) {
    296 					NEXT_ARG();
    297 					if (get_unsigned(&ivv.qos, *argv, 0))
    298 						invarg("Invalid \"qos\" value\n", *argv);
    299 				} else {
    300 					/* rewind arg */
    301 					PREV_ARG();
    302 				}
    303 			}
    304 			addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv));
    305 		} else if (matches(*argv, "rate") == 0) {
    306 			struct ifla_vf_tx_rate ivt;
    307 
    308 			NEXT_ARG();
    309 			if (get_unsigned(&ivt.rate, *argv, 0))
    310 				invarg("Invalid \"rate\" value\n", *argv);
    311 
    312 			ivt.vf = vf;
    313 			if (!new_rate_api)
    314 				addattr_l(&req->n, sizeof(*req),
    315 					  IFLA_VF_TX_RATE, &ivt, sizeof(ivt));
    316 			else if (!override_legacy_rate)
    317 				tivt.max_tx_rate = ivt.rate;
    318 
    319 		} else if (matches(*argv, "max_tx_rate") == 0) {
    320 			NEXT_ARG();
    321 			if (get_unsigned(&tivt.max_tx_rate, *argv, 0))
    322 				invarg("Invalid \"max tx rate\" value\n",
    323 				       *argv);
    324 			tivt.vf = vf;
    325 
    326 		} else if (matches(*argv, "min_tx_rate") == 0) {
    327 			NEXT_ARG();
    328 			if (get_unsigned(&tivt.min_tx_rate, *argv, 0))
    329 				invarg("Invalid \"min tx rate\" value\n",
    330 				       *argv);
    331 			tivt.vf = vf;
    332 
    333 		} else if (matches(*argv, "spoofchk") == 0) {
    334 			struct ifla_vf_spoofchk ivs;
    335 
    336 			NEXT_ARG();
    337 			if (matches(*argv, "on") == 0)
    338 				ivs.setting = 1;
    339 			else if (matches(*argv, "off") == 0)
    340 				ivs.setting = 0;
    341 			else
    342 				return on_off("spoofchk", *argv);
    343 			ivs.vf = vf;
    344 			addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs));
    345 
    346 		} else if (matches(*argv, "query_rss") == 0) {
    347 			struct ifla_vf_rss_query_en ivs;
    348 
    349 			NEXT_ARG();
    350 			if (matches(*argv, "on") == 0)
    351 				ivs.setting = 1;
    352 			else if (matches(*argv, "off") == 0)
    353 				ivs.setting = 0;
    354 			else
    355 				return on_off("query_rss", *argv);
    356 			ivs.vf = vf;
    357 			addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(ivs));
    358 
    359 		} else if (matches(*argv, "state") == 0) {
    360 			struct ifla_vf_link_state ivl;
    361 
    362 			NEXT_ARG();
    363 			if (matches(*argv, "auto") == 0)
    364 				ivl.link_state = IFLA_VF_LINK_STATE_AUTO;
    365 			else if (matches(*argv, "enable") == 0)
    366 				ivl.link_state = IFLA_VF_LINK_STATE_ENABLE;
    367 			else if (matches(*argv, "disable") == 0)
    368 				ivl.link_state = IFLA_VF_LINK_STATE_DISABLE;
    369 			else
    370 				invarg("Invalid \"state\" value\n", *argv);
    371 			ivl.vf = vf;
    372 			addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl));
    373 		} else {
    374 			/* rewind arg */
    375 			PREV_ARG();
    376 			break;
    377 		}
    378 	}
    379 
    380 	if (new_rate_api) {
    381 		int tmin, tmax;
    382 
    383 		if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) {
    384 			ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index);
    385 			if (tivt.min_tx_rate == -1)
    386 				tivt.min_tx_rate = tmin;
    387 			if (tivt.max_tx_rate == -1)
    388 				tivt.max_tx_rate = tmax;
    389 		}
    390 		addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt,
    391 			  sizeof(tivt));
    392 	}
    393 
    394 	if (argc == *argcp)
    395 		incomplete_command();
    396 
    397 	addattr_nest_end(&req->n, vfinfo);
    398 
    399 	*argcp = argc;
    400 	*argvp = argv;
    401 	return 0;
    402 }
    403 
    404 int iplink_parse(int argc, char **argv, struct iplink_req *req,
    405 		 char **name, char **type, char **link, char **dev,
    406 		 int *group, int *index)
    407 {
    408 	int ret, len;
    409 	char abuf[32];
    410 	int qlen = -1;
    411 	int mtu = -1;
    412 	int netns = -1;
    413 	int vf = -1;
    414 	int numtxqueues = -1;
    415 	int numrxqueues = -1;
    416 	int dev_index = 0;
    417 	int link_netnsid = -1;
    418 
    419 	*group = -1;
    420 	ret = argc;
    421 
    422 	while (argc > 0) {
    423 		if (strcmp(*argv, "up") == 0) {
    424 			req->i.ifi_change |= IFF_UP;
    425 			req->i.ifi_flags |= IFF_UP;
    426 		} else if (strcmp(*argv, "down") == 0) {
    427 			req->i.ifi_change |= IFF_UP;
    428 			req->i.ifi_flags &= ~IFF_UP;
    429 		} else if (strcmp(*argv, "name") == 0) {
    430 			NEXT_ARG();
    431 			*name = *argv;
    432 		} else if (strcmp(*argv, "index") == 0) {
    433 			NEXT_ARG();
    434 			*index = atoi(*argv);
    435 			if (*index < 0)
    436 				invarg("Invalid \"index\" value", *argv);
    437 		} else if (matches(*argv, "link") == 0) {
    438 			NEXT_ARG();
    439 			*link = *argv;
    440 		} else if (matches(*argv, "address") == 0) {
    441 			NEXT_ARG();
    442 			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
    443 			if (len < 0)
    444 				return -1;
    445 			addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len);
    446 		} else if (matches(*argv, "broadcast") == 0 ||
    447 			   strcmp(*argv, "brd") == 0) {
    448 			NEXT_ARG();
    449 			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
    450 			if (len < 0)
    451 				return -1;
    452 			addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
    453 		} else if (matches(*argv, "txqueuelen") == 0 ||
    454 			   strcmp(*argv, "qlen") == 0 ||
    455 			   matches(*argv, "txqlen") == 0) {
    456 			NEXT_ARG();
    457 			if (qlen != -1)
    458 				duparg("txqueuelen", *argv);
    459 			if (get_integer(&qlen,  *argv, 0))
    460 				invarg("Invalid \"txqueuelen\" value\n", *argv);
    461 			addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
    462 		} else if (strcmp(*argv, "mtu") == 0) {
    463 			NEXT_ARG();
    464 			if (mtu != -1)
    465 				duparg("mtu", *argv);
    466 			if (get_integer(&mtu, *argv, 0))
    467 				invarg("Invalid \"mtu\" value\n", *argv);
    468 			addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
    469 		} else if (strcmp(*argv, "netns") == 0) {
    470 			NEXT_ARG();
    471 			if (netns != -1)
    472 				duparg("netns", *argv);
    473 			netns = netns_get_fd(*argv);
    474 			if (netns >= 0)
    475 				addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
    476 			else if (get_integer(&netns, *argv, 0) == 0)
    477 				addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
    478 			else
    479 				invarg("Invalid \"netns\" value\n", *argv);
    480 		} else if (strcmp(*argv, "multicast") == 0) {
    481 			NEXT_ARG();
    482 			req->i.ifi_change |= IFF_MULTICAST;
    483 
    484 			if (strcmp(*argv, "on") == 0)
    485 				req->i.ifi_flags |= IFF_MULTICAST;
    486 			else if (strcmp(*argv, "off") == 0)
    487 				req->i.ifi_flags &= ~IFF_MULTICAST;
    488 			else
    489 				return on_off("multicast", *argv);
    490 		} else if (strcmp(*argv, "allmulticast") == 0) {
    491 			NEXT_ARG();
    492 			req->i.ifi_change |= IFF_ALLMULTI;
    493 
    494 			if (strcmp(*argv, "on") == 0)
    495 				req->i.ifi_flags |= IFF_ALLMULTI;
    496 			else if (strcmp(*argv, "off") == 0)
    497 				req->i.ifi_flags &= ~IFF_ALLMULTI;
    498 			else
    499 				return on_off("allmulticast", *argv);
    500 		} else if (strcmp(*argv, "promisc") == 0) {
    501 			NEXT_ARG();
    502 			req->i.ifi_change |= IFF_PROMISC;
    503 
    504 			if (strcmp(*argv, "on") == 0)
    505 				req->i.ifi_flags |= IFF_PROMISC;
    506 			else if (strcmp(*argv, "off") == 0)
    507 				req->i.ifi_flags &= ~IFF_PROMISC;
    508 			else
    509 				return on_off("promisc", *argv);
    510 		} else if (strcmp(*argv, "trailers") == 0) {
    511 			NEXT_ARG();
    512 			req->i.ifi_change |= IFF_NOTRAILERS;
    513 
    514 			if (strcmp(*argv, "off") == 0)
    515 				req->i.ifi_flags |= IFF_NOTRAILERS;
    516 			else if (strcmp(*argv, "on") == 0)
    517 				req->i.ifi_flags &= ~IFF_NOTRAILERS;
    518 			else
    519 				return on_off("trailers", *argv);
    520 		} else if (strcmp(*argv, "arp") == 0) {
    521 			NEXT_ARG();
    522 			req->i.ifi_change |= IFF_NOARP;
    523 
    524 			if (strcmp(*argv, "on") == 0)
    525 				req->i.ifi_flags &= ~IFF_NOARP;
    526 			else if (strcmp(*argv, "off") == 0)
    527 				req->i.ifi_flags |= IFF_NOARP;
    528 			else
    529 				return on_off("arp", *argv);
    530 		} else if (strcmp(*argv, "vf") == 0) {
    531 			struct rtattr *vflist;
    532 
    533 			NEXT_ARG();
    534 			if (get_integer(&vf,  *argv, 0))
    535 				invarg("Invalid \"vf\" value\n", *argv);
    536 
    537 			vflist = addattr_nest(&req->n, sizeof(*req),
    538 					      IFLA_VFINFO_LIST);
    539 			if (dev_index == 0)
    540 				missarg("dev");
    541 
    542 			len = iplink_parse_vf(vf, &argc, &argv, req, dev_index);
    543 			if (len < 0)
    544 				return -1;
    545 			addattr_nest_end(&req->n, vflist);
    546 		} else if (matches(*argv, "master") == 0) {
    547 			int ifindex;
    548 
    549 			NEXT_ARG();
    550 			ifindex = ll_name_to_index(*argv);
    551 			if (!ifindex)
    552 				invarg("Device does not exist\n", *argv);
    553 			addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
    554 				  &ifindex, 4);
    555 		} else if (matches(*argv, "nomaster") == 0) {
    556 			int ifindex = 0;
    557 
    558 			addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
    559 				  &ifindex, 4);
    560 		} else if (matches(*argv, "dynamic") == 0) {
    561 			NEXT_ARG();
    562 			req->i.ifi_change |= IFF_DYNAMIC;
    563 
    564 			if (strcmp(*argv, "on") == 0)
    565 				req->i.ifi_flags |= IFF_DYNAMIC;
    566 			else if (strcmp(*argv, "off") == 0)
    567 				req->i.ifi_flags &= ~IFF_DYNAMIC;
    568 			else
    569 				return on_off("dynamic", *argv);
    570 		} else if (matches(*argv, "type") == 0) {
    571 			NEXT_ARG();
    572 			*type = *argv;
    573 			argc--; argv++;
    574 			break;
    575 		} else if (matches(*argv, "alias") == 0) {
    576 			NEXT_ARG();
    577 			addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
    578 				  *argv, strlen(*argv));
    579 			argc--; argv++;
    580 			break;
    581 		} else if (strcmp(*argv, "group") == 0) {
    582 			NEXT_ARG();
    583 			if (*group != -1)
    584 				duparg("group", *argv);
    585 			if (rtnl_group_a2n(group, *argv))
    586 				invarg("Invalid \"group\" value\n", *argv);
    587 		} else if (strcmp(*argv, "mode") == 0) {
    588 			int mode;
    589 
    590 			NEXT_ARG();
    591 			mode = get_link_mode(*argv);
    592 			if (mode < 0)
    593 				invarg("Invalid link mode\n", *argv);
    594 			addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
    595 		} else if (strcmp(*argv, "state") == 0) {
    596 			int state;
    597 
    598 			NEXT_ARG();
    599 			state = get_operstate(*argv);
    600 			if (state < 0)
    601 				invarg("Invalid operstate\n", *argv);
    602 
    603 			addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
    604 		} else if (matches(*argv, "numtxqueues") == 0) {
    605 			NEXT_ARG();
    606 			if (numtxqueues != -1)
    607 				duparg("numtxqueues", *argv);
    608 			if (get_integer(&numtxqueues, *argv, 0))
    609 				invarg("Invalid \"numtxqueues\" value\n", *argv);
    610 			addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
    611 				  &numtxqueues, 4);
    612 		} else if (matches(*argv, "numrxqueues") == 0) {
    613 			NEXT_ARG();
    614 			if (numrxqueues != -1)
    615 				duparg("numrxqueues", *argv);
    616 			if (get_integer(&numrxqueues, *argv, 0))
    617 				invarg("Invalid \"numrxqueues\" value\n", *argv);
    618 			addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
    619 				  &numrxqueues, 4);
    620 		} else if (matches(*argv, "addrgenmode") == 0) {
    621 			struct rtattr *afs, *afs6;
    622 			int mode;
    623 
    624 			NEXT_ARG();
    625 			mode = get_addr_gen_mode(*argv);
    626 			if (mode < 0)
    627 				invarg("Invalid address generation mode\n", *argv);
    628 			afs = addattr_nest(&req->n, sizeof(*req), IFLA_AF_SPEC);
    629 			afs6 = addattr_nest(&req->n, sizeof(*req), AF_INET6);
    630 			addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode);
    631 			addattr_nest_end(&req->n, afs6);
    632 			addattr_nest_end(&req->n, afs);
    633 		} else if (matches(*argv, "link-netnsid") == 0) {
    634 			NEXT_ARG();
    635 			if (link_netnsid != -1)
    636 				duparg("link-netnsid", *argv);
    637 			if (get_integer(&link_netnsid, *argv, 0))
    638 				invarg("Invalid \"link-netnsid\" value\n", *argv);
    639 			addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID,
    640 				  link_netnsid);
    641 		} else if (strcmp(*argv, "protodown") == 0) {
    642 			unsigned int proto_down;
    643 
    644 			NEXT_ARG();
    645 			if (strcmp(*argv, "on") == 0)
    646 				proto_down = 1;
    647 			else if (strcmp(*argv, "off") == 0)
    648 				proto_down = 0;
    649 			else
    650 				return on_off("protodown", *argv);
    651 			addattr8(&req->n, sizeof(*req), IFLA_PROTO_DOWN,
    652 				 proto_down);
    653 		} else {
    654 			if (matches(*argv, "help") == 0)
    655 				usage();
    656 
    657 			if (strcmp(*argv, "dev") == 0)
    658 				NEXT_ARG();
    659 			if (*dev)
    660 				duparg2("dev", *argv);
    661 			*dev = *argv;
    662 			dev_index = ll_name_to_index(*dev);
    663 		}
    664 		argc--; argv++;
    665 	}
    666 
    667 	return ret - argc;
    668 }
    669 
    670 static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
    671 {
    672 	int len;
    673 	char *dev = NULL;
    674 	char *name = NULL;
    675 	char *link = NULL;
    676 	char *type = NULL;
    677 	int index = -1;
    678 	int group;
    679 	struct link_util *lu = NULL;
    680 	struct iplink_req req;
    681 	int ret;
    682 
    683 	memset(&req, 0, sizeof(req));
    684 
    685 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    686 	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
    687 	req.n.nlmsg_type = cmd;
    688 	req.i.ifi_family = preferred_family;
    689 
    690 	ret = iplink_parse(argc, argv, &req, &name, &type, &link, &dev, &group, &index);
    691 	if (ret < 0)
    692 		return ret;
    693 
    694 	argc -= ret;
    695 	argv += ret;
    696 
    697 	if (group != -1) {
    698 		if (dev)
    699 			addattr_l(&req.n, sizeof(req), IFLA_GROUP,
    700 					&group, sizeof(group));
    701 		else {
    702 			if (argc) {
    703 				fprintf(stderr, "Garbage instead of arguments "
    704 						"\"%s ...\". Try \"ip link "
    705 						"help\".\n", *argv);
    706 				return -1;
    707 			}
    708 			if (flags & NLM_F_CREATE) {
    709 				fprintf(stderr, "group cannot be used when "
    710 						"creating devices.\n");
    711 				return -1;
    712 			}
    713 
    714 			req.i.ifi_index = 0;
    715 			addattr32(&req.n, sizeof(req), IFLA_GROUP, group);
    716 			if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
    717 				return -2;
    718 			return 0;
    719 		}
    720 	}
    721 
    722 	if (!(flags & NLM_F_CREATE)) {
    723 		if (!dev) {
    724 			fprintf(stderr, "Not enough information: \"dev\" "
    725 					"argument is required.\n");
    726 			exit(-1);
    727 		}
    728 		if (cmd == RTM_NEWLINK && index != -1) {
    729 			fprintf(stderr, "index can be used only when "
    730 					"creating devices.\n");
    731 			exit(-1);
    732 		}
    733 
    734 		req.i.ifi_index = ll_name_to_index(dev);
    735 		if (req.i.ifi_index == 0) {
    736 			fprintf(stderr, "Cannot find device \"%s\"\n", dev);
    737 			return -1;
    738 		}
    739 	} else {
    740 		/* Allow "ip link add dev" and "ip link add name" */
    741 		if (!name)
    742 			name = dev;
    743 
    744 		if (link) {
    745 			int ifindex;
    746 
    747 			ifindex = ll_name_to_index(link);
    748 			if (ifindex == 0) {
    749 				fprintf(stderr, "Cannot find device \"%s\"\n",
    750 					link);
    751 				return -1;
    752 			}
    753 			addattr_l(&req.n, sizeof(req), IFLA_LINK, &ifindex, 4);
    754 		}
    755 
    756 		if (index == -1)
    757 			req.i.ifi_index = 0;
    758 		else
    759 			req.i.ifi_index = index;
    760 	}
    761 
    762 	if (name) {
    763 		len = strlen(name) + 1;
    764 		if (len == 1)
    765 			invarg("\"\" is not a valid device identifier\n", "name");
    766 		if (len > IFNAMSIZ)
    767 			invarg("\"name\" too long\n", name);
    768 		addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len);
    769 	}
    770 
    771 	if (type) {
    772 		struct rtattr *linkinfo;
    773 		char slavebuf[128], *ulinep = strchr(type, '_');
    774 		int iflatype;
    775 
    776 		linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
    777 		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
    778 			 strlen(type));
    779 
    780 		if (ulinep && !strcmp(ulinep, "_slave")) {
    781 			strncpy(slavebuf, type, sizeof(slavebuf));
    782 			slavebuf[sizeof(slavebuf) - 1] = '\0';
    783 			ulinep = strchr(slavebuf, '_');
    784 			/* check in case it was after sizeof(slavebuf) - 1*/
    785 			if (ulinep)
    786 				*ulinep = '\0';
    787 			lu = get_link_slave_kind(slavebuf);
    788 			iflatype = IFLA_INFO_SLAVE_DATA;
    789 		} else {
    790 			lu = get_link_kind(type);
    791 			iflatype = IFLA_INFO_DATA;
    792 		}
    793 		if (lu && argc) {
    794 			struct rtattr *data = addattr_nest(&req.n, sizeof(req), iflatype);
    795 
    796 			if (lu->parse_opt &&
    797 			    lu->parse_opt(lu, argc, argv, &req.n))
    798 				return -1;
    799 
    800 			addattr_nest_end(&req.n, data);
    801 		} else if (argc) {
    802 			if (matches(*argv, "help") == 0)
    803 				usage();
    804 			fprintf(stderr, "Garbage instead of arguments \"%s ...\". "
    805 					"Try \"ip link help\".\n", *argv);
    806 			return -1;
    807 		}
    808 		addattr_nest_end(&req.n, linkinfo);
    809 	} else if (flags & NLM_F_CREATE) {
    810 		fprintf(stderr, "Not enough information: \"type\" argument "
    811 				"is required\n");
    812 		return -1;
    813 	}
    814 
    815 	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
    816 		return -2;
    817 
    818 	return 0;
    819 }
    820 
    821 int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
    822 {
    823 	int len;
    824 	struct iplink_req req;
    825 	struct {
    826 		struct nlmsghdr n;
    827 		char buf[16384];
    828 	} answer;
    829 
    830 	memset(&req, 0, sizeof(req));
    831 
    832 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    833 	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
    834 	req.n.nlmsg_type = RTM_GETLINK;
    835 	req.i.ifi_family = preferred_family;
    836 
    837 	if (name) {
    838 		len = strlen(name) + 1;
    839 		if (len == 1)
    840 			invarg("\"\" is not a valid device identifier\n",
    841 				   "name");
    842 		if (len > IFNAMSIZ)
    843 			invarg("\"name\" too long\n", name);
    844 		addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len);
    845 	}
    846 	addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
    847 
    848 	if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
    849 		return -2;
    850 
    851 	if (brief)
    852 		print_linkinfo_brief(NULL, &answer.n, stdout);
    853 	else
    854 		print_linkinfo(NULL, &answer.n, stdout);
    855 
    856 	return 0;
    857 }
    858 
    859 #if IPLINK_IOCTL_COMPAT
    860 static int get_ctl_fd(void)
    861 {
    862 	int s_errno;
    863 	int fd;
    864 
    865 	fd = socket(PF_INET, SOCK_DGRAM, 0);
    866 	if (fd >= 0)
    867 		return fd;
    868 	s_errno = errno;
    869 	fd = socket(PF_PACKET, SOCK_DGRAM, 0);
    870 	if (fd >= 0)
    871 		return fd;
    872 	fd = socket(PF_INET6, SOCK_DGRAM, 0);
    873 	if (fd >= 0)
    874 		return fd;
    875 	errno = s_errno;
    876 	perror("Cannot create control socket");
    877 	return -1;
    878 }
    879 
    880 static int do_chflags(const char *dev, __u32 flags, __u32 mask)
    881 {
    882 	struct ifreq ifr;
    883 	int fd;
    884 	int err;
    885 
    886 	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    887 	fd = get_ctl_fd();
    888 	if (fd < 0)
    889 		return -1;
    890 	err = ioctl(fd, SIOCGIFFLAGS, &ifr);
    891 	if (err) {
    892 		perror("SIOCGIFFLAGS");
    893 		close(fd);
    894 		return -1;
    895 	}
    896 	if ((ifr.ifr_flags^flags)&mask) {
    897 		ifr.ifr_flags &= ~mask;
    898 		ifr.ifr_flags |= mask&flags;
    899 		err = ioctl(fd, SIOCSIFFLAGS, &ifr);
    900 		if (err)
    901 			perror("SIOCSIFFLAGS");
    902 	}
    903 	close(fd);
    904 	return err;
    905 }
    906 
    907 static int do_changename(const char *dev, const char *newdev)
    908 {
    909 	struct ifreq ifr;
    910 	int fd;
    911 	int err;
    912 
    913 	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    914 	strncpy(ifr.ifr_newname, newdev, IFNAMSIZ);
    915 	fd = get_ctl_fd();
    916 	if (fd < 0)
    917 		return -1;
    918 	err = ioctl(fd, SIOCSIFNAME, &ifr);
    919 	if (err) {
    920 		perror("SIOCSIFNAME");
    921 		close(fd);
    922 		return -1;
    923 	}
    924 	close(fd);
    925 	return err;
    926 }
    927 
    928 static int set_qlen(const char *dev, int qlen)
    929 {
    930 	struct ifreq ifr;
    931 	int s;
    932 
    933 	s = get_ctl_fd();
    934 	if (s < 0)
    935 		return -1;
    936 
    937 	memset(&ifr, 0, sizeof(ifr));
    938 	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    939 	ifr.ifr_qlen = qlen;
    940 	if (ioctl(s, SIOCSIFTXQLEN, &ifr) < 0) {
    941 		perror("SIOCSIFXQLEN");
    942 		close(s);
    943 		return -1;
    944 	}
    945 	close(s);
    946 
    947 	return 0;
    948 }
    949 
    950 static int set_mtu(const char *dev, int mtu)
    951 {
    952 	struct ifreq ifr;
    953 	int s;
    954 
    955 	s = get_ctl_fd();
    956 	if (s < 0)
    957 		return -1;
    958 
    959 	memset(&ifr, 0, sizeof(ifr));
    960 	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    961 	ifr.ifr_mtu = mtu;
    962 	if (ioctl(s, SIOCSIFMTU, &ifr) < 0) {
    963 		perror("SIOCSIFMTU");
    964 		close(s);
    965 		return -1;
    966 	}
    967 	close(s);
    968 
    969 	return 0;
    970 }
    971 
    972 static int get_address(const char *dev, int *htype)
    973 {
    974 	struct ifreq ifr;
    975 	struct sockaddr_ll me;
    976 	socklen_t alen;
    977 	int s;
    978 
    979 	s = socket(PF_PACKET, SOCK_DGRAM, 0);
    980 	if (s < 0) {
    981 		perror("socket(PF_PACKET)");
    982 		return -1;
    983 	}
    984 
    985 	memset(&ifr, 0, sizeof(ifr));
    986 	strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    987 	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
    988 		perror("SIOCGIFINDEX");
    989 		close(s);
    990 		return -1;
    991 	}
    992 
    993 	memset(&me, 0, sizeof(me));
    994 	me.sll_family = AF_PACKET;
    995 	me.sll_ifindex = ifr.ifr_ifindex;
    996 	me.sll_protocol = htons(ETH_P_LOOP);
    997 	if (bind(s, (struct sockaddr *)&me, sizeof(me)) == -1) {
    998 		perror("bind");
    999 		close(s);
   1000 		return -1;
   1001 	}
   1002 
   1003 	alen = sizeof(me);
   1004 	if (getsockname(s, (struct sockaddr *)&me, &alen) == -1) {
   1005 		perror("getsockname");
   1006 		close(s);
   1007 		return -1;
   1008 	}
   1009 	close(s);
   1010 	*htype = me.sll_hatype;
   1011 	return me.sll_halen;
   1012 }
   1013 
   1014 static int parse_address(const char *dev, int hatype, int halen,
   1015 		char *lla, struct ifreq *ifr)
   1016 {
   1017 	int alen;
   1018 
   1019 	memset(ifr, 0, sizeof(*ifr));
   1020 	strncpy(ifr->ifr_name, dev, IFNAMSIZ);
   1021 	ifr->ifr_hwaddr.sa_family = hatype;
   1022 	alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla);
   1023 	if (alen < 0)
   1024 		return -1;
   1025 	if (alen != halen) {
   1026 		fprintf(stderr, "Wrong address (%s) length: expected %d bytes\n", lla, halen);
   1027 		return -1;
   1028 	}
   1029 	return 0;
   1030 }
   1031 
   1032 static int set_address(struct ifreq *ifr, int brd)
   1033 {
   1034 	int s;
   1035 
   1036 	s = get_ctl_fd();
   1037 	if (s < 0)
   1038 		return -1;
   1039 	if (ioctl(s, brd?SIOCSIFHWBROADCAST:SIOCSIFHWADDR, ifr) < 0) {
   1040 		perror(brd?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
   1041 		close(s);
   1042 		return -1;
   1043 	}
   1044 	close(s);
   1045 	return 0;
   1046 }
   1047 
   1048 static int do_set(int argc, char **argv)
   1049 {
   1050 	char *dev = NULL;
   1051 	__u32 mask = 0;
   1052 	__u32 flags = 0;
   1053 	int qlen = -1;
   1054 	int mtu = -1;
   1055 	char *newaddr = NULL;
   1056 	char *newbrd = NULL;
   1057 	struct ifreq ifr0, ifr1;
   1058 	char *newname = NULL;
   1059 	int htype, halen;
   1060 
   1061 	while (argc > 0) {
   1062 		if (strcmp(*argv, "up") == 0) {
   1063 			mask |= IFF_UP;
   1064 			flags |= IFF_UP;
   1065 		} else if (strcmp(*argv, "down") == 0) {
   1066 			mask |= IFF_UP;
   1067 			flags &= ~IFF_UP;
   1068 		} else if (strcmp(*argv, "name") == 0) {
   1069 			NEXT_ARG();
   1070 			newname = *argv;
   1071 		} else if (matches(*argv, "address") == 0) {
   1072 			NEXT_ARG();
   1073 			newaddr = *argv;
   1074 		} else if (matches(*argv, "broadcast") == 0 ||
   1075 			   strcmp(*argv, "brd") == 0) {
   1076 			NEXT_ARG();
   1077 			newbrd = *argv;
   1078 		} else if (matches(*argv, "txqueuelen") == 0 ||
   1079 			   strcmp(*argv, "qlen") == 0 ||
   1080 			   matches(*argv, "txqlen") == 0) {
   1081 			NEXT_ARG();
   1082 			if (qlen != -1)
   1083 				duparg("txqueuelen", *argv);
   1084 			if (get_integer(&qlen,  *argv, 0))
   1085 				invarg("Invalid \"txqueuelen\" value\n", *argv);
   1086 		} else if (strcmp(*argv, "mtu") == 0) {
   1087 			NEXT_ARG();
   1088 			if (mtu != -1)
   1089 				duparg("mtu", *argv);
   1090 			if (get_integer(&mtu, *argv, 0))
   1091 				invarg("Invalid \"mtu\" value\n", *argv);
   1092 		} else if (strcmp(*argv, "multicast") == 0) {
   1093 			NEXT_ARG();
   1094 			mask |= IFF_MULTICAST;
   1095 
   1096 			if (strcmp(*argv, "on") == 0)
   1097 				flags |= IFF_MULTICAST;
   1098 			else if (strcmp(*argv, "off") == 0)
   1099 				flags &= ~IFF_MULTICAST;
   1100 			else
   1101 				return on_off("multicast", *argv);
   1102 		} else if (strcmp(*argv, "allmulticast") == 0) {
   1103 			NEXT_ARG();
   1104 			mask |= IFF_ALLMULTI;
   1105 
   1106 			if (strcmp(*argv, "on") == 0)
   1107 				flags |= IFF_ALLMULTI;
   1108 			else if (strcmp(*argv, "off") == 0)
   1109 				flags &= ~IFF_ALLMULTI;
   1110 			else
   1111 				return on_off("allmulticast", *argv);
   1112 		} else if (strcmp(*argv, "promisc") == 0) {
   1113 			NEXT_ARG();
   1114 			mask |= IFF_PROMISC;
   1115 
   1116 			if (strcmp(*argv, "on") == 0)
   1117 				flags |= IFF_PROMISC;
   1118 			else if (strcmp(*argv, "off") == 0)
   1119 				flags &= ~IFF_PROMISC;
   1120 			else
   1121 				return on_off("promisc", *argv);
   1122 		} else if (strcmp(*argv, "trailers") == 0) {
   1123 			NEXT_ARG();
   1124 			mask |= IFF_NOTRAILERS;
   1125 
   1126 			if (strcmp(*argv, "off") == 0)
   1127 				flags |= IFF_NOTRAILERS;
   1128 			else if (strcmp(*argv, "on") == 0)
   1129 				flags &= ~IFF_NOTRAILERS;
   1130 			else
   1131 				return on_off("trailers", *argv);
   1132 		} else if (strcmp(*argv, "arp") == 0) {
   1133 			NEXT_ARG();
   1134 			mask |= IFF_NOARP;
   1135 
   1136 			if (strcmp(*argv, "on") == 0)
   1137 				flags &= ~IFF_NOARP;
   1138 			else if (strcmp(*argv, "off") == 0)
   1139 				flags |= IFF_NOARP;
   1140 			else
   1141 				return on_off("arp", *argv);
   1142 		} else if (matches(*argv, "dynamic") == 0) {
   1143 			NEXT_ARG();
   1144 			mask |= IFF_DYNAMIC;
   1145 
   1146 			if (strcmp(*argv, "on") == 0)
   1147 				flags |= IFF_DYNAMIC;
   1148 			else if (strcmp(*argv, "off") == 0)
   1149 				flags &= ~IFF_DYNAMIC;
   1150 			else
   1151 				return on_off("dynamic", *argv);
   1152 		} else {
   1153 			if (strcmp(*argv, "dev") == 0)
   1154 				NEXT_ARG();
   1155 			else if (matches(*argv, "help") == 0)
   1156 				usage();
   1157 
   1158 			if (dev)
   1159 				duparg2("dev", *argv);
   1160 			dev = *argv;
   1161 		}
   1162 		argc--; argv++;
   1163 	}
   1164 
   1165 	if (!dev) {
   1166 		fprintf(stderr, "Not enough of information: \"dev\" argument is required.\n");
   1167 		exit(-1);
   1168 	}
   1169 
   1170 	if (newaddr || newbrd) {
   1171 		halen = get_address(dev, &htype);
   1172 		if (halen < 0)
   1173 			return -1;
   1174 		if (newaddr) {
   1175 			if (parse_address(dev, htype, halen, newaddr, &ifr0) < 0)
   1176 				return -1;
   1177 		}
   1178 		if (newbrd) {
   1179 			if (parse_address(dev, htype, halen, newbrd, &ifr1) < 0)
   1180 				return -1;
   1181 		}
   1182 	}
   1183 
   1184 	if (newname && strcmp(dev, newname)) {
   1185 		if (strlen(newname) == 0)
   1186 			invarg("\"\" is not a valid device identifier\n", "name");
   1187 		if (do_changename(dev, newname) < 0)
   1188 			return -1;
   1189 		dev = newname;
   1190 	}
   1191 	if (qlen != -1) {
   1192 		if (set_qlen(dev, qlen) < 0)
   1193 			return -1;
   1194 	}
   1195 	if (mtu != -1) {
   1196 		if (set_mtu(dev, mtu) < 0)
   1197 			return -1;
   1198 	}
   1199 	if (newaddr || newbrd) {
   1200 		if (newbrd) {
   1201 			if (set_address(&ifr1, 1) < 0)
   1202 				return -1;
   1203 		}
   1204 		if (newaddr) {
   1205 			if (set_address(&ifr0, 0) < 0)
   1206 				return -1;
   1207 		}
   1208 	}
   1209 	if (mask)
   1210 		return do_chflags(dev, flags, mask);
   1211 	return 0;
   1212 }
   1213 #endif /* IPLINK_IOCTL_COMPAT */
   1214 
   1215 static void do_help(int argc, char **argv)
   1216 {
   1217 	struct link_util *lu = NULL;
   1218 
   1219 	if (argc <= 0) {
   1220 		usage();
   1221 		return;
   1222 	}
   1223 
   1224 	lu = get_link_kind(*argv);
   1225 	if (lu && lu->print_help)
   1226 		lu->print_help(lu, argc-1, argv+1, stdout);
   1227 	else
   1228 		usage();
   1229 }
   1230 
   1231 int do_iplink(int argc, char **argv)
   1232 {
   1233 	if (argc < 1)
   1234 		return ipaddr_list_link(0, NULL);
   1235 
   1236 	if (iplink_have_newlink()) {
   1237 		if (matches(*argv, "add") == 0)
   1238 			return iplink_modify(RTM_NEWLINK,
   1239 					     NLM_F_CREATE|NLM_F_EXCL,
   1240 					     argc-1, argv+1);
   1241 		if (matches(*argv, "set") == 0 ||
   1242 		    matches(*argv, "change") == 0)
   1243 			return iplink_modify(RTM_NEWLINK, 0,
   1244 					     argc-1, argv+1);
   1245 		if (matches(*argv, "replace") == 0)
   1246 			return iplink_modify(RTM_NEWLINK,
   1247 					     NLM_F_CREATE|NLM_F_REPLACE,
   1248 					     argc-1, argv+1);
   1249 		if (matches(*argv, "delete") == 0)
   1250 			return iplink_modify(RTM_DELLINK, 0,
   1251 					     argc-1, argv+1);
   1252 	} else {
   1253 #if IPLINK_IOCTL_COMPAT
   1254 		if (matches(*argv, "set") == 0)
   1255 			return do_set(argc-1, argv+1);
   1256 #endif
   1257 	}
   1258 
   1259 	if (matches(*argv, "show") == 0 ||
   1260 	    matches(*argv, "lst") == 0 ||
   1261 	    matches(*argv, "list") == 0)
   1262 		return ipaddr_list_link(argc-1, argv+1);
   1263 
   1264 	if (matches(*argv, "help") == 0) {
   1265 		do_help(argc-1, argv+1);
   1266 		return 0;
   1267 	}
   1268 
   1269 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip link help\".\n",
   1270 		*argv);
   1271 	exit(-1);
   1272 }
   1273