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>
34 #include "ip_common.h"
35 #include "namespace.h"
37 #define IPLINK_IOCTL_COMPAT 1
39 #define LIBDIR "/usr/lib"
42 static void usage(void) __attribute__((noreturn
));
43 static int iplink_have_newlink(void);
45 void iplink_usage(void)
47 if (iplink_have_newlink()) {
48 fprintf(stderr
, "Usage: ip link add [link DEV] [ name ] NAME\n");
49 fprintf(stderr
, " [ txqueuelen PACKETS ]\n");
50 fprintf(stderr
, " [ address LLADDR ]\n");
51 fprintf(stderr
, " [ broadcast LLADDR ]\n");
52 fprintf(stderr
, " [ mtu MTU ] [index IDX ]\n");
53 fprintf(stderr
, " [ numtxqueues QUEUE_COUNT ]\n");
54 fprintf(stderr
, " [ numrxqueues QUEUE_COUNT ]\n");
55 fprintf(stderr
, " type TYPE [ ARGS ]\n");
56 fprintf(stderr
, " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n");
57 fprintf(stderr
, "\n");
58 fprintf(stderr
, " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n");
59 fprintf(stderr
, " [ { up | down } ]\n");
60 fprintf(stderr
, " [ type TYPE ARGS ]\n");
62 fprintf(stderr
, "Usage: ip link set DEVICE [ { up | down } ]\n");
64 fprintf(stderr
, " [ arp { on | off } ]\n");
65 fprintf(stderr
, " [ dynamic { on | off } ]\n");
66 fprintf(stderr
, " [ multicast { on | off } ]\n");
67 fprintf(stderr
, " [ allmulticast { on | off } ]\n");
68 fprintf(stderr
, " [ promisc { on | off } ]\n");
69 fprintf(stderr
, " [ trailers { on | off } ]\n");
70 fprintf(stderr
, " [ txqueuelen PACKETS ]\n");
71 fprintf(stderr
, " [ name NEWNAME ]\n");
72 fprintf(stderr
, " [ address LLADDR ]\n");
73 fprintf(stderr
, " [ broadcast LLADDR ]\n");
74 fprintf(stderr
, " [ mtu MTU ]\n");
75 fprintf(stderr
, " [ netns { PID | NAME } ]\n");
76 fprintf(stderr
, " [ link-netnsid ID ]\n");
77 fprintf(stderr
, " [ alias NAME ]\n");
78 fprintf(stderr
, " [ vf NUM [ mac LLADDR ]\n");
79 fprintf(stderr
, " [ vlan VLANID [ qos VLAN-QOS ] ]\n");
81 fprintf(stderr
, " [ rate TXRATE ]\n");
83 fprintf(stderr
, " [ spoofchk { on | off} ]\n");
84 fprintf(stderr
, " [ query_rss { on | off} ]\n");
85 fprintf(stderr
, " [ state { auto | enable | disable} ] ]\n");
86 fprintf(stderr
, " [ trust { on | off} ] ]\n");
87 fprintf(stderr
, " [ master DEVICE ][ vrf NAME ]\n");
88 fprintf(stderr
, " [ nomaster ]\n");
89 fprintf(stderr
, " [ addrgenmode { eui64 | none | stable_secret | random } ]\n");
90 fprintf(stderr
, " [ protodown { on | off } ]\n");
91 fprintf(stderr
, " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n");
93 if (iplink_have_newlink()) {
94 fprintf(stderr
, " ip link help [ TYPE ]\n");
95 fprintf(stderr
, "\n");
96 fprintf(stderr
, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
97 fprintf(stderr
, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n");
98 fprintf(stderr
, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n");
99 fprintf(stderr
, " bond_slave | ipvlan | geneve | bridge_slave | vrf }\n");
104 static void usage(void)
109 static int on_off(const char *msg
, const char *realval
)
112 "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
117 static void *BODY
; /* cached dlopen(NULL) handle */
118 static struct link_util
*linkutil_list
;
120 static struct link_util
*__get_link_kind(const char *id
, bool slave
)
126 for (l
= linkutil_list
; l
; l
= l
->next
)
127 if (strcmp(l
->id
, id
) == 0 &&
131 snprintf(buf
, sizeof(buf
), LIBDIR
"/ip/link_%s.so", id
);
132 dlh
= dlopen(buf
, RTLD_LAZY
);
134 /* look in current binary, only open once */
137 dlh
= BODY
= dlopen(NULL
, RTLD_LAZY
);
144 snprintf(buf
, sizeof(buf
), "%s_slave_link_util", id
);
146 snprintf(buf
, sizeof(buf
), "%s_link_util", id
);
151 l
->next
= linkutil_list
;
156 struct link_util
*get_link_kind(const char *id
)
158 return __get_link_kind(id
, false);
161 struct link_util
*get_link_slave_kind(const char *id
)
163 return __get_link_kind(id
, true);
166 static int get_link_mode(const char *mode
)
168 if (strcasecmp(mode
, "default") == 0)
169 return IF_LINK_MODE_DEFAULT
;
170 if (strcasecmp(mode
, "dormant") == 0)
171 return IF_LINK_MODE_DORMANT
;
175 static int get_addr_gen_mode(const char *mode
)
177 if (strcasecmp(mode
, "eui64") == 0)
178 return IN6_ADDR_GEN_MODE_EUI64
;
179 if (strcasecmp(mode
, "none") == 0)
180 return IN6_ADDR_GEN_MODE_NONE
;
181 if (strcasecmp(mode
, "stable_secret") == 0)
182 return IN6_ADDR_GEN_MODE_STABLE_PRIVACY
;
183 if (strcasecmp(mode
, "random") == 0)
184 return IN6_ADDR_GEN_MODE_RANDOM
;
188 #if IPLINK_IOCTL_COMPAT
189 static int have_rtnl_newlink
= -1;
191 static int accept_msg(const struct sockaddr_nl
*who
,
192 struct rtnl_ctrl_data
*ctrl
,
193 struct nlmsghdr
*n
, void *arg
)
195 struct nlmsgerr
*err
= (struct nlmsgerr
*)NLMSG_DATA(n
);
197 if (n
->nlmsg_type
== NLMSG_ERROR
&&
198 (err
->error
== -EOPNOTSUPP
|| err
->error
== -EINVAL
))
199 have_rtnl_newlink
= 0;
201 have_rtnl_newlink
= 1;
205 static int iplink_have_newlink(void)
212 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
213 .n
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
,
214 .n
.nlmsg_type
= RTM_NEWLINK
,
215 .i
.ifi_family
= AF_UNSPEC
,
218 if (have_rtnl_newlink
< 0) {
219 if (rtnl_send(&rth
, &req
.n
, req
.n
.nlmsg_len
) < 0) {
220 perror("request send failed");
223 rtnl_listen(&rth
, accept_msg
, NULL
);
225 return have_rtnl_newlink
;
227 #else /* IPLINK_IOCTL_COMPAT */
228 static int iplink_have_newlink(void)
232 #endif /* ! IPLINK_IOCTL_COMPAT */
240 static int nl_get_ll_addr_len(unsigned int dev_index
)
243 struct iplink_req req
= {
245 .nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
246 .nlmsg_type
= RTM_GETLINK
,
247 .nlmsg_flags
= NLM_F_REQUEST
250 .ifi_family
= preferred_family
,
251 .ifi_index
= dev_index
,
254 struct rtattr
*tb
[IFLA_MAX
+1];
256 if (rtnl_talk(&rth
, &req
.n
, &req
.n
, sizeof(req
)) < 0)
259 len
= req
.n
.nlmsg_len
- NLMSG_LENGTH(sizeof(req
.i
));
263 parse_rtattr_flags(tb
, IFLA_MAX
, IFLA_RTA(&req
.i
), len
, NLA_F_NESTED
);
264 if (!tb
[IFLA_ADDRESS
])
267 return RTA_PAYLOAD(tb
[IFLA_ADDRESS
]);
270 static int iplink_parse_vf(int vf
, int *argcp
, char ***argvp
,
271 struct iplink_req
*req
, int dev_index
)
273 char new_rate_api
= 0, count
= 0, override_legacy_rate
= 0;
274 struct ifla_vf_rate tivt
;
275 int len
, argc
= *argcp
;
276 char **argv
= *argvp
;
277 struct rtattr
*vfinfo
;
279 tivt
.min_tx_rate
= -1;
280 tivt
.max_tx_rate
= -1;
282 vfinfo
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_VF_INFO
);
284 while (NEXT_ARG_OK()) {
287 if (!matches(*argv
, "max_tx_rate")) {
290 /* override legacy rate */
291 override_legacy_rate
= 1;
292 } else if (!matches(*argv
, "min_tx_rate")) {
303 while (NEXT_ARG_OK()) {
305 if (matches(*argv
, "mac") == 0) {
306 struct ifla_vf_mac ivm
= { 0 };
307 int halen
= nl_get_ll_addr_len(dev_index
);
311 len
= ll_addr_a2n((char *)ivm
.mac
, 32, *argv
);
314 if (halen
> 0 && len
!= halen
) {
316 "Invalid address length %d - must be %d bytes\n",
320 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_MAC
,
322 } else if (matches(*argv
, "vlan") == 0) {
323 struct ifla_vf_vlan ivv
;
326 if (get_unsigned(&ivv
.vlan
, *argv
, 0))
327 invarg("Invalid \"vlan\" value\n", *argv
);
333 if (matches(*argv
, "qos") == 0) {
335 if (get_unsigned(&ivv
.qos
, *argv
, 0))
336 invarg("Invalid \"qos\" value\n", *argv
);
342 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_VLAN
,
344 } else if (matches(*argv
, "rate") == 0) {
345 struct ifla_vf_tx_rate ivt
;
348 if (get_unsigned(&ivt
.rate
, *argv
, 0))
349 invarg("Invalid \"rate\" value\n", *argv
);
353 addattr_l(&req
->n
, sizeof(*req
),
354 IFLA_VF_TX_RATE
, &ivt
, sizeof(ivt
));
355 else if (!override_legacy_rate
)
356 tivt
.max_tx_rate
= ivt
.rate
;
358 } else if (matches(*argv
, "max_tx_rate") == 0) {
360 if (get_unsigned(&tivt
.max_tx_rate
, *argv
, 0))
361 invarg("Invalid \"max tx rate\" value\n",
365 } else if (matches(*argv
, "min_tx_rate") == 0) {
367 if (get_unsigned(&tivt
.min_tx_rate
, *argv
, 0))
368 invarg("Invalid \"min tx rate\" value\n",
372 } else if (matches(*argv
, "spoofchk") == 0) {
373 struct ifla_vf_spoofchk ivs
;
376 if (matches(*argv
, "on") == 0)
378 else if (matches(*argv
, "off") == 0)
381 return on_off("spoofchk", *argv
);
383 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_SPOOFCHK
,
386 } else if (matches(*argv
, "query_rss") == 0) {
387 struct ifla_vf_rss_query_en ivs
;
390 if (matches(*argv
, "on") == 0)
392 else if (matches(*argv
, "off") == 0)
395 return on_off("query_rss", *argv
);
397 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RSS_QUERY_EN
,
400 } else if (matches(*argv
, "trust") == 0) {
401 struct ifla_vf_trust ivt
;
404 if (matches(*argv
, "on") == 0)
406 else if (matches(*argv
, "off") == 0)
409 invarg("Invalid \"trust\" value\n", *argv
);
411 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_TRUST
,
414 } else if (matches(*argv
, "state") == 0) {
415 struct ifla_vf_link_state ivl
;
418 if (matches(*argv
, "auto") == 0)
419 ivl
.link_state
= IFLA_VF_LINK_STATE_AUTO
;
420 else if (matches(*argv
, "enable") == 0)
421 ivl
.link_state
= IFLA_VF_LINK_STATE_ENABLE
;
422 else if (matches(*argv
, "disable") == 0)
423 ivl
.link_state
= IFLA_VF_LINK_STATE_DISABLE
;
425 invarg("Invalid \"state\" value\n", *argv
);
427 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_LINK_STATE
,
429 } else if (matches(*argv
, "node_guid") == 0) {
430 struct ifla_vf_guid ivg
;
434 if (get_guid(&ivg
.guid
, *argv
)) {
435 invarg("Invalid GUID format\n", *argv
);
438 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_NODE_GUID
,
440 } else if (matches(*argv
, "port_guid") == 0) {
441 struct ifla_vf_guid ivg
;
445 if (get_guid(&ivg
.guid
, *argv
)) {
446 invarg("Invalid GUID format\n", *argv
);
449 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_IB_PORT_GUID
,
461 if (tivt
.min_tx_rate
== -1 || tivt
.max_tx_rate
== -1) {
462 ipaddr_get_vf_rate(tivt
.vf
, &tmin
, &tmax
, dev_index
);
463 if (tivt
.min_tx_rate
== -1)
464 tivt
.min_tx_rate
= tmin
;
465 if (tivt
.max_tx_rate
== -1)
466 tivt
.max_tx_rate
= tmax
;
468 addattr_l(&req
->n
, sizeof(*req
), IFLA_VF_RATE
, &tivt
,
473 incomplete_command();
475 addattr_nest_end(&req
->n
, vfinfo
);
482 int iplink_parse(int argc
, char **argv
, struct iplink_req
*req
,
483 char **name
, char **type
, char **link
, char **dev
,
484 int *group
, int *index
)
492 int numtxqueues
= -1;
493 int numrxqueues
= -1;
495 int link_netnsid
= -1;
502 if (strcmp(*argv
, "up") == 0) {
503 req
->i
.ifi_change
|= IFF_UP
;
504 req
->i
.ifi_flags
|= IFF_UP
;
505 } else if (strcmp(*argv
, "down") == 0) {
506 req
->i
.ifi_change
|= IFF_UP
;
507 req
->i
.ifi_flags
&= ~IFF_UP
;
508 } else if (strcmp(*argv
, "name") == 0) {
511 } else if (strcmp(*argv
, "index") == 0) {
513 *index
= atoi(*argv
);
515 invarg("Invalid \"index\" value", *argv
);
516 } else if (matches(*argv
, "link") == 0) {
519 } else if (matches(*argv
, "address") == 0) {
521 addr_len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
524 addattr_l(&req
->n
, sizeof(*req
), IFLA_ADDRESS
, abuf
, addr_len
);
525 } else if (matches(*argv
, "broadcast") == 0 ||
526 strcmp(*argv
, "brd") == 0) {
528 len
= ll_addr_a2n(abuf
, sizeof(abuf
), *argv
);
531 addattr_l(&req
->n
, sizeof(*req
), IFLA_BROADCAST
, abuf
, len
);
532 } else if (matches(*argv
, "txqueuelen") == 0 ||
533 strcmp(*argv
, "qlen") == 0 ||
534 matches(*argv
, "txqlen") == 0) {
537 duparg("txqueuelen", *argv
);
538 if (get_integer(&qlen
, *argv
, 0))
539 invarg("Invalid \"txqueuelen\" value\n", *argv
);
540 addattr_l(&req
->n
, sizeof(*req
), IFLA_TXQLEN
, &qlen
, 4);
541 } else if (strcmp(*argv
, "mtu") == 0) {
544 duparg("mtu", *argv
);
545 if (get_integer(&mtu
, *argv
, 0))
546 invarg("Invalid \"mtu\" value\n", *argv
);
547 addattr_l(&req
->n
, sizeof(*req
), IFLA_MTU
, &mtu
, 4);
548 } else if (strcmp(*argv
, "netns") == 0) {
551 duparg("netns", *argv
);
552 netns
= netns_get_fd(*argv
);
554 addattr_l(&req
->n
, sizeof(*req
), IFLA_NET_NS_FD
,
556 else if (get_integer(&netns
, *argv
, 0) == 0)
557 addattr_l(&req
->n
, sizeof(*req
), IFLA_NET_NS_PID
,
560 invarg("Invalid \"netns\" value\n", *argv
);
561 } else if (strcmp(*argv
, "multicast") == 0) {
563 req
->i
.ifi_change
|= IFF_MULTICAST
;
565 if (strcmp(*argv
, "on") == 0)
566 req
->i
.ifi_flags
|= IFF_MULTICAST
;
567 else if (strcmp(*argv
, "off") == 0)
568 req
->i
.ifi_flags
&= ~IFF_MULTICAST
;
570 return on_off("multicast", *argv
);
571 } else if (strcmp(*argv
, "allmulticast") == 0) {
573 req
->i
.ifi_change
|= IFF_ALLMULTI
;
575 if (strcmp(*argv
, "on") == 0)
576 req
->i
.ifi_flags
|= IFF_ALLMULTI
;
577 else if (strcmp(*argv
, "off") == 0)
578 req
->i
.ifi_flags
&= ~IFF_ALLMULTI
;
580 return on_off("allmulticast", *argv
);
581 } else if (strcmp(*argv
, "promisc") == 0) {
583 req
->i
.ifi_change
|= IFF_PROMISC
;
585 if (strcmp(*argv
, "on") == 0)
586 req
->i
.ifi_flags
|= IFF_PROMISC
;
587 else if (strcmp(*argv
, "off") == 0)
588 req
->i
.ifi_flags
&= ~IFF_PROMISC
;
590 return on_off("promisc", *argv
);
591 } else if (strcmp(*argv
, "trailers") == 0) {
593 req
->i
.ifi_change
|= IFF_NOTRAILERS
;
595 if (strcmp(*argv
, "off") == 0)
596 req
->i
.ifi_flags
|= IFF_NOTRAILERS
;
597 else if (strcmp(*argv
, "on") == 0)
598 req
->i
.ifi_flags
&= ~IFF_NOTRAILERS
;
600 return on_off("trailers", *argv
);
601 } else if (strcmp(*argv
, "arp") == 0) {
603 req
->i
.ifi_change
|= IFF_NOARP
;
605 if (strcmp(*argv
, "on") == 0)
606 req
->i
.ifi_flags
&= ~IFF_NOARP
;
607 else if (strcmp(*argv
, "off") == 0)
608 req
->i
.ifi_flags
|= IFF_NOARP
;
610 return on_off("arp", *argv
);
611 } else if (strcmp(*argv
, "vf") == 0) {
612 struct rtattr
*vflist
;
615 if (get_integer(&vf
, *argv
, 0))
616 invarg("Invalid \"vf\" value\n", *argv
);
618 vflist
= addattr_nest(&req
->n
, sizeof(*req
),
623 len
= iplink_parse_vf(vf
, &argc
, &argv
, req
, dev_index
);
626 addattr_nest_end(&req
->n
, vflist
);
627 } else if (matches(*argv
, "master") == 0) {
631 ifindex
= ll_name_to_index(*argv
);
633 invarg("Device does not exist\n", *argv
);
634 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
636 } else if (strcmp(*argv
, "vrf") == 0) {
640 ifindex
= ll_name_to_index(*argv
);
642 invarg("Not a valid VRF name\n", *argv
);
643 if (!name_is_vrf(*argv
))
644 invarg("Not a valid VRF name\n", *argv
);
645 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
646 &ifindex
, sizeof(ifindex
));
647 } else if (matches(*argv
, "nomaster") == 0) {
650 addattr_l(&req
->n
, sizeof(*req
), IFLA_MASTER
,
652 } else if (matches(*argv
, "dynamic") == 0) {
654 req
->i
.ifi_change
|= IFF_DYNAMIC
;
656 if (strcmp(*argv
, "on") == 0)
657 req
->i
.ifi_flags
|= IFF_DYNAMIC
;
658 else if (strcmp(*argv
, "off") == 0)
659 req
->i
.ifi_flags
&= ~IFF_DYNAMIC
;
661 return on_off("dynamic", *argv
);
662 } else if (matches(*argv
, "type") == 0) {
667 } else if (matches(*argv
, "alias") == 0) {
669 addattr_l(&req
->n
, sizeof(*req
), IFLA_IFALIAS
,
670 *argv
, strlen(*argv
));
673 } else if (strcmp(*argv
, "group") == 0) {
676 duparg("group", *argv
);
677 if (rtnl_group_a2n(group
, *argv
))
678 invarg("Invalid \"group\" value\n", *argv
);
679 } else if (strcmp(*argv
, "mode") == 0) {
683 mode
= get_link_mode(*argv
);
685 invarg("Invalid link mode\n", *argv
);
686 addattr8(&req
->n
, sizeof(*req
), IFLA_LINKMODE
, mode
);
687 } else if (strcmp(*argv
, "state") == 0) {
691 state
= get_operstate(*argv
);
693 invarg("Invalid operstate\n", *argv
);
695 addattr8(&req
->n
, sizeof(*req
), IFLA_OPERSTATE
, state
);
696 } else if (matches(*argv
, "numtxqueues") == 0) {
698 if (numtxqueues
!= -1)
699 duparg("numtxqueues", *argv
);
700 if (get_integer(&numtxqueues
, *argv
, 0))
701 invarg("Invalid \"numtxqueues\" value\n", *argv
);
702 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_TX_QUEUES
,
704 } else if (matches(*argv
, "numrxqueues") == 0) {
706 if (numrxqueues
!= -1)
707 duparg("numrxqueues", *argv
);
708 if (get_integer(&numrxqueues
, *argv
, 0))
709 invarg("Invalid \"numrxqueues\" value\n", *argv
);
710 addattr_l(&req
->n
, sizeof(*req
), IFLA_NUM_RX_QUEUES
,
712 } else if (matches(*argv
, "addrgenmode") == 0) {
713 struct rtattr
*afs
, *afs6
;
717 mode
= get_addr_gen_mode(*argv
);
719 invarg("Invalid address generation mode\n", *argv
);
720 afs
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_AF_SPEC
);
721 afs6
= addattr_nest(&req
->n
, sizeof(*req
), AF_INET6
);
722 addattr8(&req
->n
, sizeof(*req
),
723 IFLA_INET6_ADDR_GEN_MODE
, mode
);
724 addattr_nest_end(&req
->n
, afs6
);
725 addattr_nest_end(&req
->n
, afs
);
726 } else if (matches(*argv
, "link-netnsid") == 0) {
728 if (link_netnsid
!= -1)
729 duparg("link-netnsid", *argv
);
730 if (get_integer(&link_netnsid
, *argv
, 0))
731 invarg("Invalid \"link-netnsid\" value\n", *argv
);
732 addattr32(&req
->n
, sizeof(*req
), IFLA_LINK_NETNSID
,
734 } else if (strcmp(*argv
, "protodown") == 0) {
735 unsigned int proto_down
;
738 if (strcmp(*argv
, "on") == 0)
740 else if (strcmp(*argv
, "off") == 0)
743 return on_off("protodown", *argv
);
744 addattr8(&req
->n
, sizeof(*req
), IFLA_PROTO_DOWN
,
747 if (matches(*argv
, "help") == 0)
750 if (strcmp(*argv
, "dev") == 0)
753 duparg2("dev", *argv
);
755 dev_index
= ll_name_to_index(*dev
);
760 if (dev_index
&& addr_len
) {
761 int halen
= nl_get_ll_addr_len(dev_index
);
763 if (halen
>= 0 && halen
!= addr_len
) {
765 "Invalid address length %d - must be %d bytes\n",
774 static int iplink_modify(int cmd
, unsigned int flags
, int argc
, char **argv
)
783 struct link_util
*lu
= NULL
;
784 struct iplink_req req
= {
785 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
786 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
788 .i
.ifi_family
= preferred_family
,
792 ret
= iplink_parse(argc
, argv
,
793 &req
, &name
, &type
, &link
, &dev
, &group
, &index
);
802 addattr_l(&req
.n
, sizeof(req
), IFLA_GROUP
,
803 &group
, sizeof(group
));
806 fprintf(stderr
, "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
810 if (flags
& NLM_F_CREATE
) {
811 fprintf(stderr
, "group cannot be used when creating devices.\n");
816 addattr32(&req
.n
, sizeof(req
), IFLA_GROUP
, group
);
817 if (rtnl_talk(&rth
, &req
.n
, NULL
, 0) < 0)
823 if (!(flags
& NLM_F_CREATE
)) {
825 fprintf(stderr
, "Not enough information: \"dev\" argument is required.\n");
828 if (cmd
== RTM_NEWLINK
&& index
!= -1) {
829 fprintf(stderr
, "index can be used only when creating devices.\n");
833 req
.i
.ifi_index
= ll_name_to_index(dev
);
834 if (req
.i
.ifi_index
== 0) {
835 fprintf(stderr
, "Cannot find device \"%s\"\n", dev
);
839 /* Allow "ip link add dev" and "ip link add name" */
846 ifindex
= ll_name_to_index(link
);
848 fprintf(stderr
, "Cannot find device \"%s\"\n",
852 addattr_l(&req
.n
, sizeof(req
), IFLA_LINK
, &ifindex
, 4);
858 req
.i
.ifi_index
= index
;
862 len
= strlen(name
) + 1;
864 invarg("\"\" is not a valid device identifier\n",
867 invarg("\"name\" too long\n", name
);
868 addattr_l(&req
.n
, sizeof(req
), IFLA_IFNAME
, name
, len
);
872 struct rtattr
*linkinfo
;
873 char slavebuf
[128], *ulinep
= strchr(type
, '_');
876 linkinfo
= addattr_nest(&req
.n
, sizeof(req
), IFLA_LINKINFO
);
877 addattr_l(&req
.n
, sizeof(req
), IFLA_INFO_KIND
, type
,
880 if (ulinep
&& !strcmp(ulinep
, "_slave")) {
881 strncpy(slavebuf
, type
, sizeof(slavebuf
));
882 slavebuf
[sizeof(slavebuf
) - 1] = '\0';
883 ulinep
= strchr(slavebuf
, '_');
884 /* check in case it was after sizeof(slavebuf) - 1*/
887 lu
= get_link_slave_kind(slavebuf
);
888 iflatype
= IFLA_INFO_SLAVE_DATA
;
890 lu
= get_link_kind(type
);
891 iflatype
= IFLA_INFO_DATA
;
894 struct rtattr
*data
= addattr_nest(&req
.n
,
895 sizeof(req
), iflatype
);
898 lu
->parse_opt(lu
, argc
, argv
, &req
.n
))
901 addattr_nest_end(&req
.n
, data
);
903 if (matches(*argv
, "help") == 0)
905 fprintf(stderr
, "Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
909 addattr_nest_end(&req
.n
, linkinfo
);
910 } else if (flags
& NLM_F_CREATE
) {
911 fprintf(stderr
, "Not enough information: \"type\" argument is required\n");
915 if (rtnl_talk(&rth
, &req
.n
, NULL
, 0) < 0)
921 int iplink_get(unsigned int flags
, char *name
, __u32 filt_mask
)
924 struct iplink_req req
= {
925 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
)),
926 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
927 .n
.nlmsg_type
= RTM_GETLINK
,
928 .i
.ifi_family
= preferred_family
,
936 len
= strlen(name
) + 1;
938 invarg("\"\" is not a valid device identifier\n",
941 invarg("\"name\" too long\n", name
);
942 addattr_l(&req
.n
, sizeof(req
), IFLA_IFNAME
, name
, len
);
944 addattr32(&req
.n
, sizeof(req
), IFLA_EXT_MASK
, filt_mask
);
946 if (rtnl_talk(&rth
, &req
.n
, &answer
.n
, sizeof(answer
)) < 0)
950 print_linkinfo_brief(NULL
, &answer
.n
, stdout
);
952 print_linkinfo(NULL
, &answer
.n
, stdout
);
957 #if IPLINK_IOCTL_COMPAT
958 static int get_ctl_fd(void)
963 fd
= socket(PF_INET
, SOCK_DGRAM
, 0);
967 fd
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
970 fd
= socket(PF_INET6
, SOCK_DGRAM
, 0);
974 perror("Cannot create control socket");
978 static int do_chflags(const char *dev
, __u32 flags
, __u32 mask
)
984 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
988 err
= ioctl(fd
, SIOCGIFFLAGS
, &ifr
);
990 perror("SIOCGIFFLAGS");
994 if ((ifr
.ifr_flags
^flags
)&mask
) {
995 ifr
.ifr_flags
&= ~mask
;
996 ifr
.ifr_flags
|= mask
&flags
;
997 err
= ioctl(fd
, SIOCSIFFLAGS
, &ifr
);
999 perror("SIOCSIFFLAGS");
1005 static int do_changename(const char *dev
, const char *newdev
)
1011 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1012 strncpy(ifr
.ifr_newname
, newdev
, IFNAMSIZ
);
1016 err
= ioctl(fd
, SIOCSIFNAME
, &ifr
);
1018 perror("SIOCSIFNAME");
1026 static int set_qlen(const char *dev
, int qlen
)
1028 struct ifreq ifr
= { .ifr_qlen
= qlen
};
1035 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1036 if (ioctl(s
, SIOCSIFTXQLEN
, &ifr
) < 0) {
1037 perror("SIOCSIFXQLEN");
1046 static int set_mtu(const char *dev
, int mtu
)
1048 struct ifreq ifr
= { .ifr_mtu
= mtu
};
1055 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1056 if (ioctl(s
, SIOCSIFMTU
, &ifr
) < 0) {
1057 perror("SIOCSIFMTU");
1066 static int get_address(const char *dev
, int *htype
)
1068 struct ifreq ifr
= {};
1069 struct sockaddr_ll me
= {
1070 .sll_family
= AF_PACKET
,
1071 .sll_protocol
= htons(ETH_P_LOOP
),
1076 s
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
1078 perror("socket(PF_PACKET)");
1082 strncpy(ifr
.ifr_name
, dev
, IFNAMSIZ
);
1083 if (ioctl(s
, SIOCGIFINDEX
, &ifr
) < 0) {
1084 perror("SIOCGIFINDEX");
1089 me
.sll_ifindex
= ifr
.ifr_ifindex
;
1090 if (bind(s
, (struct sockaddr
*)&me
, sizeof(me
)) == -1) {
1097 if (getsockname(s
, (struct sockaddr
*)&me
, &alen
) == -1) {
1098 perror("getsockname");
1103 *htype
= me
.sll_hatype
;
1104 return me
.sll_halen
;
1107 static int parse_address(const char *dev
, int hatype
, int halen
,
1108 char *lla
, struct ifreq
*ifr
)
1112 memset(ifr
, 0, sizeof(*ifr
));
1113 strncpy(ifr
->ifr_name
, dev
, IFNAMSIZ
);
1114 ifr
->ifr_hwaddr
.sa_family
= hatype
;
1115 alen
= ll_addr_a2n(ifr
->ifr_hwaddr
.sa_data
, 14, lla
);
1118 if (alen
!= halen
) {
1119 fprintf(stderr
, "Wrong address (%s) length: expected %d bytes\n",
1126 static int set_address(struct ifreq
*ifr
, int brd
)
1133 if (ioctl(s
, brd
?SIOCSIFHWBROADCAST
:SIOCSIFHWADDR
, ifr
) < 0) {
1134 perror(brd
?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
1142 static int do_set(int argc
, char **argv
)
1149 char *newaddr
= NULL
;
1150 char *newbrd
= NULL
;
1151 struct ifreq ifr0
, ifr1
;
1152 char *newname
= NULL
;
1156 if (strcmp(*argv
, "up") == 0) {
1159 } else if (strcmp(*argv
, "down") == 0) {
1162 } else if (strcmp(*argv
, "name") == 0) {
1165 } else if (matches(*argv
, "address") == 0) {
1168 } else if (matches(*argv
, "broadcast") == 0 ||
1169 strcmp(*argv
, "brd") == 0) {
1172 } else if (matches(*argv
, "txqueuelen") == 0 ||
1173 strcmp(*argv
, "qlen") == 0 ||
1174 matches(*argv
, "txqlen") == 0) {
1177 duparg("txqueuelen", *argv
);
1178 if (get_integer(&qlen
, *argv
, 0))
1179 invarg("Invalid \"txqueuelen\" value\n", *argv
);
1180 } else if (strcmp(*argv
, "mtu") == 0) {
1183 duparg("mtu", *argv
);
1184 if (get_integer(&mtu
, *argv
, 0))
1185 invarg("Invalid \"mtu\" value\n", *argv
);
1186 } else if (strcmp(*argv
, "multicast") == 0) {
1188 mask
|= IFF_MULTICAST
;
1190 if (strcmp(*argv
, "on") == 0)
1191 flags
|= IFF_MULTICAST
;
1192 else if (strcmp(*argv
, "off") == 0)
1193 flags
&= ~IFF_MULTICAST
;
1195 return on_off("multicast", *argv
);
1196 } else if (strcmp(*argv
, "allmulticast") == 0) {
1198 mask
|= IFF_ALLMULTI
;
1200 if (strcmp(*argv
, "on") == 0)
1201 flags
|= IFF_ALLMULTI
;
1202 else if (strcmp(*argv
, "off") == 0)
1203 flags
&= ~IFF_ALLMULTI
;
1205 return on_off("allmulticast", *argv
);
1206 } else if (strcmp(*argv
, "promisc") == 0) {
1208 mask
|= IFF_PROMISC
;
1210 if (strcmp(*argv
, "on") == 0)
1211 flags
|= IFF_PROMISC
;
1212 else if (strcmp(*argv
, "off") == 0)
1213 flags
&= ~IFF_PROMISC
;
1215 return on_off("promisc", *argv
);
1216 } else if (strcmp(*argv
, "trailers") == 0) {
1218 mask
|= IFF_NOTRAILERS
;
1220 if (strcmp(*argv
, "off") == 0)
1221 flags
|= IFF_NOTRAILERS
;
1222 else if (strcmp(*argv
, "on") == 0)
1223 flags
&= ~IFF_NOTRAILERS
;
1225 return on_off("trailers", *argv
);
1226 } else if (strcmp(*argv
, "arp") == 0) {
1230 if (strcmp(*argv
, "on") == 0)
1231 flags
&= ~IFF_NOARP
;
1232 else if (strcmp(*argv
, "off") == 0)
1235 return on_off("arp", *argv
);
1236 } else if (matches(*argv
, "dynamic") == 0) {
1238 mask
|= IFF_DYNAMIC
;
1240 if (strcmp(*argv
, "on") == 0)
1241 flags
|= IFF_DYNAMIC
;
1242 else if (strcmp(*argv
, "off") == 0)
1243 flags
&= ~IFF_DYNAMIC
;
1245 return on_off("dynamic", *argv
);
1247 if (strcmp(*argv
, "dev") == 0)
1249 else if (matches(*argv
, "help") == 0)
1253 duparg2("dev", *argv
);
1261 "Not enough of information: \"dev\" argument is required.\n");
1265 if (newaddr
|| newbrd
) {
1266 halen
= get_address(dev
, &htype
);
1270 if (parse_address(dev
, htype
, halen
, newaddr
, &ifr0
) < 0)
1274 if (parse_address(dev
, htype
, halen
, newbrd
, &ifr1
) < 0)
1279 if (newname
&& strcmp(dev
, newname
)) {
1280 if (strlen(newname
) == 0)
1281 invarg("\"\" is not a valid device identifier\n", "name");
1282 if (do_changename(dev
, newname
) < 0)
1287 if (set_qlen(dev
, qlen
) < 0)
1291 if (set_mtu(dev
, mtu
) < 0)
1294 if (newaddr
|| newbrd
) {
1296 if (set_address(&ifr1
, 1) < 0)
1300 if (set_address(&ifr0
, 0) < 0)
1305 return do_chflags(dev
, flags
, mask
);
1308 #endif /* IPLINK_IOCTL_COMPAT */
1310 static void do_help(int argc
, char **argv
)
1312 struct link_util
*lu
= NULL
;
1319 lu
= get_link_kind(*argv
);
1320 if (lu
&& lu
->print_help
)
1321 lu
->print_help(lu
, argc
-1, argv
+1, stdout
);
1326 int do_iplink(int argc
, char **argv
)
1329 return ipaddr_list_link(0, NULL
);
1331 if (iplink_have_newlink()) {
1332 if (matches(*argv
, "add") == 0)
1333 return iplink_modify(RTM_NEWLINK
,
1334 NLM_F_CREATE
|NLM_F_EXCL
,
1336 if (matches(*argv
, "set") == 0 ||
1337 matches(*argv
, "change") == 0)
1338 return iplink_modify(RTM_NEWLINK
, 0,
1340 if (matches(*argv
, "replace") == 0)
1341 return iplink_modify(RTM_NEWLINK
,
1342 NLM_F_CREATE
|NLM_F_REPLACE
,
1344 if (matches(*argv
, "delete") == 0)
1345 return iplink_modify(RTM_DELLINK
, 0,
1348 #if IPLINK_IOCTL_COMPAT
1349 if (matches(*argv
, "set") == 0)
1350 return do_set(argc
-1, argv
+1);
1354 if (matches(*argv
, "show") == 0 ||
1355 matches(*argv
, "lst") == 0 ||
1356 matches(*argv
, "list") == 0)
1357 return ipaddr_list_link(argc
-1, argv
+1);
1359 if (matches(*argv
, "help") == 0) {
1360 do_help(argc
-1, argv
+1);
1364 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip link help\".\n",