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