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.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
20 #include <sys/socket.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>
28 #include <sys/ioctl.h>
29 #include <linux/sockios.h>
31 #include <linux/mpls.h>
35 #include "ip_common.h"
37 #include "namespace.h"
39 #define IPLINK_IOCTL_COMPAT 1
41 #define LIBDIR "/usr/lib"
44 static void usage(void) __attribute__((noreturn
));
45 static int iplink_have_newlink(void);
47 void iplink_usage(void)
49 if (iplink_have_newlink()) {
51 "Usage: ip link add [link DEV] [ name ] NAME\n"
52 " [ txqueuelen PACKETS ]\n"
53 " [ address LLADDR ]\n"
54 " [ broadcast LLADDR ]\n"
55 " [ mtu MTU ] [index IDX ]\n"
56 " [ numtxqueues QUEUE_COUNT ]\n"
57 " [ numrxqueues QUEUE_COUNT ]\n"
58 " type TYPE [ ARGS ]\n"
60 " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"
62 " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"
63 " [ { up | down } ]\n"
64 " [ type TYPE ARGS ]\n");
67 "Usage: ip link set DEVICE [ { up | down } ]\n");
70 " [ arp { on | off } ]\n"
71 " [ dynamic { on | off } ]\n"
72 " [ multicast { on | off } ]\n"
73 " [ allmulticast { on | off } ]\n"
74 " [ promisc { on | off } ]\n"
75 " [ trailers { on | off } ]\n"
76 " [ carrier { on | off } ]\n"
77 " [ txqueuelen PACKETS ]\n"
79 " [ address LLADDR ]\n"
80 " [ broadcast LLADDR ]\n"
82 " [ netns { PID | NAME } ]\n"
83 " [ link-netnsid ID ]\n"
85 " [ vf NUM [ mac LLADDR ]\n"
86 " [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]\n"
88 " [ max_tx_rate TXRATE ]\n"
89 " [ min_tx_rate TXRATE ]\n"
90 " [ spoofchk { on | off} ]\n"
91 " [ query_rss { on | off} ]\n"
92 " [ state { auto | enable | disable} ] ]\n"
93 " [ trust { on | off} ] ]\n"
95 " object FILE [ section NAME ] [ verbose ] |\n"
97 " [ master DEVICE ][ vrf NAME ]\n"
99 " [ addrgenmode { eui64 | none | stable_secret | random } ]\n"
100 " [ protodown { on | off } ]\n"
102 " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n");
104 fprintf(stderr
, "\n ip link xstats type TYPE [ ARGS ]\n");
105 fprintf(stderr
, "\n ip link afstats [ dev DEVICE ]\n");
107 if (iplink_have_newlink()) {
110 " ip link help [ TYPE ]\n"
112 "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"
113 " bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
114 " gre | gretap | ip6gre | ip6gretap | vti | nlmon | team_slave |\n"
115 " bond_slave | ipvlan | geneve | bridge_slave | vrf | macsec }\n");
120 static void usage(void)
125 static int on_off(const char *msg
, const char *realval
)
128 "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
133 static void *BODY
; /* cached dlopen(NULL) handle */
134 static struct link_util
*linkutil_list
;
136 struct link_util
*get_link_kind(const char *id
)
142 for (l
= linkutil_list
; l
; l
= l
->next
)
143 if (strcmp(l
->id
, id
) == 0)
146 snprintf(buf
, sizeof(buf
), LIBDIR
"/ip/link_%s.so", id
);
147 dlh
= dlopen(buf
, RTLD_LAZY
);
149 /* look in current binary, only open once */
152 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
158 snprintf(buf
, sizeof(buf
), "%s_link_util", id
);
163 l
->next
= linkutil_list
;
168 static int get_link_mode(const char *mode
)
170 if (strcasecmp(mode
, "default") == 0)
171 return IF_LINK_MODE_DEFAULT
;
172 if (strcasecmp(mode
, "dormant") == 0)
173 return IF_LINK_MODE_DORMANT
;
177 static int get_addr_gen_mode(const char *mode
)
179 if (strcasecmp(mode
, "eui64") == 0)
180 return IN6_ADDR_GEN_MODE_EUI64
;
181 if (strcasecmp(mode
, "none") == 0)
182 return IN6_ADDR_GEN_MODE_NONE
;
183 if (strcasecmp(mode
, "stable_secret") == 0)
184 return IN6_ADDR_GEN_MODE_STABLE_PRIVACY
;
185 if (strcasecmp(mode
, "random") == 0)
186 return IN6_ADDR_GEN_MODE_RANDOM
;
190 #if IPLINK_IOCTL_COMPAT
191 static int have_rtnl_newlink
= -1;
193 static int accept_msg(const struct sockaddr_nl
*who
,
194 struct rtnl_ctrl_data
*ctrl
,
195 struct nlmsghdr
*n
, void *arg
)
197 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(n
);
199 if (n
->nlmsg_type
== NLMSG_ERROR
&&
200 (err
->error
== -EOPNOTSUPP
|| err
->error
== -EINVAL
))
201 have_rtnl_newlink
= 0;
203 have_rtnl_newlink
= 1;
207 static int iplink_have_newlink(void)
214 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
215 .n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
,
216 .n
.nlmsg_type
= RTM_NEWLINK
,
217 .i
.ifi_family
= AF_UNSPEC
,
220 if (have_rtnl_newlink
< 0) {
221 if (rtnl_send(&rth
, &req
.n
, req
.n
.nlmsg_len
) < 0) {
222 perror("request send failed");
225 rtnl_listen(&rth
, accept_msg
, NULL
);
227 return have_rtnl_newlink
;
229 #else /* IPLINK_IOCTL_COMPAT */
230 static int iplink_have_newlink(void)
234 #endif /* ! IPLINK_IOCTL_COMPAT */
236 static int nl_get_ll_addr_len(unsigned int dev_index
)
239 struct iplink_req req
= {
241 .nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
242 .nlmsg_type
= RTM_GETLINK
,
243 .nlmsg_flags
= NLM_F_REQUEST
246 .ifi_family
= preferred_family
,
247 .ifi_index
= dev_index
,
250 struct rtattr
*tb
[IFLA_MAX
+1];
252 if (rtnl_talk(&rth
, &req
.n
, &req
.n
, sizeof(req
)) < 0)
255 len
= req
.n
.nlmsg_len
- NLMSG_LENGTH(sizeof(req
.i
));
259 parse_rtattr_flags(tb
, IFLA_MAX
, IFLA_RTA(&req
.i
), len
, NLA_F_NESTED
);
260 if (!tb
[IFLA_ADDRESS
])
263 return RTA_PAYLOAD(tb
[IFLA_ADDRESS
]);
266 static void iplink_parse_vf_vlan_info(int vf
, int *argcp
, char ***argvp
,
267 struct ifla_vf_vlan_info
*ivvip
)
270 char **argv
= *argvp
;
273 if (get_unsigned(&ivvip
->vlan
, *argv
, 0))
274 invarg("Invalid \"vlan\" value\n", *argv
);
278 ivvip
->vlan_proto
= htons(ETH_P_8021Q
);
281 if (matches(*argv
, "qos") == 0) {
283 if (get_unsigned(&ivvip
->qos
, *argv
, 0))
284 invarg("Invalid \"qos\" value\n", *argv
);
292 if (matches(*argv
, "proto") == 0) {
294 if (ll_proto_a2n(&ivvip
->vlan_proto
, *argv
))
295 invarg("protocol is invalid\n", *argv
);
296 if (ivvip
->vlan_proto
!= htons(ETH_P_8021AD
) &&
297 ivvip
->vlan_proto
!= htons(ETH_P_8021Q
)) {
300 char msg
[64 + sizeof(b1
) + sizeof(b2
)];
303 "Invalid \"vlan protocol\" value - supported %s, %s\n",
304 ll_proto_n2a(htons(ETH_P_8021Q
),
306 ll_proto_n2a(htons(ETH_P_8021AD
),
320 static int iplink_parse_vf(int vf
, int *argcp
, char ***argvp
,
321 struct iplink_req
*req
, int dev_index
)
323 char new_rate_api
= 0, count
= 0, override_legacy_rate
= 0;
324 struct ifla_vf_rate tivt
;
325 int len
, argc
= *argcp
;
326 char **argv
= *argvp
;
327 struct rtattr
*vfinfo
;
329 tivt
.min_tx_rate
= -1;
330 tivt
.max_tx_rate
= -1;
332 vfinfo
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_VF_INFO
);
334 while (NEXT_ARG_OK()) {
337 if (!matches(*argv
, "max_tx_rate")) {
340 /* override legacy rate */
341 override_legacy_rate
= 1;
342 } else if (!matches(*argv
, "min_tx_rate")) {
353 while (NEXT_ARG_OK()) {
355 if (matches(*argv
, "mac") == 0) {
356 struct ifla_vf_mac ivm
= { 0 };
357 int halen
= nl_get_ll_addr_len(dev_index
);
361 len
= ll_addr_a2n((char *)ivm
.mac
, 32, *argv
);
364 if (halen
> 0 && len
!= halen
) {
366 "Invalid address length %d - must be %d bytes\n",
370 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_MAC
,
372 } else if (matches(*argv
, "vlan") == 0) {
373 struct ifla_vf_vlan_info ivvi
;
375 iplink_parse_vf_vlan_info(vf
, &argc
, &argv
, &ivvi
);
376 /* support the old interface in case of older kernel*/
377 if (ivvi
.vlan_proto
== htons(ETH_P_8021Q
)) {
378 struct ifla_vf_vlan ivv
;
381 ivv
.vlan
= ivvi
.vlan
;
383 addattr_l(&req
->n
, sizeof(*req
),
384 IFLA_VF_VLAN
, &ivv
, sizeof(ivv
));
386 struct rtattr
*vfvlanlist
;
388 vfvlanlist
= addattr_nest(&req
->n
, sizeof(*req
),
390 addattr_l(&req
->n
, sizeof(*req
),
391 IFLA_VF_VLAN_INFO
, &ivvi
,
394 while (NEXT_ARG_OK()) {
396 if (matches(*argv
, "vlan") != 0) {
400 iplink_parse_vf_vlan_info(vf
, &argc
,
402 addattr_l(&req
->n
, sizeof(*req
),
403 IFLA_VF_VLAN_INFO
, &ivvi
,
406 addattr_nest_end(&req
->n
, vfvlanlist
);
408 } else if (matches(*argv
, "rate") == 0) {
409 struct ifla_vf_tx_rate ivt
;
412 if (get_unsigned(&ivt
.rate
, *argv
, 0))
413 invarg("Invalid \"rate\" value\n", *argv
);
417 addattr_l(&req
->n
, sizeof(*req
),
418 IFLA_VF_TX_RATE
, &ivt
, sizeof(ivt
));
419 else if (!override_legacy_rate
)
420 tivt
.max_tx_rate
= ivt
.rate
;
422 } else if (matches(*argv
, "max_tx_rate") == 0) {
424 if (get_unsigned(&tivt
.max_tx_rate
, *argv
, 0))
425 invarg("Invalid \"max tx rate\" value\n",
429 } else if (matches(*argv
, "min_tx_rate") == 0) {
431 if (get_unsigned(&tivt
.min_tx_rate
, *argv
, 0))
432 invarg("Invalid \"min tx rate\" value\n",
436 } else if (matches(*argv
, "spoofchk") == 0) {
437 struct ifla_vf_spoofchk ivs
;
440 if (matches(*argv
, "on") == 0)
442 else if (matches(*argv
, "off") == 0)
445 return on_off("spoofchk", *argv
);
447 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_SPOOFCHK
,
450 } else if (matches(*argv
, "query_rss") == 0) {
451 struct ifla_vf_rss_query_en ivs
;
454 if (matches(*argv
, "on") == 0)
456 else if (matches(*argv
, "off") == 0)
459 return on_off("query_rss", *argv
);
461 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RSS_QUERY_EN
,
464 } else if (matches(*argv
, "trust") == 0) {
465 struct ifla_vf_trust ivt
;
468 if (matches(*argv
, "on") == 0)
470 else if (matches(*argv
, "off") == 0)
473 invarg("Invalid \"trust\" value\n", *argv
);
475 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_TRUST
,
478 } else if (matches(*argv
, "state") == 0) {
479 struct ifla_vf_link_state ivl
;
482 if (matches(*argv
, "auto") == 0)
483 ivl
.link_state
= IFLA_VF_LINK_STATE_AUTO
;
484 else if (matches(*argv
, "enable") == 0)
485 ivl
.link_state
= IFLA_VF_LINK_STATE_ENABLE
;
486 else if (matches(*argv
, "disable") == 0)
487 ivl
.link_state
= IFLA_VF_LINK_STATE_DISABLE
;
489 invarg("Invalid \"state\" value\n", *argv
);
491 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_LINK_STATE
,
493 } else if (matches(*argv
, "node_guid") == 0) {
494 struct ifla_vf_guid ivg
;
498 if (get_guid(&ivg
.guid
, *argv
)) {
499 invarg("Invalid GUID format\n", *argv
);
502 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_NODE_GUID
,
504 } else if (matches(*argv
, "port_guid") == 0) {
505 struct ifla_vf_guid ivg
;
509 if (get_guid(&ivg
.guid
, *argv
)) {
510 invarg("Invalid GUID format\n", *argv
);
513 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_PORT_GUID
,
525 if (tivt
.min_tx_rate
== -1 || tivt
.max_tx_rate
== -1) {
526 ipaddr_get_vf_rate(tivt
.vf
, &tmin
, &tmax
, dev_index
);
527 if (tivt
.min_tx_rate
== -1)
528 tivt
.min_tx_rate
= tmin
;
529 if (tivt
.max_tx_rate
== -1)
530 tivt
.max_tx_rate
= tmax
;
532 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RATE
, &tivt
,
537 incomplete_command();
539 addattr_nest_end(&req
->n
, vfinfo
);
546 int iplink_parse(int argc
, char **argv
, struct iplink_req
*req
,
547 char **name
, char **type
, char **link
, char **dev
,
548 int *group
, int *index
)
556 int numtxqueues
= -1;
557 int numrxqueues
= -1;
559 int link_netnsid
= -1;
566 if (strcmp(*argv
, "up") == 0) {
567 req
->i
.ifi_change
|= IFF_UP
;
568 req
->i
.ifi_flags
|= IFF_UP
;
569 } else if (strcmp(*argv
, "down") == 0) {
570 req
->i
.ifi_change
|= IFF_UP
;
571 req
->i
.ifi_flags
&= ~IFF_UP
;
572 } else if (strcmp(*argv
, "name") == 0) {
575 } else if (strcmp(*argv
, "index") == 0) {
577 *index
= atoi(*argv
);
579 invarg("Invalid \"index\" value", *argv
);
580 } else if (matches(*argv
, "link") == 0) {
583 } else if (matches(*argv
, "address") == 0) {
585 addr_len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
588 addattr_l(&req
->n
, sizeof(*req
),
589 IFLA_ADDRESS
, abuf
, addr_len
);
590 } else if (matches(*argv
, "broadcast") == 0 ||
591 strcmp(*argv
, "brd") == 0) {
593 len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
596 addattr_l(&req
->n
, sizeof(*req
),
597 IFLA_BROADCAST
, abuf
, len
);
598 } else if (matches(*argv
, "txqueuelen") == 0 ||
599 strcmp(*argv
, "qlen") == 0 ||
600 matches(*argv
, "txqlen") == 0) {
603 duparg("txqueuelen", *argv
);
604 if (get_integer(&qlen
, *argv
, 0))
605 invarg("Invalid \"txqueuelen\" value\n", *argv
);
606 addattr_l(&req
->n
, sizeof(*req
),
607 IFLA_TXQLEN
, &qlen
, 4);
608 } else if (strcmp(*argv
, "mtu") == 0) {
611 duparg("mtu", *argv
);
612 if (get_integer(&mtu
, *argv
, 0))
613 invarg("Invalid \"mtu\" value\n", *argv
);
614 addattr_l(&req
->n
, sizeof(*req
), IFLA_MTU
, &mtu
, 4);
615 } else if (strcmp(*argv
, "xdpgeneric") == 0 ||
616 strcmp(*argv
, "xdp") == 0) {
617 bool generic
= strcmp(*argv
, "xdpgeneric") == 0;
620 if (xdp_parse(&argc
, &argv
, req
, generic
))
622 } else if (strcmp(*argv
, "netns") == 0) {
625 duparg("netns", *argv
);
626 netns
= netns_get_fd(*argv
);
628 addattr_l(&req
->n
, sizeof(*req
), IFLA_NET_NS_FD
,
630 else if (get_integer(&netns
, *argv
, 0) == 0)
631 addattr_l(&req
->n
, sizeof(*req
),
632 IFLA_NET_NS_PID
, &netns
, 4);
634 invarg("Invalid \"netns\" value\n", *argv
);
635 } else if (strcmp(*argv
, "multicast") == 0) {
637 req
->i
.ifi_change
|= IFF_MULTICAST
;
639 if (strcmp(*argv
, "on") == 0)
640 req
->i
.ifi_flags
|= IFF_MULTICAST
;
641 else if (strcmp(*argv
, "off") == 0)
642 req
->i
.ifi_flags
&= ~IFF_MULTICAST
;
644 return on_off("multicast", *argv
);
645 } else if (strcmp(*argv
, "allmulticast") == 0) {
647 req
->i
.ifi_change
|= IFF_ALLMULTI
;
649 if (strcmp(*argv
, "on") == 0)
650 req
->i
.ifi_flags
|= IFF_ALLMULTI
;
651 else if (strcmp(*argv
, "off") == 0)
652 req
->i
.ifi_flags
&= ~IFF_ALLMULTI
;
654 return on_off("allmulticast", *argv
);
655 } else if (strcmp(*argv
, "promisc") == 0) {
657 req
->i
.ifi_change
|= IFF_PROMISC
;
659 if (strcmp(*argv
, "on") == 0)
660 req
->i
.ifi_flags
|= IFF_PROMISC
;
661 else if (strcmp(*argv
, "off") == 0)
662 req
->i
.ifi_flags
&= ~IFF_PROMISC
;
664 return on_off("promisc", *argv
);
665 } else if (strcmp(*argv
, "trailers") == 0) {
667 req
->i
.ifi_change
|= IFF_NOTRAILERS
;
669 if (strcmp(*argv
, "off") == 0)
670 req
->i
.ifi_flags
|= IFF_NOTRAILERS
;
671 else if (strcmp(*argv
, "on") == 0)
672 req
->i
.ifi_flags
&= ~IFF_NOTRAILERS
;
674 return on_off("trailers", *argv
);
675 } else if (strcmp(*argv
, "arp") == 0) {
677 req
->i
.ifi_change
|= IFF_NOARP
;
679 if (strcmp(*argv
, "on") == 0)
680 req
->i
.ifi_flags
&= ~IFF_NOARP
;
681 else if (strcmp(*argv
, "off") == 0)
682 req
->i
.ifi_flags
|= IFF_NOARP
;
684 return on_off("arp", *argv
);
685 } else if (strcmp(*argv
, "carrier") == 0) {
689 if (strcmp(*argv
, "on") == 0)
691 else if (strcmp(*argv
, "off") == 0)
694 return on_off("carrier", *argv
);
696 addattr8(&req
->n
, sizeof(*req
), IFLA_CARRIER
, carrier
);
697 } else if (strcmp(*argv
, "vf") == 0) {
698 struct rtattr
*vflist
;
701 if (get_integer(&vf
, *argv
, 0))
702 invarg("Invalid \"vf\" value\n", *argv
);
704 vflist
= addattr_nest(&req
->n
, sizeof(*req
),
709 len
= iplink_parse_vf(vf
, &argc
, &argv
, req
, dev_index
);
712 addattr_nest_end(&req
->n
, vflist
);
713 } else if (matches(*argv
, "master") == 0) {
717 ifindex
= ll_name_to_index(*argv
);
719 invarg("Device does not exist\n", *argv
);
720 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
722 } else if (strcmp(*argv
, "vrf") == 0) {
726 ifindex
= ll_name_to_index(*argv
);
728 invarg("Not a valid VRF name\n", *argv
);
729 if (!name_is_vrf(*argv
))
730 invarg("Not a valid VRF name\n", *argv
);
731 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
732 &ifindex
, sizeof(ifindex
));
733 } else if (matches(*argv
, "nomaster") == 0) {
736 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
738 } else if (matches(*argv
, "dynamic") == 0) {
740 req
->i
.ifi_change
|= IFF_DYNAMIC
;
742 if (strcmp(*argv
, "on") == 0)
743 req
->i
.ifi_flags
|= IFF_DYNAMIC
;
744 else if (strcmp(*argv
, "off") == 0)
745 req
->i
.ifi_flags
&= ~IFF_DYNAMIC
;
747 return on_off("dynamic", *argv
);
748 } else if (matches(*argv
, "type") == 0) {
753 } else if (matches(*argv
, "alias") == 0) {
755 addattr_l(&req
->n
, sizeof(*req
), IFLA_IFALIAS
,
756 *argv
, strlen(*argv
));
759 } else if (strcmp(*argv
, "group") == 0) {
762 duparg("group", *argv
);
763 if (rtnl_group_a2n(group
, *argv
))
764 invarg("Invalid \"group\" value\n", *argv
);
765 } else if (strcmp(*argv
, "mode") == 0) {
769 mode
= get_link_mode(*argv
);
771 invarg("Invalid link mode\n", *argv
);
772 addattr8(&req
->n
, sizeof(*req
), IFLA_LINKMODE
, mode
);
773 } else if (strcmp(*argv
, "state") == 0) {
777 state
= get_operstate(*argv
);
779 invarg("Invalid operstate\n", *argv
);
781 addattr8(&req
->n
, sizeof(*req
), IFLA_OPERSTATE
, state
);
782 } else if (matches(*argv
, "numtxqueues") == 0) {
784 if (numtxqueues
!= -1)
785 duparg("numtxqueues", *argv
);
786 if (get_integer(&numtxqueues
, *argv
, 0))
787 invarg("Invalid \"numtxqueues\" value\n",
789 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_TX_QUEUES
,
791 } else if (matches(*argv
, "numrxqueues") == 0) {
793 if (numrxqueues
!= -1)
794 duparg("numrxqueues", *argv
);
795 if (get_integer(&numrxqueues
, *argv
, 0))
796 invarg("Invalid \"numrxqueues\" value\n",
798 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_RX_QUEUES
,
800 } else if (matches(*argv
, "addrgenmode") == 0) {
801 struct rtattr
*afs
, *afs6
;
805 mode
= get_addr_gen_mode(*argv
);
807 invarg("Invalid address generation mode\n",
809 afs
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_AF_SPEC
);
810 afs6
= addattr_nest(&req
->n
, sizeof(*req
), AF_INET6
);
811 addattr8(&req
->n
, sizeof(*req
),
812 IFLA_INET6_ADDR_GEN_MODE
, mode
);
813 addattr_nest_end(&req
->n
, afs6
);
814 addattr_nest_end(&req
->n
, afs
);
815 } else if (matches(*argv
, "link-netnsid") == 0) {
817 if (link_netnsid
!= -1)
818 duparg("link-netnsid", *argv
);
819 if (get_integer(&link_netnsid
, *argv
, 0))
820 invarg("Invalid \"link-netnsid\" value\n",
822 addattr32(&req
->n
, sizeof(*req
), IFLA_LINK_NETNSID
,
824 } else if (strcmp(*argv
, "protodown") == 0) {
825 unsigned int proto_down
;
828 if (strcmp(*argv
, "on") == 0)
830 else if (strcmp(*argv
, "off") == 0)
833 return on_off("protodown", *argv
);
834 addattr8(&req
->n
, sizeof(*req
), IFLA_PROTO_DOWN
,
837 if (matches(*argv
, "help") == 0)
840 if (strcmp(*argv
, "dev") == 0)
843 duparg2("dev", *argv
);
845 dev_index
= ll_name_to_index(*dev
);
850 if (dev_index
&& addr_len
) {
851 int halen
= nl_get_ll_addr_len(dev_index
);
853 if (halen
>= 0 && halen
!= addr_len
) {
855 "Invalid address length %d - must be %d bytes\n",
864 static int iplink_modify(int cmd
, unsigned int flags
, int argc
, char **argv
)
873 struct link_util
*lu
= NULL
;
874 struct iplink_req req
= {
875 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
876 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
878 .i
.ifi_family
= preferred_family
,
882 ret
= iplink_parse(argc
, argv
,
883 &req
, &name
, &type
, &link
, &dev
, &group
, &index
);
892 addattr_l(&req
.n
, sizeof(req
), IFLA_GROUP
,
893 &group
, sizeof(group
));
897 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
901 if (flags
& NLM_F_CREATE
) {
903 "group cannot be used when creating devices.\n");
908 addattr32(&req
.n
, sizeof(req
), IFLA_GROUP
, group
);
909 if (rtnl_talk(&rth
, &req
.n
, NULL
, 0) < 0)
915 if (!(flags
& NLM_F_CREATE
)) {
918 "Not enough information: \"dev\" argument is required.\n");
921 if (cmd
== RTM_NEWLINK
&& index
!= -1) {
923 "index can be used only when creating devices.\n");
927 req
.i
.ifi_index
= ll_name_to_index(dev
);
928 if (req
.i
.ifi_index
== 0) {
929 fprintf(stderr
, "Cannot find device \"%s\"\n", dev
);
933 /* Allow "ip link add dev" and "ip link add name" */
940 ifindex
= ll_name_to_index(link
);
942 fprintf(stderr
, "Cannot find device \"%s\"\n",
946 addattr_l(&req
.n
, sizeof(req
), IFLA_LINK
, &ifindex
, 4);
952 req
.i
.ifi_index
= index
;
956 len
= strlen(name
) + 1;
958 invarg("\"\" is not a valid device identifier\n",
961 invarg("\"name\" too long\n", name
);
962 addattr_l(&req
.n
, sizeof(req
), IFLA_IFNAME
, name
, len
);
966 struct rtattr
*linkinfo
;
967 char *ulinep
= strchr(type
, '_');
970 linkinfo
= addattr_nest(&req
.n
, sizeof(req
), IFLA_LINKINFO
);
971 addattr_l(&req
.n
, sizeof(req
), IFLA_INFO_KIND
, type
,
974 lu
= get_link_kind(type
);
975 if (ulinep
&& !strcmp(ulinep
, "_slave"))
976 iflatype
= IFLA_INFO_SLAVE_DATA
;
978 iflatype
= IFLA_INFO_DATA
;
981 = addattr_nest(&req
.n
,
982 sizeof(req
), iflatype
);
985 lu
->parse_opt(lu
, argc
, argv
, &req
.n
))
988 addattr_nest_end(&req
.n
, data
);
990 if (matches(*argv
, "help") == 0)
993 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
997 addattr_nest_end(&req
.n
, linkinfo
);
998 } else if (flags
& NLM_F_CREATE
) {
1000 "Not enough information: \"type\" argument is required\n");
1004 if (rtnl_talk(&rth
, &req
.n
, NULL
, 0) < 0)
1010 int iplink_get(unsigned int flags
, char *name
, __u32 filt_mask
)
1013 struct iplink_req req
= {
1014 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
1015 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
1016 .n
.nlmsg_type
= RTM_GETLINK
,
1017 .i
.ifi_family
= preferred_family
,
1025 len
= strlen(name
) + 1;
1027 invarg("\"\" is not a valid device identifier\n",
1030 invarg("\"name\" too long\n", name
);
1031 addattr_l(&req
.n
, sizeof(req
), IFLA_IFNAME
, name
, len
);
1033 addattr32(&req
.n
, sizeof(req
), IFLA_EXT_MASK
, filt_mask
);
1035 if (rtnl_talk(&rth
, &req
.n
, &answer
.n
, sizeof(answer
)) < 0)
1039 print_linkinfo_brief(NULL
, &answer
.n
, stdout
, NULL
);
1041 print_linkinfo(NULL
, &answer
.n
, stdout
);
1046 #if IPLINK_IOCTL_COMPAT
1047 static int get_ctl_fd(void)
1052 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
1056 fd
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
1059 fd
= socket(PF_INET6
, SOCK_DGRAM
, 0);
1063 perror("Cannot create control socket");
1067 static int do_chflags(const char *dev
, __u32 flags
, __u32 mask
)
1073 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1077 err
= ioctl(fd
, SIOCGIFFLAGS
, &ifr
);
1079 perror("SIOCGIFFLAGS");
1083 if ((ifr
.ifr_flags
^flags
)&mask
) {
1084 ifr
.ifr_flags
&= ~mask
;
1085 ifr
.ifr_flags
|= mask
&flags
;
1086 err
= ioctl(fd
, SIOCSIFFLAGS
, &ifr
);
1088 perror("SIOCSIFFLAGS");
1094 static int do_changename(const char *dev
, const char *newdev
)
1100 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1101 strncpy(ifr
.ifr_newname
, newdev
, IFNAMSIZ
);
1105 err
= ioctl(fd
, SIOCSIFNAME
, &ifr
);
1107 perror("SIOCSIFNAME");
1115 static int set_qlen(const char *dev
, int qlen
)
1117 struct ifreq ifr
= { .ifr_qlen
= qlen
};
1124 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1125 if (ioctl(s
, SIOCSIFTXQLEN
, &ifr
) < 0) {
1126 perror("SIOCSIFXQLEN");
1135 static int set_mtu(const char *dev
, int mtu
)
1137 struct ifreq ifr
= { .ifr_mtu
= mtu
};
1144 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1145 if (ioctl(s
, SIOCSIFMTU
, &ifr
) < 0) {
1146 perror("SIOCSIFMTU");
1155 static int get_address(const char *dev
, int *htype
)
1157 struct ifreq ifr
= {};
1158 struct sockaddr_ll me
= {
1159 .sll_family
= AF_PACKET
,
1160 .sll_protocol
= htons(ETH_P_LOOP
),
1165 s
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
1167 perror("socket(PF_PACKET)");
1171 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1172 if (ioctl(s
, SIOCGIFINDEX
, &ifr
) < 0) {
1173 perror("SIOCGIFINDEX");
1178 me
.sll_ifindex
= ifr
.ifr_ifindex
;
1179 if (bind(s
, (struct sockaddr
*)&me
, sizeof(me
)) == -1) {
1186 if (getsockname(s
, (struct sockaddr
*)&me
, &alen
) == -1) {
1187 perror("getsockname");
1192 *htype
= me
.sll_hatype
;
1193 return me
.sll_halen
;
1196 static int parse_address(const char *dev
, int hatype
, int halen
,
1197 char *lla
, struct ifreq
*ifr
)
1201 memset(ifr
, 0, sizeof(*ifr
));
1202 strncpy(ifr
->ifr_name
, dev
, IFNAMSIZ
);
1203 ifr
->ifr_hwaddr
.sa_family
= hatype
;
1204 alen
= ll_addr_a2n(ifr
->ifr_hwaddr
.sa_data
, 14, lla
);
1207 if (alen
!= halen
) {
1209 "Wrong address (%s) length: expected %d bytes\n",
1216 static int set_address(struct ifreq
*ifr
, int brd
)
1223 if (ioctl(s
, brd
?SIOCSIFHWBROADCAST
:SIOCSIFHWADDR
, ifr
) < 0) {
1224 perror(brd
?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
1232 static int do_set(int argc
, char **argv
)
1239 char *newaddr
= NULL
;
1240 char *newbrd
= NULL
;
1241 struct ifreq ifr0
, ifr1
;
1242 char *newname
= NULL
;
1246 if (strcmp(*argv
, "up") == 0) {
1249 } else if (strcmp(*argv
, "down") == 0) {
1252 } else if (strcmp(*argv
, "name") == 0) {
1255 } else if (matches(*argv
, "address") == 0) {
1258 } else if (matches(*argv
, "broadcast") == 0 ||
1259 strcmp(*argv
, "brd") == 0) {
1262 } else if (matches(*argv
, "txqueuelen") == 0 ||
1263 strcmp(*argv
, "qlen") == 0 ||
1264 matches(*argv
, "txqlen") == 0) {
1267 duparg("txqueuelen", *argv
);
1268 if (get_integer(&qlen
, *argv
, 0))
1269 invarg("Invalid \"txqueuelen\" value\n", *argv
);
1270 } else if (strcmp(*argv
, "mtu") == 0) {
1273 duparg("mtu", *argv
);
1274 if (get_integer(&mtu
, *argv
, 0))
1275 invarg("Invalid \"mtu\" value\n", *argv
);
1276 } else if (strcmp(*argv
, "multicast") == 0) {
1278 mask
|= IFF_MULTICAST
;
1280 if (strcmp(*argv
, "on") == 0)
1281 flags
|= IFF_MULTICAST
;
1282 else if (strcmp(*argv
, "off") == 0)
1283 flags
&= ~IFF_MULTICAST
;
1285 return on_off("multicast", *argv
);
1286 } else if (strcmp(*argv
, "allmulticast") == 0) {
1288 mask
|= IFF_ALLMULTI
;
1290 if (strcmp(*argv
, "on") == 0)
1291 flags
|= IFF_ALLMULTI
;
1292 else if (strcmp(*argv
, "off") == 0)
1293 flags
&= ~IFF_ALLMULTI
;
1295 return on_off("allmulticast", *argv
);
1296 } else if (strcmp(*argv
, "promisc") == 0) {
1298 mask
|= IFF_PROMISC
;
1300 if (strcmp(*argv
, "on") == 0)
1301 flags
|= IFF_PROMISC
;
1302 else if (strcmp(*argv
, "off") == 0)
1303 flags
&= ~IFF_PROMISC
;
1305 return on_off("promisc", *argv
);
1306 } else if (strcmp(*argv
, "trailers") == 0) {
1308 mask
|= IFF_NOTRAILERS
;
1310 if (strcmp(*argv
, "off") == 0)
1311 flags
|= IFF_NOTRAILERS
;
1312 else if (strcmp(*argv
, "on") == 0)
1313 flags
&= ~IFF_NOTRAILERS
;
1315 return on_off("trailers", *argv
);
1316 } else if (strcmp(*argv
, "arp") == 0) {
1320 if (strcmp(*argv
, "on") == 0)
1321 flags
&= ~IFF_NOARP
;
1322 else if (strcmp(*argv
, "off") == 0)
1325 return on_off("arp", *argv
);
1326 } else if (matches(*argv
, "dynamic") == 0) {
1328 mask
|= IFF_DYNAMIC
;
1330 if (strcmp(*argv
, "on") == 0)
1331 flags
|= IFF_DYNAMIC
;
1332 else if (strcmp(*argv
, "off") == 0)
1333 flags
&= ~IFF_DYNAMIC
;
1335 return on_off("dynamic", *argv
);
1337 if (strcmp(*argv
, "dev") == 0)
1339 else if (matches(*argv
, "help") == 0)
1343 duparg2("dev", *argv
);
1351 "Not enough of information: \"dev\" argument is required.\n");
1355 if (newaddr
|| newbrd
) {
1356 halen
= get_address(dev
, &htype
);
1360 if (parse_address(dev
, htype
, halen
,
1361 newaddr
, &ifr0
) < 0)
1365 if (parse_address(dev
, htype
, halen
,
1371 if (newname
&& strcmp(dev
, newname
)) {
1372 if (strlen(newname
) == 0)
1373 invarg("\"\" is not a valid device identifier\n",
1375 if (do_changename(dev
, newname
) < 0)
1380 if (set_qlen(dev
, qlen
) < 0)
1384 if (set_mtu(dev
, mtu
) < 0)
1387 if (newaddr
|| newbrd
) {
1389 if (set_address(&ifr1
, 1) < 0)
1393 if (set_address(&ifr0
, 0) < 0)
1398 return do_chflags(dev
, flags
, mask
);
1401 #endif /* IPLINK_IOCTL_COMPAT */
1403 static void print_mpls_stats(FILE *fp
, struct rtattr
*attr
)
1405 struct rtattr
*mrtb
[MPLS_STATS_MAX
+1];
1406 struct mpls_link_stats
*stats
;
1408 parse_rtattr(mrtb
, MPLS_STATS_MAX
, RTA_DATA(attr
),
1410 if (!mrtb
[MPLS_STATS_LINK
])
1413 stats
= RTA_DATA(mrtb
[MPLS_STATS_LINK
]);
1415 fprintf(fp
, " mpls:\n");
1416 fprintf(fp
, " RX: bytes packets errors dropped noroute\n");
1418 print_num(fp
, 10, stats
->rx_bytes
);
1419 print_num(fp
, 8, stats
->rx_packets
);
1420 print_num(fp
, 7, stats
->rx_errors
);
1421 print_num(fp
, 8, stats
->rx_dropped
);
1422 print_num(fp
, 7, stats
->rx_noroute
);
1424 fprintf(fp
, " TX: bytes packets errors dropped\n");
1426 print_num(fp
, 10, stats
->tx_bytes
);
1427 print_num(fp
, 8, stats
->tx_packets
);
1428 print_num(fp
, 7, stats
->tx_errors
);
1429 print_num(fp
, 7, stats
->tx_dropped
);
1433 static void print_af_stats_attr(FILE *fp
, int ifindex
, struct rtattr
*attr
)
1435 bool if_printed
= false;
1439 rem
= RTA_PAYLOAD(attr
);
1440 for (i
= RTA_DATA(attr
); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
)) {
1441 if (preferred_family
!= AF_UNSPEC
&&
1442 i
->rta_type
!= preferred_family
)
1446 fprintf(fp
, "%u: %s\n", ifindex
,
1447 ll_index_to_name(ifindex
));
1451 switch (i
->rta_type
) {
1453 print_mpls_stats(fp
, i
);
1456 fprintf(fp
, " unknown af(%d)\n", i
->rta_type
);
1462 struct af_stats_ctx
{
1467 static int print_af_stats(const struct sockaddr_nl
*who
,
1471 struct if_stats_msg
*ifsm
= NLMSG_DATA(n
);
1472 struct rtattr
*tb
[IFLA_STATS_MAX
+1];
1473 int len
= n
->nlmsg_len
;
1474 struct af_stats_ctx
*ctx
= arg
;
1477 len
-= NLMSG_LENGTH(sizeof(*ifsm
));
1479 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
1483 if (ctx
->ifindex
&& ifsm
->ifindex
!= ctx
->ifindex
)
1486 parse_rtattr(tb
, IFLA_STATS_MAX
, IFLA_STATS_RTA(ifsm
), len
);
1488 if (tb
[IFLA_STATS_AF_SPEC
])
1489 print_af_stats_attr(fp
, ifsm
->ifindex
, tb
[IFLA_STATS_AF_SPEC
]);
1495 static int iplink_afstats(int argc
, char **argv
)
1497 __u32 filt_mask
= IFLA_STATS_FILTER_BIT(IFLA_STATS_AF_SPEC
);
1498 const char *filter_dev
= NULL
;
1499 struct af_stats_ctx ctx
= {
1505 if (strcmp(*argv
, "dev") == 0) {
1508 duparg2("dev", *argv
);
1510 } else if (matches(*argv
, "help") == 0) {
1514 "Command \"%s\" is unknown, try \"ip link help\".\n",
1523 ctx
.ifindex
= ll_name_to_index(filter_dev
);
1524 if (ctx
.ifindex
<= 0) {
1526 "Device \"%s\" does not exist.\n",
1532 if (rtnl_wilddump_stats_req_filter(&rth
, AF_UNSPEC
,
1535 perror("Cannont send dump request");
1539 if (rtnl_dump_filter(&rth
, print_af_stats
, &ctx
) < 0) {
1540 fprintf(stderr
, "Dump terminated\n");
1547 static void do_help(int argc
, char **argv
)
1549 struct link_util
*lu
= NULL
;
1556 lu
= get_link_kind(*argv
);
1557 if (lu
&& lu
->print_help
)
1558 lu
->print_help(lu
, argc
-1, argv
+1, stdout
);
1563 int do_iplink(int argc
, char **argv
)
1566 return ipaddr_list_link(0, NULL
);
1568 if (iplink_have_newlink()) {
1569 if (matches(*argv
, "add") == 0)
1570 return iplink_modify(RTM_NEWLINK
,
1571 NLM_F_CREATE
|NLM_F_EXCL
,
1573 if (matches(*argv
, "set") == 0 ||
1574 matches(*argv
, "change") == 0)
1575 return iplink_modify(RTM_NEWLINK
, 0,
1577 if (matches(*argv
, "replace") == 0)
1578 return iplink_modify(RTM_NEWLINK
,
1579 NLM_F_CREATE
|NLM_F_REPLACE
,
1581 if (matches(*argv
, "delete") == 0)
1582 return iplink_modify(RTM_DELLINK
, 0,
1585 #if IPLINK_IOCTL_COMPAT
1586 if (matches(*argv
, "set") == 0)
1587 return do_set(argc
-1, argv
+1);
1591 if (matches(*argv
, "show") == 0 ||
1592 matches(*argv
, "lst") == 0 ||
1593 matches(*argv
, "list") == 0)
1594 return ipaddr_list_link(argc
-1, argv
+1);
1596 if (matches(*argv
, "xstats") == 0)
1597 return iplink_ifla_xstats(argc
-1, argv
+1);
1599 if (matches(*argv
, "afstats") == 0) {
1600 iplink_afstats(argc
-1, argv
+1);
1604 if (matches(*argv
, "help") == 0) {
1605 do_help(argc
-1, argv
+1);
1609 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip link help\".\n",