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