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