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