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