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