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