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>
19 #include <sys/socket.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>
27 #include <sys/ioctl.h>
29 #include <linux/mpls.h>
33 #include "ip_common.h"
34 #include "namespace.h"
36 #define IPLINK_IOCTL_COMPAT 1
39 #define GSO_MAX_SIZE 65536
42 #define GSO_MAX_SEGS 65535
46 static void usage(void) __attribute__((noreturn
));
47 static int iplink_have_newlink(void);
49 void iplink_usage(void)
51 if (iplink_have_newlink()) {
53 "Usage: ip link add [link DEV] [ name ] NAME\n"
54 " [ txqueuelen PACKETS ]\n"
55 " [ address LLADDR ]\n"
56 " [ broadcast LLADDR ]\n"
57 " [ mtu MTU ] [index IDX ]\n"
58 " [ numtxqueues QUEUE_COUNT ]\n"
59 " [ numrxqueues QUEUE_COUNT ]\n"
60 " type TYPE [ ARGS ]\n"
62 " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"
64 " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"
65 " [ { up | down } ]\n"
66 " [ type TYPE ARGS ]\n");
69 "Usage: ip link set DEVICE [ { up | down } ]\n");
72 " [ arp { on | off } ]\n"
73 " [ dynamic { on | off } ]\n"
74 " [ multicast { on | off } ]\n"
75 " [ allmulticast { on | off } ]\n"
76 " [ promisc { on | off } ]\n"
77 " [ trailers { on | off } ]\n"
78 " [ carrier { on | off } ]\n"
79 " [ txqueuelen PACKETS ]\n"
81 " [ address LLADDR ]\n"
82 " [ broadcast LLADDR ]\n"
84 " [ netns { PID | NAME } ]\n"
85 " [ link-netns NAME | link-netnsid ID ]\n"
87 " [ vf NUM [ mac LLADDR ]\n"
88 " [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]\n"
90 " [ max_tx_rate TXRATE ]\n"
91 " [ min_tx_rate TXRATE ]\n"
92 " [ spoofchk { on | off} ]\n"
93 " [ query_rss { on | off} ]\n"
94 " [ state { auto | enable | disable} ]\n"
95 " [ trust { on | off} ]\n"
96 " [ node_guid EUI64 ]\n"
97 " [ port_guid EUI64 ] ]\n"
98 " [ { xdp | xdpgeneric | xdpdrv | xdpoffload } { off |\n"
99 " object FILE [ section NAME ] [ verbose ] |\n"
101 " [ master DEVICE ][ vrf NAME ]\n"
103 " [ addrgenmode { eui64 | none | stable_secret | random } ]\n"
104 " [ protodown { on | off } ]\n"
105 " [ protodown_reason PREASON { on | off } ]\n"
106 " [ gso_max_size BYTES ] | [ gso_max_segs PACKETS ]\n"
108 " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n"
110 " ip link xstats type TYPE [ ARGS ]\n"
112 " ip link afstats [ dev DEVICE ]\n"
113 " ip link property add dev DEVICE [ altname NAME .. ]\n"
114 " ip link property del dev DEVICE [ altname NAME .. ]\n");
116 if (iplink_have_newlink()) {
119 " ip link help [ TYPE ]\n"
121 "TYPE := { vlan | veth | vcan | vxcan | dummy | ifb | macvlan | macvtap |\n"
122 " bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
123 " gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n"
124 " vti | nlmon | team_slave | bond_slave | bridge_slave |\n"
125 " ipvlan | ipvtap | geneve | bareudp | vrf | macsec | netdevsim | rmnet |\n"
131 static void usage(void)
136 static int on_off(const char *msg
, const char *realval
)
139 "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
144 static void *BODY
; /* cached dlopen(NULL) handle */
145 static struct link_util
*linkutil_list
;
147 struct link_util
*get_link_kind(const char *id
)
153 for (l
= linkutil_list
; l
; l
= l
->next
)
154 if (strcmp(l
->id
, id
) == 0)
157 snprintf(buf
, sizeof(buf
), "%s/link_%s.so", get_ip_lib_dir(), id
);
158 dlh
= dlopen(buf
, RTLD_LAZY
);
160 /* look in current binary, only open once */
163 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
169 snprintf(buf
, sizeof(buf
), "%s_link_util", id
);
174 l
->next
= linkutil_list
;
179 static int get_link_mode(const char *mode
)
181 if (strcasecmp(mode
, "default") == 0)
182 return IF_LINK_MODE_DEFAULT
;
183 if (strcasecmp(mode
, "dormant") == 0)
184 return IF_LINK_MODE_DORMANT
;
188 static int get_addr_gen_mode(const char *mode
)
190 if (strcasecmp(mode
, "eui64") == 0)
191 return IN6_ADDR_GEN_MODE_EUI64
;
192 if (strcasecmp(mode
, "none") == 0)
193 return IN6_ADDR_GEN_MODE_NONE
;
194 if (strcasecmp(mode
, "stable_secret") == 0)
195 return IN6_ADDR_GEN_MODE_STABLE_PRIVACY
;
196 if (strcasecmp(mode
, "random") == 0)
197 return IN6_ADDR_GEN_MODE_RANDOM
;
201 #if IPLINK_IOCTL_COMPAT
202 static int have_rtnl_newlink
= -1;
204 static int accept_msg(struct rtnl_ctrl_data
*ctrl
,
205 struct nlmsghdr
*n
, void *arg
)
207 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(n
);
209 if (n
->nlmsg_type
== NLMSG_ERROR
&&
210 (err
->error
== -EOPNOTSUPP
|| err
->error
== -EINVAL
))
211 have_rtnl_newlink
= 0;
213 have_rtnl_newlink
= 1;
217 static int iplink_have_newlink(void)
224 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
225 .n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
,
226 .n
.nlmsg_type
= RTM_NEWLINK
,
227 .i
.ifi_family
= AF_UNSPEC
,
230 if (have_rtnl_newlink
< 0) {
231 if (rtnl_send(&rth
, &req
.n
, req
.n
.nlmsg_len
) < 0) {
232 perror("request send failed");
235 rtnl_listen(&rth
, accept_msg
, NULL
);
237 return have_rtnl_newlink
;
239 #else /* IPLINK_IOCTL_COMPAT */
240 static int iplink_have_newlink(void)
244 #endif /* ! IPLINK_IOCTL_COMPAT */
246 static int nl_get_ll_addr_len(const char *ifname
)
249 int dev_index
= ll_name_to_index(ifname
);
250 struct iplink_req req
= {
252 .nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
253 .nlmsg_type
= RTM_GETLINK
,
254 .nlmsg_flags
= NLM_F_REQUEST
257 .ifi_family
= preferred_family
,
258 .ifi_index
= dev_index
,
261 struct nlmsghdr
*answer
;
262 struct rtattr
*tb
[IFLA_MAX
+1];
267 if (rtnl_talk(&rth
, &req
.n
, &answer
) < 0)
270 len
= answer
->nlmsg_len
- NLMSG_LENGTH(sizeof(struct ifinfomsg
));
276 parse_rtattr_flags(tb
, IFLA_MAX
, IFLA_RTA(NLMSG_DATA(answer
)),
278 if (!tb
[IFLA_ADDRESS
]) {
283 len
= RTA_PAYLOAD(tb
[IFLA_ADDRESS
]);
288 static void iplink_parse_vf_vlan_info(int vf
, int *argcp
, char ***argvp
,
289 struct ifla_vf_vlan_info
*ivvip
)
292 char **argv
= *argvp
;
296 if (get_unsigned(&vci
, *argv
, 0) || vci
> 4095)
297 invarg("Invalid \"vlan\" value\n", *argv
);
302 ivvip
->vlan_proto
= htons(ETH_P_8021Q
);
305 if (matches(*argv
, "qos") == 0) {
307 if (get_unsigned(&ivvip
->qos
, *argv
, 0))
308 invarg("Invalid \"qos\" value\n", *argv
);
316 if (matches(*argv
, "proto") == 0) {
318 if (ll_proto_a2n(&ivvip
->vlan_proto
, *argv
))
319 invarg("protocol is invalid\n", *argv
);
320 if (ivvip
->vlan_proto
!= htons(ETH_P_8021AD
) &&
321 ivvip
->vlan_proto
!= htons(ETH_P_8021Q
)) {
324 char msg
[64 + sizeof(b1
) + sizeof(b2
)];
327 "Invalid \"vlan protocol\" value - supported %s, %s\n",
328 ll_proto_n2a(htons(ETH_P_8021Q
),
330 ll_proto_n2a(htons(ETH_P_8021AD
),
344 static int iplink_parse_vf(int vf
, int *argcp
, char ***argvp
,
345 struct iplink_req
*req
, const char *dev
)
347 char new_rate_api
= 0, count
= 0, override_legacy_rate
= 0;
348 struct ifla_vf_rate tivt
;
349 int len
, argc
= *argcp
;
350 char **argv
= *argvp
;
351 struct rtattr
*vfinfo
;
354 tivt
.min_tx_rate
= -1;
355 tivt
.max_tx_rate
= -1;
357 vfinfo
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_VF_INFO
);
359 while (NEXT_ARG_OK()) {
362 if (!matches(*argv
, "max_tx_rate")) {
365 /* override legacy rate */
366 override_legacy_rate
= 1;
367 } else if (!matches(*argv
, "min_tx_rate")) {
378 while (NEXT_ARG_OK()) {
380 if (matches(*argv
, "mac") == 0) {
381 struct ifla_vf_mac ivm
= { 0 };
382 int halen
= nl_get_ll_addr_len(dev
);
386 len
= ll_addr_a2n((char *)ivm
.mac
, 32, *argv
);
389 if (halen
> 0 && len
!= halen
) {
391 "Invalid address length %d - must be %d bytes\n",
395 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_MAC
,
397 } else if (matches(*argv
, "vlan") == 0) {
398 struct ifla_vf_vlan_info ivvi
;
400 iplink_parse_vf_vlan_info(vf
, &argc
, &argv
, &ivvi
);
401 /* support the old interface in case of older kernel*/
402 if (ivvi
.vlan_proto
== htons(ETH_P_8021Q
)) {
403 struct ifla_vf_vlan ivv
;
406 ivv
.vlan
= ivvi
.vlan
;
408 addattr_l(&req
->n
, sizeof(*req
),
409 IFLA_VF_VLAN
, &ivv
, sizeof(ivv
));
411 struct rtattr
*vfvlanlist
;
413 vfvlanlist
= addattr_nest(&req
->n
, sizeof(*req
),
415 addattr_l(&req
->n
, sizeof(*req
),
416 IFLA_VF_VLAN_INFO
, &ivvi
,
419 while (NEXT_ARG_OK()) {
421 if (matches(*argv
, "vlan") != 0) {
425 iplink_parse_vf_vlan_info(vf
, &argc
,
427 addattr_l(&req
->n
, sizeof(*req
),
428 IFLA_VF_VLAN_INFO
, &ivvi
,
431 addattr_nest_end(&req
->n
, vfvlanlist
);
433 } else if (matches(*argv
, "rate") == 0) {
434 struct ifla_vf_tx_rate ivt
;
437 if (get_unsigned(&ivt
.rate
, *argv
, 0))
438 invarg("Invalid \"rate\" value\n", *argv
);
442 addattr_l(&req
->n
, sizeof(*req
),
443 IFLA_VF_TX_RATE
, &ivt
, sizeof(ivt
));
444 else if (!override_legacy_rate
)
445 tivt
.max_tx_rate
= ivt
.rate
;
447 } else if (matches(*argv
, "max_tx_rate") == 0) {
449 if (get_unsigned(&tivt
.max_tx_rate
, *argv
, 0))
450 invarg("Invalid \"max tx rate\" value\n",
454 } else if (matches(*argv
, "min_tx_rate") == 0) {
456 if (get_unsigned(&tivt
.min_tx_rate
, *argv
, 0))
457 invarg("Invalid \"min tx rate\" value\n",
461 } else if (matches(*argv
, "spoofchk") == 0) {
462 struct ifla_vf_spoofchk ivs
;
465 ivs
.setting
= parse_on_off("spoofchk", *argv
, &ret
);
469 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_SPOOFCHK
,
472 } else if (matches(*argv
, "query_rss") == 0) {
473 struct ifla_vf_rss_query_en ivs
;
476 ivs
.setting
= parse_on_off("query_rss", *argv
, &ret
);
480 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RSS_QUERY_EN
,
483 } else if (matches(*argv
, "trust") == 0) {
484 struct ifla_vf_trust ivt
;
487 ivt
.setting
= parse_on_off("trust", *argv
, &ret
);
491 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_TRUST
,
494 } else if (matches(*argv
, "state") == 0) {
495 struct ifla_vf_link_state ivl
;
498 if (matches(*argv
, "auto") == 0)
499 ivl
.link_state
= IFLA_VF_LINK_STATE_AUTO
;
500 else if (matches(*argv
, "enable") == 0)
501 ivl
.link_state
= IFLA_VF_LINK_STATE_ENABLE
;
502 else if (matches(*argv
, "disable") == 0)
503 ivl
.link_state
= IFLA_VF_LINK_STATE_DISABLE
;
505 invarg("Invalid \"state\" value\n", *argv
);
507 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_LINK_STATE
,
509 } else if (matches(*argv
, "node_guid") == 0) {
510 struct ifla_vf_guid ivg
;
514 if (get_guid(&ivg
.guid
, *argv
)) {
515 invarg("Invalid GUID format\n", *argv
);
518 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_NODE_GUID
,
520 } else if (matches(*argv
, "port_guid") == 0) {
521 struct ifla_vf_guid ivg
;
525 if (get_guid(&ivg
.guid
, *argv
)) {
526 invarg("Invalid GUID format\n", *argv
);
529 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_PORT_GUID
,
541 if (tivt
.min_tx_rate
== -1 || tivt
.max_tx_rate
== -1) {
542 ipaddr_get_vf_rate(tivt
.vf
, &tmin
, &tmax
, dev
);
543 if (tivt
.min_tx_rate
== -1)
544 tivt
.min_tx_rate
= tmin
;
545 if (tivt
.max_tx_rate
== -1)
546 tivt
.max_tx_rate
= tmax
;
549 if (tivt
.max_tx_rate
&& tivt
.min_tx_rate
> tivt
.max_tx_rate
) {
551 "Invalid min_tx_rate %d - must be <= max_tx_rate %d\n",
552 tivt
.min_tx_rate
, tivt
.max_tx_rate
);
556 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RATE
, &tivt
,
561 incomplete_command();
563 addattr_nest_end(&req
->n
, vfinfo
);
570 int iplink_parse(int argc
, char **argv
, struct iplink_req
*req
, char **type
)
581 int numtxqueues
= -1;
582 int numrxqueues
= -1;
583 int link_netnsid
= -1;
592 if (strcmp(*argv
, "up") == 0) {
593 req
->i
.ifi_change
|= IFF_UP
;
594 req
->i
.ifi_flags
|= IFF_UP
;
595 } else if (strcmp(*argv
, "down") == 0) {
596 req
->i
.ifi_change
|= IFF_UP
;
597 req
->i
.ifi_flags
&= ~IFF_UP
;
598 } else if (strcmp(*argv
, "name") == 0) {
601 duparg("name", *argv
);
602 if (check_ifname(*argv
))
603 invarg("\"name\" not a valid ifname", *argv
);
607 } else if (strcmp(*argv
, "index") == 0) {
610 duparg("index", *argv
);
613 invarg("Invalid \"index\" value", *argv
);
614 } else if (matches(*argv
, "link") == 0) {
617 } else if (matches(*argv
, "address") == 0) {
619 addr_len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
622 addattr_l(&req
->n
, sizeof(*req
),
623 IFLA_ADDRESS
, abuf
, addr_len
);
624 } else if (matches(*argv
, "broadcast") == 0 ||
625 strcmp(*argv
, "brd") == 0) {
627 len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
630 addattr_l(&req
->n
, sizeof(*req
),
631 IFLA_BROADCAST
, abuf
, len
);
632 } else if (matches(*argv
, "txqueuelen") == 0 ||
633 strcmp(*argv
, "qlen") == 0 ||
634 matches(*argv
, "txqlen") == 0) {
637 duparg("txqueuelen", *argv
);
638 if (get_integer(&qlen
, *argv
, 0))
639 invarg("Invalid \"txqueuelen\" value\n", *argv
);
640 addattr_l(&req
->n
, sizeof(*req
),
641 IFLA_TXQLEN
, &qlen
, 4);
642 } else if (strcmp(*argv
, "mtu") == 0) {
645 duparg("mtu", *argv
);
646 if (get_integer(&mtu
, *argv
, 0))
647 invarg("Invalid \"mtu\" value\n", *argv
);
648 addattr_l(&req
->n
, sizeof(*req
), IFLA_MTU
, &mtu
, 4);
649 } else if (strcmp(*argv
, "xdpgeneric") == 0 ||
650 strcmp(*argv
, "xdpdrv") == 0 ||
651 strcmp(*argv
, "xdpoffload") == 0 ||
652 strcmp(*argv
, "xdp") == 0) {
653 bool generic
= strcmp(*argv
, "xdpgeneric") == 0;
654 bool drv
= strcmp(*argv
, "xdpdrv") == 0;
655 bool offload
= strcmp(*argv
, "xdpoffload") == 0;
658 if (xdp_parse(&argc
, &argv
, req
, dev
,
659 generic
, drv
, offload
))
662 if (offload
&& name
== dev
)
664 } else if (strcmp(*argv
, "netns") == 0) {
667 duparg("netns", *argv
);
668 netns
= netns_get_fd(*argv
);
670 addattr_l(&req
->n
, sizeof(*req
), IFLA_NET_NS_FD
,
672 else if (get_integer(&netns
, *argv
, 0) == 0)
673 addattr_l(&req
->n
, sizeof(*req
),
674 IFLA_NET_NS_PID
, &netns
, 4);
676 invarg("Invalid \"netns\" value\n", *argv
);
677 } else if (strcmp(*argv
, "multicast") == 0) {
679 req
->i
.ifi_change
|= IFF_MULTICAST
;
681 if (strcmp(*argv
, "on") == 0)
682 req
->i
.ifi_flags
|= IFF_MULTICAST
;
683 else if (strcmp(*argv
, "off") == 0)
684 req
->i
.ifi_flags
&= ~IFF_MULTICAST
;
686 return on_off("multicast", *argv
);
687 } else if (strcmp(*argv
, "allmulticast") == 0) {
689 req
->i
.ifi_change
|= IFF_ALLMULTI
;
691 if (strcmp(*argv
, "on") == 0)
692 req
->i
.ifi_flags
|= IFF_ALLMULTI
;
693 else if (strcmp(*argv
, "off") == 0)
694 req
->i
.ifi_flags
&= ~IFF_ALLMULTI
;
696 return on_off("allmulticast", *argv
);
697 } else if (strcmp(*argv
, "promisc") == 0) {
699 req
->i
.ifi_change
|= IFF_PROMISC
;
701 if (strcmp(*argv
, "on") == 0)
702 req
->i
.ifi_flags
|= IFF_PROMISC
;
703 else if (strcmp(*argv
, "off") == 0)
704 req
->i
.ifi_flags
&= ~IFF_PROMISC
;
706 return on_off("promisc", *argv
);
707 } else if (strcmp(*argv
, "trailers") == 0) {
709 req
->i
.ifi_change
|= IFF_NOTRAILERS
;
711 if (strcmp(*argv
, "off") == 0)
712 req
->i
.ifi_flags
|= IFF_NOTRAILERS
;
713 else if (strcmp(*argv
, "on") == 0)
714 req
->i
.ifi_flags
&= ~IFF_NOTRAILERS
;
716 return on_off("trailers", *argv
);
717 } else if (strcmp(*argv
, "arp") == 0) {
719 req
->i
.ifi_change
|= IFF_NOARP
;
721 if (strcmp(*argv
, "on") == 0)
722 req
->i
.ifi_flags
&= ~IFF_NOARP
;
723 else if (strcmp(*argv
, "off") == 0)
724 req
->i
.ifi_flags
|= IFF_NOARP
;
726 return on_off("arp", *argv
);
727 } else if (strcmp(*argv
, "carrier") == 0) {
731 carrier
= parse_on_off("carrier", *argv
, &err
);
735 addattr8(&req
->n
, sizeof(*req
), IFLA_CARRIER
, carrier
);
736 } else if (strcmp(*argv
, "vf") == 0) {
737 struct rtattr
*vflist
;
740 if (get_integer(&vf
, *argv
, 0))
741 invarg("Invalid \"vf\" value\n", *argv
);
743 vflist
= addattr_nest(&req
->n
, sizeof(*req
),
748 len
= iplink_parse_vf(vf
, &argc
, &argv
, req
, dev
);
751 addattr_nest_end(&req
->n
, vflist
);
755 } else if (matches(*argv
, "master") == 0) {
759 ifindex
= ll_name_to_index(*argv
);
761 invarg("Device does not exist\n", *argv
);
762 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
764 } else if (strcmp(*argv
, "vrf") == 0) {
768 ifindex
= ll_name_to_index(*argv
);
770 invarg("Not a valid VRF name\n", *argv
);
771 if (!name_is_vrf(*argv
))
772 invarg("Not a valid VRF name\n", *argv
);
773 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
774 &ifindex
, sizeof(ifindex
));
775 } else if (matches(*argv
, "nomaster") == 0) {
778 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
780 } else if (matches(*argv
, "dynamic") == 0) {
782 req
->i
.ifi_change
|= IFF_DYNAMIC
;
784 if (strcmp(*argv
, "on") == 0)
785 req
->i
.ifi_flags
|= IFF_DYNAMIC
;
786 else if (strcmp(*argv
, "off") == 0)
787 req
->i
.ifi_flags
&= ~IFF_DYNAMIC
;
789 return on_off("dynamic", *argv
);
790 } else if (matches(*argv
, "type") == 0) {
795 } else if (matches(*argv
, "alias") == 0) {
799 invarg("alias too long\n", *argv
);
800 addattr_l(&req
->n
, sizeof(*req
), IFLA_IFALIAS
,
802 } else if (strcmp(*argv
, "group") == 0) {
805 duparg("group", *argv
);
806 if (rtnl_group_a2n(&group
, *argv
))
807 invarg("Invalid \"group\" value\n", *argv
);
808 addattr32(&req
->n
, sizeof(*req
), IFLA_GROUP
, group
);
809 } else if (strcmp(*argv
, "mode") == 0) {
813 mode
= get_link_mode(*argv
);
815 invarg("Invalid link mode\n", *argv
);
816 addattr8(&req
->n
, sizeof(*req
), IFLA_LINKMODE
, mode
);
817 } else if (strcmp(*argv
, "state") == 0) {
821 state
= get_operstate(*argv
);
823 invarg("Invalid operstate\n", *argv
);
825 addattr8(&req
->n
, sizeof(*req
), IFLA_OPERSTATE
, state
);
826 } else if (matches(*argv
, "numtxqueues") == 0) {
828 if (numtxqueues
!= -1)
829 duparg("numtxqueues", *argv
);
830 if (get_integer(&numtxqueues
, *argv
, 0))
831 invarg("Invalid \"numtxqueues\" value\n",
833 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_TX_QUEUES
,
835 } else if (matches(*argv
, "numrxqueues") == 0) {
837 if (numrxqueues
!= -1)
838 duparg("numrxqueues", *argv
);
839 if (get_integer(&numrxqueues
, *argv
, 0))
840 invarg("Invalid \"numrxqueues\" value\n",
842 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_RX_QUEUES
,
844 } else if (matches(*argv
, "addrgenmode") == 0) {
845 struct rtattr
*afs
, *afs6
;
849 mode
= get_addr_gen_mode(*argv
);
851 invarg("Invalid address generation mode\n",
853 afs
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_AF_SPEC
);
854 afs6
= addattr_nest(&req
->n
, sizeof(*req
), AF_INET6
);
855 addattr8(&req
->n
, sizeof(*req
),
856 IFLA_INET6_ADDR_GEN_MODE
, mode
);
857 addattr_nest_end(&req
->n
, afs6
);
858 addattr_nest_end(&req
->n
, afs
);
859 } else if (matches(*argv
, "link-netns") == 0) {
861 if (link_netnsid
!= -1)
862 duparg("link-netns/link-netnsid", *argv
);
863 link_netnsid
= get_netnsid_from_name(*argv
);
864 /* No nsid? Try to assign one. */
865 if (link_netnsid
< 0)
866 set_netnsid_from_name(*argv
, -1);
867 link_netnsid
= get_netnsid_from_name(*argv
);
868 if (link_netnsid
< 0)
869 invarg("Invalid \"link-netns\" value\n",
871 addattr32(&req
->n
, sizeof(*req
), IFLA_LINK_NETNSID
,
873 } else if (matches(*argv
, "link-netnsid") == 0) {
875 if (link_netnsid
!= -1)
876 duparg("link-netns/link-netnsid", *argv
);
877 if (get_integer(&link_netnsid
, *argv
, 0))
878 invarg("Invalid \"link-netnsid\" value\n",
880 addattr32(&req
->n
, sizeof(*req
), IFLA_LINK_NETNSID
,
882 } else if (strcmp(*argv
, "protodown") == 0) {
883 unsigned int proto_down
;
886 proto_down
= parse_on_off("protodown", *argv
, &err
);
889 addattr8(&req
->n
, sizeof(*req
), IFLA_PROTO_DOWN
,
891 } else if (strcmp(*argv
, "protodown_reason") == 0) {
893 __u32 preason
= 0, prvalue
= 0, prmask
= 0;
896 if (protodown_reason_a2n(&preason
, *argv
))
897 invarg("invalid protodown reason\n", *argv
);
899 prmask
= 1 << preason
;
900 if (matches(*argv
, "on") == 0)
902 else if (matches(*argv
, "off") == 0)
905 return on_off("protodown_reason", *argv
);
906 pr
= addattr_nest(&req
->n
, sizeof(*req
),
907 IFLA_PROTO_DOWN_REASON
| NLA_F_NESTED
);
908 addattr32(&req
->n
, sizeof(*req
),
909 IFLA_PROTO_DOWN_REASON_MASK
, prmask
);
910 addattr32(&req
->n
, sizeof(*req
),
911 IFLA_PROTO_DOWN_REASON_VALUE
, prvalue
);
912 addattr_nest_end(&req
->n
, pr
);
913 } else if (strcmp(*argv
, "gso_max_size") == 0) {
914 unsigned int max_size
;
917 if (get_unsigned(&max_size
, *argv
, 0) ||
918 max_size
> GSO_MAX_SIZE
)
919 invarg("Invalid \"gso_max_size\" value\n",
921 addattr32(&req
->n
, sizeof(*req
),
922 IFLA_GSO_MAX_SIZE
, max_size
);
923 } else if (strcmp(*argv
, "gso_max_segs") == 0) {
924 unsigned int max_segs
;
927 if (get_unsigned(&max_segs
, *argv
, 0) ||
928 max_segs
> GSO_MAX_SEGS
)
929 invarg("Invalid \"gso_max_segs\" value\n",
931 addattr32(&req
->n
, sizeof(*req
),
932 IFLA_GSO_MAX_SEGS
, max_segs
);
934 if (matches(*argv
, "help") == 0)
937 if (strcmp(*argv
, "dev") == 0)
940 duparg2("dev", *argv
);
941 if (check_altifname(*argv
))
942 invarg("\"dev\" not a valid ifname", *argv
);
950 /* Allow "ip link add dev" and "ip link add name" */
955 else if (!strcmp(name
, dev
))
958 if (dev
&& addr_len
&&
959 !(req
->n
.nlmsg_flags
& NLM_F_CREATE
)) {
960 int halen
= nl_get_ll_addr_len(dev
);
962 if (halen
>= 0 && halen
!= addr_len
) {
964 "Invalid address length %d - must be %d bytes\n",
970 if (!(req
->n
.nlmsg_flags
& NLM_F_CREATE
) && index
) {
972 "index can be used only when creating devices.\n");
980 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
984 if (req
->n
.nlmsg_flags
& NLM_F_CREATE
) {
986 "group cannot be used when creating devices.\n");
995 if (!(req
->n
.nlmsg_flags
& NLM_F_CREATE
)) {
998 "Not enough information: \"dev\" argument is required.\n");
1002 req
->i
.ifi_index
= ll_name_to_index(dev
);
1003 if (!req
->i
.ifi_index
)
1006 /* Not renaming to the same name */
1012 "both \"name\" and \"dev\" cannot be used when creating devices.\n");
1019 ifindex
= ll_name_to_index(link
);
1022 addattr32(&req
->n
, sizeof(*req
), IFLA_LINK
, ifindex
);
1025 req
->i
.ifi_index
= index
;
1029 addattr_l(&req
->n
, sizeof(*req
),
1030 IFLA_IFNAME
, name
, strlen(name
) + 1);
1036 static int iplink_modify(int cmd
, unsigned int flags
, int argc
, char **argv
)
1039 struct iplink_req req
= {
1040 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
1041 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
1042 .n
.nlmsg_type
= cmd
,
1043 .i
.ifi_family
= preferred_family
,
1047 ret
= iplink_parse(argc
, argv
, &req
, &type
);
1052 struct link_util
*lu
;
1053 struct rtattr
*linkinfo
;
1054 char *ulinep
= strchr(type
, '_');
1057 linkinfo
= addattr_nest(&req
.n
, sizeof(req
), IFLA_LINKINFO
);
1058 addattr_l(&req
.n
, sizeof(req
), IFLA_INFO_KIND
, type
,
1061 lu
= get_link_kind(type
);
1062 if (ulinep
&& !strcmp(ulinep
, "_slave"))
1063 iflatype
= IFLA_INFO_SLAVE_DATA
;
1065 iflatype
= IFLA_INFO_DATA
;
1071 struct rtattr
*data
;
1073 data
= addattr_nest(&req
.n
, sizeof(req
), iflatype
);
1075 if (lu
->parse_opt
&&
1076 lu
->parse_opt(lu
, argc
, argv
, &req
.n
))
1079 addattr_nest_end(&req
.n
, data
);
1081 if (matches(*argv
, "help") == 0)
1084 "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
1088 addattr_nest_end(&req
.n
, linkinfo
);
1089 } else if (flags
& NLM_F_CREATE
) {
1091 "Not enough information: \"type\" argument is required\n");
1095 if (rtnl_talk(&rth
, &req
.n
, NULL
) < 0)
1098 /* remove device from cache; next use can refresh with new data */
1099 ll_drop_by_index(req
.i
.ifi_index
);
1104 int iplink_get(char *name
, __u32 filt_mask
)
1106 struct iplink_req req
= {
1107 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
1108 .n
.nlmsg_flags
= NLM_F_REQUEST
,
1109 .n
.nlmsg_type
= RTM_GETLINK
,
1110 .i
.ifi_family
= preferred_family
,
1112 struct nlmsghdr
*answer
;
1115 addattr_l(&req
.n
, sizeof(req
),
1116 !check_ifname(name
) ? IFLA_IFNAME
: IFLA_ALT_IFNAME
,
1117 name
, strlen(name
) + 1);
1119 addattr32(&req
.n
, sizeof(req
), IFLA_EXT_MASK
, filt_mask
);
1121 if (rtnl_talk(&rth
, &req
.n
, &answer
) < 0)
1124 open_json_object(NULL
);
1125 print_linkinfo(answer
, stdout
);
1126 close_json_object();
1132 #if IPLINK_IOCTL_COMPAT
1133 static int get_ctl_fd(void)
1138 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
1142 fd
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
1145 fd
= socket(PF_INET6
, SOCK_DGRAM
, 0);
1149 perror("Cannot create control socket");
1153 static int do_chflags(const char *dev
, __u32 flags
, __u32 mask
)
1159 strlcpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1163 err
= ioctl(fd
, SIOCGIFFLAGS
, &ifr
);
1165 perror("SIOCGIFFLAGS");
1169 if ((ifr
.ifr_flags
^flags
)&mask
) {
1170 ifr
.ifr_flags
&= ~mask
;
1171 ifr
.ifr_flags
|= mask
&flags
;
1172 err
= ioctl(fd
, SIOCSIFFLAGS
, &ifr
);
1174 perror("SIOCSIFFLAGS");
1180 static int do_changename(const char *dev
, const char *newdev
)
1186 strlcpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1187 strlcpy(ifr
.ifr_newname
, newdev
, IFNAMSIZ
);
1191 err
= ioctl(fd
, SIOCSIFNAME
, &ifr
);
1193 perror("SIOCSIFNAME");
1201 static int set_qlen(const char *dev
, int qlen
)
1203 struct ifreq ifr
= { .ifr_qlen
= qlen
};
1210 strlcpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1211 if (ioctl(s
, SIOCSIFTXQLEN
, &ifr
) < 0) {
1212 perror("SIOCSIFXQLEN");
1221 static int set_mtu(const char *dev
, int mtu
)
1223 struct ifreq ifr
= { .ifr_mtu
= mtu
};
1230 strlcpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1231 if (ioctl(s
, SIOCSIFMTU
, &ifr
) < 0) {
1232 perror("SIOCSIFMTU");
1241 static int get_address(const char *dev
, int *htype
)
1243 struct ifreq ifr
= {};
1244 struct sockaddr_ll me
= {
1245 .sll_family
= AF_PACKET
,
1246 .sll_protocol
= htons(ETH_P_LOOP
),
1251 s
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
1253 perror("socket(PF_PACKET)");
1257 strlcpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1258 if (ioctl(s
, SIOCGIFINDEX
, &ifr
) < 0) {
1259 perror("SIOCGIFINDEX");
1264 me
.sll_ifindex
= ifr
.ifr_ifindex
;
1265 if (bind(s
, (struct sockaddr
*)&me
, sizeof(me
)) == -1) {
1272 if (getsockname(s
, (struct sockaddr
*)&me
, &alen
) == -1) {
1273 perror("getsockname");
1278 *htype
= me
.sll_hatype
;
1279 return me
.sll_halen
;
1282 static int parse_address(const char *dev
, int hatype
, int halen
,
1283 char *lla
, struct ifreq
*ifr
)
1287 memset(ifr
, 0, sizeof(*ifr
));
1288 strlcpy(ifr
->ifr_name
, dev
, IFNAMSIZ
);
1289 ifr
->ifr_hwaddr
.sa_family
= hatype
;
1290 alen
= ll_addr_a2n(ifr
->ifr_hwaddr
.sa_data
, 14, lla
);
1293 if (alen
!= halen
) {
1295 "Wrong address (%s) length: expected %d bytes\n",
1302 static int set_address(struct ifreq
*ifr
, int brd
)
1309 if (ioctl(s
, brd
?SIOCSIFHWBROADCAST
:SIOCSIFHWADDR
, ifr
) < 0) {
1310 perror(brd
?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
1318 static int do_set(int argc
, char **argv
)
1325 char *newaddr
= NULL
;
1326 char *newbrd
= NULL
;
1327 struct ifreq ifr0
, ifr1
;
1328 char *newname
= NULL
;
1332 if (strcmp(*argv
, "up") == 0) {
1335 } else if (strcmp(*argv
, "down") == 0) {
1338 } else if (strcmp(*argv
, "name") == 0) {
1340 if (check_ifname(*argv
))
1341 invarg("\"name\" not a valid ifname", *argv
);
1343 } else if (matches(*argv
, "address") == 0) {
1346 } else if (matches(*argv
, "broadcast") == 0 ||
1347 strcmp(*argv
, "brd") == 0) {
1350 } else if (matches(*argv
, "txqueuelen") == 0 ||
1351 strcmp(*argv
, "qlen") == 0 ||
1352 matches(*argv
, "txqlen") == 0) {
1355 duparg("txqueuelen", *argv
);
1356 if (get_integer(&qlen
, *argv
, 0))
1357 invarg("Invalid \"txqueuelen\" value\n", *argv
);
1358 } else if (strcmp(*argv
, "mtu") == 0) {
1361 duparg("mtu", *argv
);
1362 if (get_integer(&mtu
, *argv
, 0))
1363 invarg("Invalid \"mtu\" value\n", *argv
);
1364 } else if (strcmp(*argv
, "multicast") == 0) {
1366 mask
|= IFF_MULTICAST
;
1368 if (strcmp(*argv
, "on") == 0)
1369 flags
|= IFF_MULTICAST
;
1370 else if (strcmp(*argv
, "off") == 0)
1371 flags
&= ~IFF_MULTICAST
;
1373 return on_off("multicast", *argv
);
1374 } else if (strcmp(*argv
, "allmulticast") == 0) {
1376 mask
|= IFF_ALLMULTI
;
1378 if (strcmp(*argv
, "on") == 0)
1379 flags
|= IFF_ALLMULTI
;
1380 else if (strcmp(*argv
, "off") == 0)
1381 flags
&= ~IFF_ALLMULTI
;
1383 return on_off("allmulticast", *argv
);
1384 } else if (strcmp(*argv
, "promisc") == 0) {
1386 mask
|= IFF_PROMISC
;
1388 if (strcmp(*argv
, "on") == 0)
1389 flags
|= IFF_PROMISC
;
1390 else if (strcmp(*argv
, "off") == 0)
1391 flags
&= ~IFF_PROMISC
;
1393 return on_off("promisc", *argv
);
1394 } else if (strcmp(*argv
, "trailers") == 0) {
1396 mask
|= IFF_NOTRAILERS
;
1398 if (strcmp(*argv
, "off") == 0)
1399 flags
|= IFF_NOTRAILERS
;
1400 else if (strcmp(*argv
, "on") == 0)
1401 flags
&= ~IFF_NOTRAILERS
;
1403 return on_off("trailers", *argv
);
1404 } else if (strcmp(*argv
, "arp") == 0) {
1408 if (strcmp(*argv
, "on") == 0)
1409 flags
&= ~IFF_NOARP
;
1410 else if (strcmp(*argv
, "off") == 0)
1413 return on_off("arp", *argv
);
1414 } else if (matches(*argv
, "dynamic") == 0) {
1416 mask
|= IFF_DYNAMIC
;
1418 if (strcmp(*argv
, "on") == 0)
1419 flags
|= IFF_DYNAMIC
;
1420 else if (strcmp(*argv
, "off") == 0)
1421 flags
&= ~IFF_DYNAMIC
;
1423 return on_off("dynamic", *argv
);
1425 if (strcmp(*argv
, "dev") == 0)
1427 else if (matches(*argv
, "help") == 0)
1431 duparg2("dev", *argv
);
1432 if (check_ifname(*argv
))
1433 invarg("\"dev\" not a valid ifname", *argv
);
1441 "Not enough of information: \"dev\" argument is required.\n");
1445 if (newaddr
|| newbrd
) {
1446 halen
= get_address(dev
, &htype
);
1450 if (parse_address(dev
, htype
, halen
,
1451 newaddr
, &ifr0
) < 0)
1455 if (parse_address(dev
, htype
, halen
,
1461 if (newname
&& strcmp(dev
, newname
)) {
1462 if (do_changename(dev
, newname
) < 0)
1467 if (set_qlen(dev
, qlen
) < 0)
1471 if (set_mtu(dev
, mtu
) < 0)
1474 if (newaddr
|| newbrd
) {
1476 if (set_address(&ifr1
, 1) < 0)
1480 if (set_address(&ifr0
, 0) < 0)
1485 return do_chflags(dev
, flags
, mask
);
1488 #endif /* IPLINK_IOCTL_COMPAT */
1490 static void print_mpls_stats(FILE *fp
, struct rtattr
*attr
)
1492 struct rtattr
*mrtb
[MPLS_STATS_MAX
+1];
1493 struct mpls_link_stats
*stats
;
1495 parse_rtattr(mrtb
, MPLS_STATS_MAX
, RTA_DATA(attr
),
1497 if (!mrtb
[MPLS_STATS_LINK
])
1500 stats
= RTA_DATA(mrtb
[MPLS_STATS_LINK
]);
1502 fprintf(fp
, " mpls:\n");
1503 fprintf(fp
, " RX: bytes packets errors dropped noroute\n");
1505 print_num(fp
, 10, stats
->rx_bytes
);
1506 print_num(fp
, 8, stats
->rx_packets
);
1507 print_num(fp
, 7, stats
->rx_errors
);
1508 print_num(fp
, 8, stats
->rx_dropped
);
1509 print_num(fp
, 7, stats
->rx_noroute
);
1511 fprintf(fp
, " TX: bytes packets errors dropped\n");
1513 print_num(fp
, 10, stats
->tx_bytes
);
1514 print_num(fp
, 8, stats
->tx_packets
);
1515 print_num(fp
, 7, stats
->tx_errors
);
1516 print_num(fp
, 7, stats
->tx_dropped
);
1520 static void print_af_stats_attr(FILE *fp
, int ifindex
, struct rtattr
*attr
)
1522 bool if_printed
= false;
1526 rem
= RTA_PAYLOAD(attr
);
1527 for (i
= RTA_DATA(attr
); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
)) {
1528 if (preferred_family
!= AF_UNSPEC
&&
1529 i
->rta_type
!= preferred_family
)
1533 fprintf(fp
, "%u: %s\n", ifindex
,
1534 ll_index_to_name(ifindex
));
1538 switch (i
->rta_type
) {
1540 print_mpls_stats(fp
, i
);
1543 fprintf(fp
, " unknown af(%d)\n", i
->rta_type
);
1549 struct af_stats_ctx
{
1554 static int print_af_stats(struct nlmsghdr
*n
, void *arg
)
1556 struct if_stats_msg
*ifsm
= NLMSG_DATA(n
);
1557 struct rtattr
*tb
[IFLA_STATS_MAX
+1];
1558 int len
= n
->nlmsg_len
;
1559 struct af_stats_ctx
*ctx
= arg
;
1562 len
-= NLMSG_LENGTH(sizeof(*ifsm
));
1564 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
1568 if (ctx
->ifindex
&& ifsm
->ifindex
!= ctx
->ifindex
)
1571 parse_rtattr(tb
, IFLA_STATS_MAX
, IFLA_STATS_RTA(ifsm
), len
);
1573 if (tb
[IFLA_STATS_AF_SPEC
])
1574 print_af_stats_attr(fp
, ifsm
->ifindex
, tb
[IFLA_STATS_AF_SPEC
]);
1580 static int iplink_afstats(int argc
, char **argv
)
1582 __u32 filt_mask
= IFLA_STATS_FILTER_BIT(IFLA_STATS_AF_SPEC
);
1583 const char *filter_dev
= NULL
;
1584 struct af_stats_ctx ctx
= {
1590 if (strcmp(*argv
, "dev") == 0) {
1593 duparg2("dev", *argv
);
1595 } else if (matches(*argv
, "help") == 0) {
1599 "Command \"%s\" is unknown, try \"ip link help\".\n",
1608 ctx
.ifindex
= ll_name_to_index(filter_dev
);
1609 if (ctx
.ifindex
<= 0) {
1611 "Device \"%s\" does not exist.\n",
1617 if (rtnl_statsdump_req_filter(&rth
, AF_UNSPEC
, filt_mask
) < 0) {
1618 perror("Cannont send dump request");
1622 if (rtnl_dump_filter(&rth
, print_af_stats
, &ctx
) < 0) {
1623 fprintf(stderr
, "Dump terminated\n");
1630 static int iplink_prop_mod(int argc
, char **argv
, struct iplink_req
*req
)
1632 struct rtattr
*proplist
;
1636 proplist
= addattr_nest(&req
->n
, sizeof(*req
),
1637 IFLA_PROP_LIST
| NLA_F_NESTED
);
1640 if (matches(*argv
, "altname") == 0) {
1642 if (check_altifname(*argv
))
1643 invarg("not a valid altname", *argv
);
1645 addattr_l(&req
->n
, sizeof(*req
), IFLA_ALT_IFNAME
,
1646 name
, strlen(name
) + 1);
1647 } else if (matches(*argv
, "help") == 0) {
1650 if (strcmp(*argv
, "dev") == 0)
1653 duparg2("dev", *argv
);
1654 if (check_altifname(*argv
))
1655 invarg("\"dev\" not a valid ifname", *argv
);
1660 addattr_nest_end(&req
->n
, proplist
);
1663 fprintf(stderr
, "Not enough of information: \"dev\" argument is required.\n");
1667 req
->i
.ifi_index
= ll_name_to_index(dev
);
1668 if (!req
->i
.ifi_index
)
1671 if (rtnl_talk(&rth
, &req
->n
, NULL
) < 0)
1677 static int iplink_prop(int argc
, char **argv
)
1679 struct iplink_req req
= {
1680 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
1681 .n
.nlmsg_flags
= NLM_F_REQUEST
,
1682 .i
.ifi_family
= preferred_family
,
1690 if (matches(*argv
, "add") == 0) {
1691 req
.n
.nlmsg_flags
|= NLM_F_EXCL
| NLM_F_CREATE
| NLM_F_APPEND
;
1692 req
.n
.nlmsg_type
= RTM_NEWLINKPROP
;
1693 } else if (matches(*argv
, "del") == 0) {
1694 req
.n
.nlmsg_type
= RTM_DELLINKPROP
;
1695 } else if (matches(*argv
, "help") == 0) {
1698 fprintf(stderr
, "Operator required\n");
1701 return iplink_prop_mod(argc
- 1, argv
+ 1, &req
);
1704 static void do_help(int argc
, char **argv
)
1706 struct link_util
*lu
= NULL
;
1713 lu
= get_link_kind(*argv
);
1714 if (lu
&& lu
->print_help
)
1715 lu
->print_help(lu
, argc
-1, argv
+1, stdout
);
1720 int do_iplink(int argc
, char **argv
)
1723 return ipaddr_list_link(0, NULL
);
1725 if (iplink_have_newlink()) {
1726 if (matches(*argv
, "add") == 0)
1727 return iplink_modify(RTM_NEWLINK
,
1728 NLM_F_CREATE
|NLM_F_EXCL
,
1730 if (matches(*argv
, "set") == 0 ||
1731 matches(*argv
, "change") == 0)
1732 return iplink_modify(RTM_NEWLINK
, 0,
1734 if (matches(*argv
, "replace") == 0)
1735 return iplink_modify(RTM_NEWLINK
,
1736 NLM_F_CREATE
|NLM_F_REPLACE
,
1738 if (matches(*argv
, "delete") == 0)
1739 return iplink_modify(RTM_DELLINK
, 0,
1742 #if IPLINK_IOCTL_COMPAT
1743 if (matches(*argv
, "set") == 0)
1744 return do_set(argc
-1, argv
+1);
1748 if (matches(*argv
, "show") == 0 ||
1749 matches(*argv
, "lst") == 0 ||
1750 matches(*argv
, "list") == 0)
1751 return ipaddr_list_link(argc
-1, argv
+1);
1753 if (matches(*argv
, "xstats") == 0)
1754 return iplink_ifla_xstats(argc
-1, argv
+1);
1756 if (matches(*argv
, "afstats") == 0) {
1757 iplink_afstats(argc
-1, argv
+1);
1761 if (matches(*argv
, "property") == 0)
1762 return iplink_prop(argc
-1, argv
+1);
1764 if (matches(*argv
, "help") == 0) {
1765 do_help(argc
-1, argv
+1);
1769 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip link help\".\n",