xref: /aosp_15_r20/external/libnl/lib/route/link.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2003-2012 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup rtnl
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup link Links (Interfaces)
9*4dc78e53SAndroid Build Coastguard Worker  *
10*4dc78e53SAndroid Build Coastguard Worker  * @details
11*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{route_link, Link Documentation}
12*4dc78e53SAndroid Build Coastguard Worker  * @{
13*4dc78e53SAndroid Build Coastguard Worker  */
14*4dc78e53SAndroid Build Coastguard Worker 
15*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
16*4dc78e53SAndroid Build Coastguard Worker 
17*4dc78e53SAndroid Build Coastguard Worker #include <linux/if_arp.h>
18*4dc78e53SAndroid Build Coastguard Worker 
19*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
20*4dc78e53SAndroid Build Coastguard Worker #include <netlink/attr.h>
21*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
22*4dc78e53SAndroid Build Coastguard Worker #include <netlink/object.h>
23*4dc78e53SAndroid Build Coastguard Worker #include <netlink/hashtable.h>
24*4dc78e53SAndroid Build Coastguard Worker #include <netlink/data.h>
25*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rtnl.h>
26*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
27*4dc78e53SAndroid Build Coastguard Worker 
28*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-route/nl-route.h"
29*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
30*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
31*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
32*4dc78e53SAndroid Build Coastguard Worker #include "link-sriov.h"
33*4dc78e53SAndroid Build Coastguard Worker #include "link/link-api.h"
34*4dc78e53SAndroid Build Coastguard Worker 
35*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
36*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_MTU		(1 <<  0)
37*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_LINK		(1 <<  1)
38*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_TXQLEN	(1 <<  2)
39*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_WEIGHT	(1 <<  3)
40*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_MASTER	(1 <<  4)
41*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_QDISC		(1 <<  5)
42*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_MAP		(1 <<  6)
43*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_ADDR		(1 <<  7)
44*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_BRD		(1 <<  8)
45*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_FLAGS		(1 <<  9)
46*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_IFNAME	(1 << 10)
47*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_IFINDEX	(1 << 11)
48*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_FAMILY	(1 << 12)
49*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_ARPTYPE	(1 << 13)
50*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_STATS		(1 << 14)
51*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_CHANGE	(1 << 15)
52*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_OPERSTATE	(1 << 16)
53*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_LINKMODE	(1 << 17)
54*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_LINKINFO	(1 << 18)
55*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_IFALIAS	(1 << 19)
56*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_NUM_VF	(1 << 20)
57*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_PROMISCUITY	(1 << 21)
58*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_NUM_TX_QUEUES	(1 << 22)
59*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_NUM_RX_QUEUES	(1 << 23)
60*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_GROUP		(1 << 24)
61*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_CARRIER	(1 << 25)
62*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_PROTINFO	(1 << 26)
63*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_AF_SPEC	(1 << 27)
64*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_PHYS_PORT_ID	(1 << 28)
65*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_NS_FD		(1 << 29)
66*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_NS_PID	(1 << 30)
67*4dc78e53SAndroid Build Coastguard Worker /* 31 used by 32-bit api */
68*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_LINK_NETNSID  	((uint64_t) 1 << 32)
69*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_VF_LIST		((uint64_t) 1 << 33)
70*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_CARRIER_CHANGES	((uint64_t) 1 << 34)
71*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_PHYS_PORT_NAME	((uint64_t) 1 << 35)
72*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_PHYS_SWITCH_ID	((uint64_t) 1 << 36)
73*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_GSO_MAX_SEGS		((uint64_t) 1 << 37)
74*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_GSO_MAX_SIZE		((uint64_t) 1 << 38)
75*4dc78e53SAndroid Build Coastguard Worker #define LINK_ATTR_LINKINFO_SLAVE_KIND	((uint64_t) 1 << 39)
76*4dc78e53SAndroid Build Coastguard Worker 
77*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_link_ops;
78*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops link_obj_ops;
79*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
80*4dc78e53SAndroid Build Coastguard Worker 
link_lookup(struct nl_cache * cache,int ifindex)81*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *link_lookup(struct nl_cache *cache, int ifindex)
82*4dc78e53SAndroid Build Coastguard Worker {
83*4dc78e53SAndroid Build Coastguard Worker 	if (!cache) {
84*4dc78e53SAndroid Build Coastguard Worker 		cache = __nl_cache_mngt_require("route/link");
85*4dc78e53SAndroid Build Coastguard Worker 		if (!cache)
86*4dc78e53SAndroid Build Coastguard Worker 			return NULL;
87*4dc78e53SAndroid Build Coastguard Worker 	}
88*4dc78e53SAndroid Build Coastguard Worker 
89*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_link_get(cache, ifindex);
90*4dc78e53SAndroid Build Coastguard Worker }
91*4dc78e53SAndroid Build Coastguard Worker 
af_lookup_and_alloc(struct rtnl_link * link,int family)92*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_link_af_ops *af_lookup_and_alloc(struct rtnl_link *link,
93*4dc78e53SAndroid Build Coastguard Worker 						    int family)
94*4dc78e53SAndroid Build Coastguard Worker {
95*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link_af_ops *af_ops;
96*4dc78e53SAndroid Build Coastguard Worker 
97*4dc78e53SAndroid Build Coastguard Worker 	af_ops = rtnl_link_af_ops_lookup(family);
98*4dc78e53SAndroid Build Coastguard Worker 	if (!af_ops)
99*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
100*4dc78e53SAndroid Build Coastguard Worker 
101*4dc78e53SAndroid Build Coastguard Worker 	if (!rtnl_link_af_alloc(link, af_ops)) {
102*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_af_ops_put(af_ops);
103*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
104*4dc78e53SAndroid Build Coastguard Worker 	}
105*4dc78e53SAndroid Build Coastguard Worker 
106*4dc78e53SAndroid Build Coastguard Worker 	return af_ops;
107*4dc78e53SAndroid Build Coastguard Worker }
108*4dc78e53SAndroid Build Coastguard Worker 
af_free(struct rtnl_link * link,struct rtnl_link_af_ops * ops,void * data,void * arg)109*4dc78e53SAndroid Build Coastguard Worker static int af_free(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
110*4dc78e53SAndroid Build Coastguard Worker 		    void *data, void *arg)
111*4dc78e53SAndroid Build Coastguard Worker {
112*4dc78e53SAndroid Build Coastguard Worker 	if (ops->ao_free)
113*4dc78e53SAndroid Build Coastguard Worker 		ops->ao_free(link, data);
114*4dc78e53SAndroid Build Coastguard Worker 
115*4dc78e53SAndroid Build Coastguard Worker 	rtnl_link_af_ops_put(ops);
116*4dc78e53SAndroid Build Coastguard Worker 
117*4dc78e53SAndroid Build Coastguard Worker 	return 0;
118*4dc78e53SAndroid Build Coastguard Worker }
119*4dc78e53SAndroid Build Coastguard Worker 
af_request_type(int af_type,struct rtnl_link * changes)120*4dc78e53SAndroid Build Coastguard Worker static int af_request_type(int af_type, struct rtnl_link *changes)
121*4dc78e53SAndroid Build Coastguard Worker {
122*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link_af_ops *ops;
123*4dc78e53SAndroid Build Coastguard Worker 
124*4dc78e53SAndroid Build Coastguard Worker 	ops = rtnl_link_af_ops_lookup(af_type);
125*4dc78e53SAndroid Build Coastguard Worker 	if (ops && ops->ao_override_rtm && ops->ao_override_rtm(changes))
126*4dc78e53SAndroid Build Coastguard Worker 		return RTM_SETLINK;
127*4dc78e53SAndroid Build Coastguard Worker 
128*4dc78e53SAndroid Build Coastguard Worker 	return RTM_NEWLINK;
129*4dc78e53SAndroid Build Coastguard Worker }
130*4dc78e53SAndroid Build Coastguard Worker 
af_clone(struct rtnl_link * link,struct rtnl_link_af_ops * ops,void * data,void * arg)131*4dc78e53SAndroid Build Coastguard Worker static int af_clone(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
132*4dc78e53SAndroid Build Coastguard Worker 		    void *data, void *arg)
133*4dc78e53SAndroid Build Coastguard Worker {
134*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *dst = arg;
135*4dc78e53SAndroid Build Coastguard Worker 
136*4dc78e53SAndroid Build Coastguard Worker 	if (ops->ao_clone &&
137*4dc78e53SAndroid Build Coastguard Worker 	    !(dst->l_af_data[ops->ao_family] = ops->ao_clone(dst, data)))
138*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
139*4dc78e53SAndroid Build Coastguard Worker 
140*4dc78e53SAndroid Build Coastguard Worker 	return 0;
141*4dc78e53SAndroid Build Coastguard Worker }
142*4dc78e53SAndroid Build Coastguard Worker 
af_fill(struct rtnl_link * link,struct rtnl_link_af_ops * ops,void * data,void * arg)143*4dc78e53SAndroid Build Coastguard Worker static int af_fill(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
144*4dc78e53SAndroid Build Coastguard Worker 		   void *data, void *arg)
145*4dc78e53SAndroid Build Coastguard Worker {
146*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg = arg;
147*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *af_attr = NULL;
148*4dc78e53SAndroid Build Coastguard Worker 	int err;
149*4dc78e53SAndroid Build Coastguard Worker 
150*4dc78e53SAndroid Build Coastguard Worker 	if (!ops->ao_fill_af)
151*4dc78e53SAndroid Build Coastguard Worker 		return 0;
152*4dc78e53SAndroid Build Coastguard Worker 
153*4dc78e53SAndroid Build Coastguard Worker 	if (!ops->ao_fill_af_no_nest)
154*4dc78e53SAndroid Build Coastguard Worker 		if (!(af_attr = nla_nest_start(msg, ops->ao_family)))
155*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_MSGSIZE;
156*4dc78e53SAndroid Build Coastguard Worker 
157*4dc78e53SAndroid Build Coastguard Worker 	if ((err = ops->ao_fill_af(link, arg, data)) < 0)
158*4dc78e53SAndroid Build Coastguard Worker 		return err;
159*4dc78e53SAndroid Build Coastguard Worker 
160*4dc78e53SAndroid Build Coastguard Worker 	if (!ops->ao_fill_af_no_nest)
161*4dc78e53SAndroid Build Coastguard Worker 		nla_nest_end(msg, af_attr);
162*4dc78e53SAndroid Build Coastguard Worker 
163*4dc78e53SAndroid Build Coastguard Worker 	return 0;
164*4dc78e53SAndroid Build Coastguard Worker }
165*4dc78e53SAndroid Build Coastguard Worker 
af_fill_pi(struct rtnl_link * link,struct rtnl_link_af_ops * ops,void * data,void * arg)166*4dc78e53SAndroid Build Coastguard Worker static int af_fill_pi(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
167*4dc78e53SAndroid Build Coastguard Worker 		   void *data, void *arg)
168*4dc78e53SAndroid Build Coastguard Worker {
169*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg = arg;
170*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *pi_attr;
171*4dc78e53SAndroid Build Coastguard Worker 	int err, pi_type = IFLA_PROTINFO;
172*4dc78e53SAndroid Build Coastguard Worker 
173*4dc78e53SAndroid Build Coastguard Worker 	if (!ops->ao_fill_pi)
174*4dc78e53SAndroid Build Coastguard Worker 		return 0;
175*4dc78e53SAndroid Build Coastguard Worker 
176*4dc78e53SAndroid Build Coastguard Worker 	if (ops->ao_fill_pi_flags > 0)
177*4dc78e53SAndroid Build Coastguard Worker 		pi_type |= ops->ao_fill_pi_flags;
178*4dc78e53SAndroid Build Coastguard Worker 
179*4dc78e53SAndroid Build Coastguard Worker 	if (!(pi_attr = nla_nest_start(msg, pi_type)))
180*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MSGSIZE;
181*4dc78e53SAndroid Build Coastguard Worker 
182*4dc78e53SAndroid Build Coastguard Worker 	if ((err = ops->ao_fill_pi(link, arg, data)) < 0)
183*4dc78e53SAndroid Build Coastguard Worker 		return err;
184*4dc78e53SAndroid Build Coastguard Worker 
185*4dc78e53SAndroid Build Coastguard Worker 	nla_nest_end(msg, pi_attr);
186*4dc78e53SAndroid Build Coastguard Worker 
187*4dc78e53SAndroid Build Coastguard Worker 	return 0;
188*4dc78e53SAndroid Build Coastguard Worker }
189*4dc78e53SAndroid Build Coastguard Worker 
af_dump_line(struct rtnl_link * link,struct rtnl_link_af_ops * ops,void * data,void * arg)190*4dc78e53SAndroid Build Coastguard Worker static int af_dump_line(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
191*4dc78e53SAndroid Build Coastguard Worker 			 void *data, void *arg)
192*4dc78e53SAndroid Build Coastguard Worker {
193*4dc78e53SAndroid Build Coastguard Worker 	struct nl_dump_params *p = arg;
194*4dc78e53SAndroid Build Coastguard Worker 
195*4dc78e53SAndroid Build Coastguard Worker 	if (ops->ao_dump[NL_DUMP_LINE])
196*4dc78e53SAndroid Build Coastguard Worker 		ops->ao_dump[NL_DUMP_LINE](link, p, data);
197*4dc78e53SAndroid Build Coastguard Worker 
198*4dc78e53SAndroid Build Coastguard Worker 	return 0;
199*4dc78e53SAndroid Build Coastguard Worker }
200*4dc78e53SAndroid Build Coastguard Worker 
af_dump_details(struct rtnl_link * link,struct rtnl_link_af_ops * ops,void * data,void * arg)201*4dc78e53SAndroid Build Coastguard Worker static int af_dump_details(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
202*4dc78e53SAndroid Build Coastguard Worker 			   void *data, void *arg)
203*4dc78e53SAndroid Build Coastguard Worker {
204*4dc78e53SAndroid Build Coastguard Worker 	struct nl_dump_params *p = arg;
205*4dc78e53SAndroid Build Coastguard Worker 
206*4dc78e53SAndroid Build Coastguard Worker 	if (ops->ao_dump[NL_DUMP_DETAILS])
207*4dc78e53SAndroid Build Coastguard Worker 		ops->ao_dump[NL_DUMP_DETAILS](link, p, data);
208*4dc78e53SAndroid Build Coastguard Worker 
209*4dc78e53SAndroid Build Coastguard Worker 	return 0;
210*4dc78e53SAndroid Build Coastguard Worker }
211*4dc78e53SAndroid Build Coastguard Worker 
af_dump_stats(struct rtnl_link * link,struct rtnl_link_af_ops * ops,void * data,void * arg)212*4dc78e53SAndroid Build Coastguard Worker static int af_dump_stats(struct rtnl_link *link, struct rtnl_link_af_ops *ops,
213*4dc78e53SAndroid Build Coastguard Worker 			 void *data, void *arg)
214*4dc78e53SAndroid Build Coastguard Worker {
215*4dc78e53SAndroid Build Coastguard Worker 	struct nl_dump_params *p = arg;
216*4dc78e53SAndroid Build Coastguard Worker 
217*4dc78e53SAndroid Build Coastguard Worker 	if (ops->ao_dump[NL_DUMP_STATS])
218*4dc78e53SAndroid Build Coastguard Worker 		ops->ao_dump[NL_DUMP_STATS](link, p, data);
219*4dc78e53SAndroid Build Coastguard Worker 
220*4dc78e53SAndroid Build Coastguard Worker 	return 0;
221*4dc78e53SAndroid Build Coastguard Worker }
222*4dc78e53SAndroid Build Coastguard Worker 
do_foreach_af(struct rtnl_link * link,int (* cb)(struct rtnl_link *,struct rtnl_link_af_ops *,void *,void *),void * arg)223*4dc78e53SAndroid Build Coastguard Worker static int do_foreach_af(struct rtnl_link *link,
224*4dc78e53SAndroid Build Coastguard Worker 			 int (*cb)(struct rtnl_link *,
225*4dc78e53SAndroid Build Coastguard Worker 				   struct rtnl_link_af_ops *, void *, void *),
226*4dc78e53SAndroid Build Coastguard Worker 			 void *arg)
227*4dc78e53SAndroid Build Coastguard Worker {
228*4dc78e53SAndroid Build Coastguard Worker 	int i, err;
229*4dc78e53SAndroid Build Coastguard Worker 
230*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < AF_MAX; i++) {
231*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_af_data[i]) {
232*4dc78e53SAndroid Build Coastguard Worker 			_nl_auto_rtnl_link_af_ops struct rtnl_link_af_ops *ops = NULL;
233*4dc78e53SAndroid Build Coastguard Worker 
234*4dc78e53SAndroid Build Coastguard Worker 			if (!(ops = rtnl_link_af_ops_lookup(i)))
235*4dc78e53SAndroid Build Coastguard Worker 				BUG();
236*4dc78e53SAndroid Build Coastguard Worker 
237*4dc78e53SAndroid Build Coastguard Worker 			err = cb(link, ops, link->l_af_data[i], arg);
238*4dc78e53SAndroid Build Coastguard Worker 			if (err < 0)
239*4dc78e53SAndroid Build Coastguard Worker 				return err;
240*4dc78e53SAndroid Build Coastguard Worker 		}
241*4dc78e53SAndroid Build Coastguard Worker 	}
242*4dc78e53SAndroid Build Coastguard Worker 
243*4dc78e53SAndroid Build Coastguard Worker 	return 0;
244*4dc78e53SAndroid Build Coastguard Worker }
245*4dc78e53SAndroid Build Coastguard Worker 
release_link_info(struct rtnl_link * link)246*4dc78e53SAndroid Build Coastguard Worker static void release_link_info(struct rtnl_link *link)
247*4dc78e53SAndroid Build Coastguard Worker {
248*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link_info_ops *io = link->l_info_ops;
249*4dc78e53SAndroid Build Coastguard Worker 
250*4dc78e53SAndroid Build Coastguard Worker 	if (io != NULL) {
251*4dc78e53SAndroid Build Coastguard Worker 		if (io->io_free)
252*4dc78e53SAndroid Build Coastguard Worker 			io->io_free(link);
253*4dc78e53SAndroid Build Coastguard Worker 		else {
254*4dc78e53SAndroid Build Coastguard Worker 			/* Catch missing io_free() implementations */
255*4dc78e53SAndroid Build Coastguard Worker 			BUG_ON(link->l_info);
256*4dc78e53SAndroid Build Coastguard Worker 		}
257*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_info_ops_put(io);
258*4dc78e53SAndroid Build Coastguard Worker 		link->l_info_ops = NULL;
259*4dc78e53SAndroid Build Coastguard Worker 	}
260*4dc78e53SAndroid Build Coastguard Worker }
261*4dc78e53SAndroid Build Coastguard Worker 
link_free_data(struct nl_object * c)262*4dc78e53SAndroid Build Coastguard Worker static void link_free_data(struct nl_object *c)
263*4dc78e53SAndroid Build Coastguard Worker {
264*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link = nl_object_priv(c);
265*4dc78e53SAndroid Build Coastguard Worker 
266*4dc78e53SAndroid Build Coastguard Worker 	if (link) {
267*4dc78e53SAndroid Build Coastguard Worker 		release_link_info(link);
268*4dc78e53SAndroid Build Coastguard Worker 
269*4dc78e53SAndroid Build Coastguard Worker 		/* proto info af reference */
270*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_af_ops_put(link->l_af_ops);
271*4dc78e53SAndroid Build Coastguard Worker 
272*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_put(link->l_addr);
273*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_put(link->l_bcast);
274*4dc78e53SAndroid Build Coastguard Worker 
275*4dc78e53SAndroid Build Coastguard Worker 		free(link->l_ifalias);
276*4dc78e53SAndroid Build Coastguard Worker 		free(link->l_info_kind);
277*4dc78e53SAndroid Build Coastguard Worker 		free(link->l_info_slave_kind);
278*4dc78e53SAndroid Build Coastguard Worker 
279*4dc78e53SAndroid Build Coastguard Worker 		do_foreach_af(link, af_free, NULL);
280*4dc78e53SAndroid Build Coastguard Worker 
281*4dc78e53SAndroid Build Coastguard Worker 		nl_data_free(link->l_phys_port_id);
282*4dc78e53SAndroid Build Coastguard Worker 		nl_data_free(link->l_phys_switch_id);
283*4dc78e53SAndroid Build Coastguard Worker 
284*4dc78e53SAndroid Build Coastguard Worker 		if (link->ce_mask & LINK_ATTR_VF_LIST)
285*4dc78e53SAndroid Build Coastguard Worker 			rtnl_link_sriov_free_data(link);
286*4dc78e53SAndroid Build Coastguard Worker 	}
287*4dc78e53SAndroid Build Coastguard Worker }
288*4dc78e53SAndroid Build Coastguard Worker 
link_clone(struct nl_object * _dst,struct nl_object * _src)289*4dc78e53SAndroid Build Coastguard Worker static int link_clone(struct nl_object *_dst, struct nl_object *_src)
290*4dc78e53SAndroid Build Coastguard Worker {
291*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *dst = nl_object_priv(_dst);
292*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *src = nl_object_priv(_src);
293*4dc78e53SAndroid Build Coastguard Worker 	int err;
294*4dc78e53SAndroid Build Coastguard Worker 
295*4dc78e53SAndroid Build Coastguard Worker 	dst->l_addr = NULL;
296*4dc78e53SAndroid Build Coastguard Worker 	dst->l_bcast = NULL;
297*4dc78e53SAndroid Build Coastguard Worker 	dst->l_info_kind = NULL;
298*4dc78e53SAndroid Build Coastguard Worker 	dst->l_info_slave_kind = NULL;
299*4dc78e53SAndroid Build Coastguard Worker 	dst->l_info_ops = NULL;
300*4dc78e53SAndroid Build Coastguard Worker 	memset(dst->l_af_data, 0, sizeof (dst->l_af_data));
301*4dc78e53SAndroid Build Coastguard Worker 	dst->l_info = NULL;
302*4dc78e53SAndroid Build Coastguard Worker 	dst->l_ifalias = NULL;
303*4dc78e53SAndroid Build Coastguard Worker 	dst->l_af_ops = NULL;
304*4dc78e53SAndroid Build Coastguard Worker 	dst->l_phys_port_id = NULL;
305*4dc78e53SAndroid Build Coastguard Worker 	dst->l_phys_switch_id = NULL;
306*4dc78e53SAndroid Build Coastguard Worker 	dst->l_vf_list = NULL;
307*4dc78e53SAndroid Build Coastguard Worker 
308*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_addr)
309*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->l_addr = nl_addr_clone(src->l_addr)))
310*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
311*4dc78e53SAndroid Build Coastguard Worker 
312*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_bcast)
313*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->l_bcast = nl_addr_clone(src->l_bcast)))
314*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
315*4dc78e53SAndroid Build Coastguard Worker 
316*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_ifalias)
317*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->l_ifalias = strdup(src->l_ifalias)))
318*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
319*4dc78e53SAndroid Build Coastguard Worker 
320*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_info_kind)
321*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->l_info_kind = strdup(src->l_info_kind)))
322*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
323*4dc78e53SAndroid Build Coastguard Worker 
324*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_info_slave_kind)
325*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->l_info_slave_kind = strdup(src->l_info_slave_kind)))
326*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
327*4dc78e53SAndroid Build Coastguard Worker 
328*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_info_ops) {
329*4dc78e53SAndroid Build Coastguard Worker 
330*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_info_ops_get(src->l_info_ops);
331*4dc78e53SAndroid Build Coastguard Worker 		dst->l_info_ops = src->l_info_ops;
332*4dc78e53SAndroid Build Coastguard Worker 
333*4dc78e53SAndroid Build Coastguard Worker 		if (src->l_info_ops->io_clone) {
334*4dc78e53SAndroid Build Coastguard Worker 			err = src->l_info_ops->io_clone(dst, src);
335*4dc78e53SAndroid Build Coastguard Worker 			if (err < 0)
336*4dc78e53SAndroid Build Coastguard Worker 				return err;
337*4dc78e53SAndroid Build Coastguard Worker 		}
338*4dc78e53SAndroid Build Coastguard Worker 	}
339*4dc78e53SAndroid Build Coastguard Worker 
340*4dc78e53SAndroid Build Coastguard Worker 	if ((err = do_foreach_af(src, af_clone, dst)) < 0)
341*4dc78e53SAndroid Build Coastguard Worker 		return err;
342*4dc78e53SAndroid Build Coastguard Worker 
343*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_af_ops)
344*4dc78e53SAndroid Build Coastguard Worker 		dst->l_af_ops = af_lookup_and_alloc(dst, src->l_af_ops->ao_family);
345*4dc78e53SAndroid Build Coastguard Worker 
346*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_phys_port_id)
347*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->l_phys_port_id = nl_data_clone(src->l_phys_port_id)))
348*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
349*4dc78e53SAndroid Build Coastguard Worker 
350*4dc78e53SAndroid Build Coastguard Worker 	if (src->l_phys_switch_id)
351*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->l_phys_switch_id = nl_data_clone(src->l_phys_switch_id)))
352*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
353*4dc78e53SAndroid Build Coastguard Worker 
354*4dc78e53SAndroid Build Coastguard Worker 	if (src->ce_mask & LINK_ATTR_VF_LIST)
355*4dc78e53SAndroid Build Coastguard Worker 		if ((err = rtnl_link_sriov_clone(dst, src)) < 0)
356*4dc78e53SAndroid Build Coastguard Worker 			return err;
357*4dc78e53SAndroid Build Coastguard Worker 
358*4dc78e53SAndroid Build Coastguard Worker 	return 0;
359*4dc78e53SAndroid Build Coastguard Worker }
360*4dc78e53SAndroid Build Coastguard Worker 
361*4dc78e53SAndroid Build Coastguard Worker struct nla_policy rtln_link_policy[IFLA_MAX+1] = {
362*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_IFNAME]		= { .type = NLA_STRING,
363*4dc78e53SAndroid Build Coastguard Worker 				    .maxlen = IFNAMSIZ },
364*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_MTU]		= { .type = NLA_U32 },
365*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_TXQLEN]		= { .type = NLA_U32 },
366*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_LINK]		= { .type = NLA_U32 },
367*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_WEIGHT]		= { .type = NLA_U32 },
368*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_MASTER]		= { .type = NLA_U32 },
369*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_OPERSTATE]	= { .type = NLA_U8 },
370*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_LINKMODE] 	= { .type = NLA_U8 },
371*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_LINKINFO]		= { .type = NLA_NESTED },
372*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_QDISC]		= { .type = NLA_STRING,
373*4dc78e53SAndroid Build Coastguard Worker 				    .maxlen = IFQDISCSIZ },
374*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_STATS]		= { .minlen = _nl_offsetofend (struct rtnl_link_stats, tx_compressed) },
375*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_STATS64]		= { .minlen = _nl_offsetofend (struct rtnl_link_stats64, tx_compressed) },
376*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_MAP]		= { .minlen = sizeof(struct rtnl_link_ifmap) },
377*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_IFALIAS]		= { .type = NLA_STRING, .maxlen = IFALIASZ },
378*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_NUM_VF]		= { .type = NLA_U32 },
379*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_VFINFO_LIST]	= { .type = NLA_NESTED },
380*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_AF_SPEC]		= { .type = NLA_NESTED },
381*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_PROMISCUITY]	= { .type = NLA_U32 },
382*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_NUM_TX_QUEUES]	= { .type = NLA_U32 },
383*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_NUM_RX_QUEUES]	= { .type = NLA_U32 },
384*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_GSO_MAX_SEGS]	= { .type = NLA_U32 },
385*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_GSO_MAX_SIZE]	= { .type = NLA_U32 },
386*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_GROUP]		= { .type = NLA_U32 },
387*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_CARRIER]		= { .type = NLA_U8 },
388*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_CARRIER_CHANGES]	= { .type = NLA_U32 },
389*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_PHYS_PORT_ID]	= { .type = NLA_UNSPEC },
390*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_PHYS_PORT_NAME]	= { .type = NLA_STRING, .maxlen = IFNAMSIZ },
391*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_PHYS_SWITCH_ID]	= { .type = NLA_UNSPEC },
392*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_NET_NS_PID]	= { .type = NLA_U32 },
393*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_NET_NS_FD]	= { .type = NLA_U32 },
394*4dc78e53SAndroid Build Coastguard Worker };
395*4dc78e53SAndroid Build Coastguard Worker 
396*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy link_info_policy[IFLA_INFO_MAX+1] = {
397*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_INFO_KIND]	= { .type = NLA_STRING },
398*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },
399*4dc78e53SAndroid Build Coastguard Worker 	[IFLA_INFO_XSTATS]	= { .type = NLA_NESTED },
400*4dc78e53SAndroid Build Coastguard Worker };
401*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_info_parse(struct rtnl_link * link,struct nlattr ** tb)402*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_info_parse(struct rtnl_link *link, struct nlattr **tb)
403*4dc78e53SAndroid Build Coastguard Worker {
404*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_IFNAME] == NULL)
405*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
406*4dc78e53SAndroid Build Coastguard Worker 
407*4dc78e53SAndroid Build Coastguard Worker 	nla_strlcpy(link->l_name, tb[IFLA_IFNAME], IFNAMSIZ);
408*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_IFNAME;
409*4dc78e53SAndroid Build Coastguard Worker 
410*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_STATS]) {
411*4dc78e53SAndroid Build Coastguard Worker 		struct rtnl_link_stats *st = nla_data(tb[IFLA_STATS]);
412*4dc78e53SAndroid Build Coastguard Worker 
413*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_PACKETS]	= st->rx_packets;
414*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_PACKETS]	= st->tx_packets;
415*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_BYTES]	= st->rx_bytes;
416*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_BYTES]	= st->tx_bytes;
417*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_ERRORS]	= st->rx_errors;
418*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_ERRORS]	= st->tx_errors;
419*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_DROPPED]	= st->rx_dropped;
420*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_DROPPED]	= st->tx_dropped;
421*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_MULTICAST]	= st->multicast;
422*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_COLLISIONS]	= st->collisions;
423*4dc78e53SAndroid Build Coastguard Worker 
424*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_LEN_ERR]	= st->rx_length_errors;
425*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_OVER_ERR]	= st->rx_over_errors;
426*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_CRC_ERR]	= st->rx_crc_errors;
427*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_FRAME_ERR]	= st->rx_frame_errors;
428*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_FIFO_ERR]	= st->rx_fifo_errors;
429*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_MISSED_ERR]	= st->rx_missed_errors;
430*4dc78e53SAndroid Build Coastguard Worker 
431*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_ABORT_ERR]	= st->tx_aborted_errors;
432*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_CARRIER_ERR]	= st->tx_carrier_errors;
433*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_FIFO_ERR]	= st->tx_fifo_errors;
434*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_HBEAT_ERR]	= st->tx_heartbeat_errors;
435*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_WIN_ERR]	= st->tx_window_errors;
436*4dc78e53SAndroid Build Coastguard Worker 
437*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_COMPRESSED]	= st->rx_compressed;
438*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_COMPRESSED]	= st->tx_compressed;
439*4dc78e53SAndroid Build Coastguard Worker 
440*4dc78e53SAndroid Build Coastguard Worker 		/* beware: @st might not be the full struct, only fields up to
441*4dc78e53SAndroid Build Coastguard Worker 		 * tx_compressed are present. See _nl_offsetofend() above. */
442*4dc78e53SAndroid Build Coastguard Worker 
443*4dc78e53SAndroid Build Coastguard Worker 		if (_nla_len(tb[IFLA_STATS]) >= _nl_offsetofend (struct rtnl_link_stats, rx_nohandler))
444*4dc78e53SAndroid Build Coastguard Worker 			link->l_stats[RTNL_LINK_RX_NOHANDLER] = st->rx_nohandler;
445*4dc78e53SAndroid Build Coastguard Worker 		else
446*4dc78e53SAndroid Build Coastguard Worker 			link->l_stats[RTNL_LINK_RX_NOHANDLER] = 0;
447*4dc78e53SAndroid Build Coastguard Worker 
448*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_STATS;
449*4dc78e53SAndroid Build Coastguard Worker 	}
450*4dc78e53SAndroid Build Coastguard Worker 
451*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_STATS64]) {
452*4dc78e53SAndroid Build Coastguard Worker 		/*
453*4dc78e53SAndroid Build Coastguard Worker 		 * This structure contains 64bit parameters, and per the
454*4dc78e53SAndroid Build Coastguard Worker 		 * documentation in lib/attr.c, must not be accessed
455*4dc78e53SAndroid Build Coastguard Worker 		 * directly (because of alignment to 4 instead of 8).
456*4dc78e53SAndroid Build Coastguard Worker 		 * Therefore, copy the data to the stack and access it from
457*4dc78e53SAndroid Build Coastguard Worker 		 * there, where it will be aligned to 8.
458*4dc78e53SAndroid Build Coastguard Worker 		 */
459*4dc78e53SAndroid Build Coastguard Worker 		struct rtnl_link_stats64 st = { 0 };
460*4dc78e53SAndroid Build Coastguard Worker 
461*4dc78e53SAndroid Build Coastguard Worker 		nla_memcpy(&st, tb[IFLA_STATS64], sizeof (st));
462*4dc78e53SAndroid Build Coastguard Worker 
463*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_PACKETS]	= st.rx_packets;
464*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_PACKETS]	= st.tx_packets;
465*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_BYTES]	= st.rx_bytes;
466*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_BYTES]	= st.tx_bytes;
467*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_ERRORS]	= st.rx_errors;
468*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_ERRORS]	= st.tx_errors;
469*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_DROPPED]	= st.rx_dropped;
470*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_DROPPED]	= st.tx_dropped;
471*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_MULTICAST]	= st.multicast;
472*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_COLLISIONS]	= st.collisions;
473*4dc78e53SAndroid Build Coastguard Worker 
474*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_LEN_ERR]	= st.rx_length_errors;
475*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_OVER_ERR]	= st.rx_over_errors;
476*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_CRC_ERR]	= st.rx_crc_errors;
477*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_FRAME_ERR]	= st.rx_frame_errors;
478*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_FIFO_ERR]	= st.rx_fifo_errors;
479*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_MISSED_ERR]	= st.rx_missed_errors;
480*4dc78e53SAndroid Build Coastguard Worker 
481*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_ABORT_ERR]	= st.tx_aborted_errors;
482*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_CARRIER_ERR]	= st.tx_carrier_errors;
483*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_FIFO_ERR]	= st.tx_fifo_errors;
484*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_HBEAT_ERR]	= st.tx_heartbeat_errors;
485*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_WIN_ERR]	= st.tx_window_errors;
486*4dc78e53SAndroid Build Coastguard Worker 
487*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_COMPRESSED]	= st.rx_compressed;
488*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_COMPRESSED]	= st.tx_compressed;
489*4dc78e53SAndroid Build Coastguard Worker 
490*4dc78e53SAndroid Build Coastguard Worker 		/* beware: @st might not be the full struct, only fields up to
491*4dc78e53SAndroid Build Coastguard Worker 		 * tx_compressed are present. See _nl_offsetofend() above. */
492*4dc78e53SAndroid Build Coastguard Worker 
493*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_NOHANDLER]	= st.rx_nohandler;
494*4dc78e53SAndroid Build Coastguard Worker 
495*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_STATS;
496*4dc78e53SAndroid Build Coastguard Worker 	}
497*4dc78e53SAndroid Build Coastguard Worker 
498*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_TXQLEN]) {
499*4dc78e53SAndroid Build Coastguard Worker 		link->l_txqlen = nla_get_u32(tb[IFLA_TXQLEN]);
500*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_TXQLEN;
501*4dc78e53SAndroid Build Coastguard Worker 	}
502*4dc78e53SAndroid Build Coastguard Worker 
503*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_MTU]) {
504*4dc78e53SAndroid Build Coastguard Worker 		link->l_mtu = nla_get_u32(tb[IFLA_MTU]);
505*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_MTU;
506*4dc78e53SAndroid Build Coastguard Worker 	}
507*4dc78e53SAndroid Build Coastguard Worker 
508*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_ADDRESS]) {
509*4dc78e53SAndroid Build Coastguard Worker 		link->l_addr = nl_addr_alloc_attr(tb[IFLA_ADDRESS], AF_UNSPEC);
510*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_addr == NULL)
511*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
512*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_family(link->l_addr,
513*4dc78e53SAndroid Build Coastguard Worker 				   nl_addr_guess_family(link->l_addr));
514*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_ADDR;
515*4dc78e53SAndroid Build Coastguard Worker 	}
516*4dc78e53SAndroid Build Coastguard Worker 
517*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_BROADCAST]) {
518*4dc78e53SAndroid Build Coastguard Worker 		link->l_bcast = nl_addr_alloc_attr(tb[IFLA_BROADCAST],
519*4dc78e53SAndroid Build Coastguard Worker 						   AF_UNSPEC);
520*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_bcast == NULL)
521*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
522*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_family(link->l_bcast,
523*4dc78e53SAndroid Build Coastguard Worker 				   nl_addr_guess_family(link->l_bcast));
524*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_BRD;
525*4dc78e53SAndroid Build Coastguard Worker 	}
526*4dc78e53SAndroid Build Coastguard Worker 
527*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_LINK]) {
528*4dc78e53SAndroid Build Coastguard Worker 		link->l_link = nla_get_u32(tb[IFLA_LINK]);
529*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_LINK;
530*4dc78e53SAndroid Build Coastguard Worker 	}
531*4dc78e53SAndroid Build Coastguard Worker 
532*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_LINK_NETNSID]) {
533*4dc78e53SAndroid Build Coastguard Worker 		link->l_link_netnsid = nla_get_s32(tb[IFLA_LINK_NETNSID]);
534*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_LINK_NETNSID;
535*4dc78e53SAndroid Build Coastguard Worker 	}
536*4dc78e53SAndroid Build Coastguard Worker 
537*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_WEIGHT]) {
538*4dc78e53SAndroid Build Coastguard Worker 		link->l_weight = nla_get_u32(tb[IFLA_WEIGHT]);
539*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_WEIGHT;
540*4dc78e53SAndroid Build Coastguard Worker 	}
541*4dc78e53SAndroid Build Coastguard Worker 
542*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_QDISC]) {
543*4dc78e53SAndroid Build Coastguard Worker 		nla_strlcpy(link->l_qdisc, tb[IFLA_QDISC], IFQDISCSIZ);
544*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_QDISC;
545*4dc78e53SAndroid Build Coastguard Worker 	}
546*4dc78e53SAndroid Build Coastguard Worker 
547*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_MAP]) {
548*4dc78e53SAndroid Build Coastguard Worker 		nla_memcpy(&link->l_map, tb[IFLA_MAP],
549*4dc78e53SAndroid Build Coastguard Worker 			   sizeof(struct rtnl_link_ifmap));
550*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_MAP;
551*4dc78e53SAndroid Build Coastguard Worker 	}
552*4dc78e53SAndroid Build Coastguard Worker 
553*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_MASTER]) {
554*4dc78e53SAndroid Build Coastguard Worker 		link->l_master = nla_get_u32(tb[IFLA_MASTER]);
555*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_MASTER;
556*4dc78e53SAndroid Build Coastguard Worker 	}
557*4dc78e53SAndroid Build Coastguard Worker 
558*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_CARRIER]) {
559*4dc78e53SAndroid Build Coastguard Worker 		link->l_carrier = nla_get_u8(tb[IFLA_CARRIER]);
560*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_CARRIER;
561*4dc78e53SAndroid Build Coastguard Worker 	}
562*4dc78e53SAndroid Build Coastguard Worker 
563*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_CARRIER_CHANGES]) {
564*4dc78e53SAndroid Build Coastguard Worker 		link->l_carrier_changes = nla_get_u32(tb[IFLA_CARRIER_CHANGES]);
565*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_CARRIER_CHANGES;
566*4dc78e53SAndroid Build Coastguard Worker 	}
567*4dc78e53SAndroid Build Coastguard Worker 
568*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_OPERSTATE]) {
569*4dc78e53SAndroid Build Coastguard Worker 		link->l_operstate = nla_get_u8(tb[IFLA_OPERSTATE]);
570*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_OPERSTATE;
571*4dc78e53SAndroid Build Coastguard Worker 	}
572*4dc78e53SAndroid Build Coastguard Worker 
573*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_LINKMODE]) {
574*4dc78e53SAndroid Build Coastguard Worker 		link->l_linkmode = nla_get_u8(tb[IFLA_LINKMODE]);
575*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_LINKMODE;
576*4dc78e53SAndroid Build Coastguard Worker 	}
577*4dc78e53SAndroid Build Coastguard Worker 
578*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_IFALIAS]) {
579*4dc78e53SAndroid Build Coastguard Worker 		link->l_ifalias = nla_strdup(tb[IFLA_IFALIAS]);
580*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_ifalias == NULL)
581*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
582*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_IFALIAS;
583*4dc78e53SAndroid Build Coastguard Worker 	}
584*4dc78e53SAndroid Build Coastguard Worker 
585*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_NET_NS_FD]) {
586*4dc78e53SAndroid Build Coastguard Worker 		link->l_ns_fd = nla_get_u32(tb[IFLA_NET_NS_FD]);
587*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_NS_FD;
588*4dc78e53SAndroid Build Coastguard Worker 	}
589*4dc78e53SAndroid Build Coastguard Worker 
590*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_NET_NS_PID]) {
591*4dc78e53SAndroid Build Coastguard Worker 		link->l_ns_pid = nla_get_u32(tb[IFLA_NET_NS_PID]);
592*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_NS_PID;
593*4dc78e53SAndroid Build Coastguard Worker 	}
594*4dc78e53SAndroid Build Coastguard Worker 
595*4dc78e53SAndroid Build Coastguard Worker 	return 0;
596*4dc78e53SAndroid Build Coastguard Worker }
597*4dc78e53SAndroid Build Coastguard Worker 
link_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * n,struct nl_parser_param * pp)598*4dc78e53SAndroid Build Coastguard Worker static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
599*4dc78e53SAndroid Build Coastguard Worker 			   struct nlmsghdr *n, struct nl_parser_param *pp)
600*4dc78e53SAndroid Build Coastguard Worker {
601*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link = NULL;
602*4dc78e53SAndroid Build Coastguard Worker 	struct nla_policy real_link_policy[ARRAY_SIZE(rtln_link_policy)];
603*4dc78e53SAndroid Build Coastguard Worker 	struct nla_policy *link_policy = rtln_link_policy;
604*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link_af_ops *af_ops_family;
605*4dc78e53SAndroid Build Coastguard Worker 	struct ifinfomsg *ifi;
606*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *tb[IFLA_MAX+1];
607*4dc78e53SAndroid Build Coastguard Worker 	int err, family;
608*4dc78e53SAndroid Build Coastguard Worker 
609*4dc78e53SAndroid Build Coastguard Worker 	link = rtnl_link_alloc();
610*4dc78e53SAndroid Build Coastguard Worker 	if (link == NULL)
611*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
612*4dc78e53SAndroid Build Coastguard Worker 
613*4dc78e53SAndroid Build Coastguard Worker 	link->ce_msgtype = n->nlmsg_type;
614*4dc78e53SAndroid Build Coastguard Worker 
615*4dc78e53SAndroid Build Coastguard Worker 	if (!nlmsg_valid_hdr(n, sizeof(*ifi)))
616*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MSG_TOOSHORT;
617*4dc78e53SAndroid Build Coastguard Worker 
618*4dc78e53SAndroid Build Coastguard Worker 	ifi = nlmsg_data(n);
619*4dc78e53SAndroid Build Coastguard Worker 	link->l_family = family = ifi->ifi_family;
620*4dc78e53SAndroid Build Coastguard Worker 	link->l_arptype = ifi->ifi_type;
621*4dc78e53SAndroid Build Coastguard Worker 	link->l_index = ifi->ifi_index;
622*4dc78e53SAndroid Build Coastguard Worker 	link->l_flags = ifi->ifi_flags;
623*4dc78e53SAndroid Build Coastguard Worker 	link->l_change = ifi->ifi_change;
624*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask = (LINK_ATTR_FAMILY |
625*4dc78e53SAndroid Build Coastguard Worker 			 LINK_ATTR_ARPTYPE| LINK_ATTR_IFINDEX |
626*4dc78e53SAndroid Build Coastguard Worker 			 LINK_ATTR_FLAGS | LINK_ATTR_CHANGE);
627*4dc78e53SAndroid Build Coastguard Worker 
628*4dc78e53SAndroid Build Coastguard Worker 	if ((link->l_af_ops = af_lookup_and_alloc(link, family))) {
629*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_af_ops->ao_protinfo_policy) {
630*4dc78e53SAndroid Build Coastguard Worker 			_NL_STATIC_ASSERT (sizeof(rtln_link_policy) == sizeof(real_link_policy));
631*4dc78e53SAndroid Build Coastguard Worker 			memcpy(&real_link_policy, rtln_link_policy, sizeof(rtln_link_policy));
632*4dc78e53SAndroid Build Coastguard Worker 			memcpy(&real_link_policy[IFLA_PROTINFO],
633*4dc78e53SAndroid Build Coastguard Worker 			       link->l_af_ops->ao_protinfo_policy,
634*4dc78e53SAndroid Build Coastguard Worker 			       sizeof(struct nla_policy));
635*4dc78e53SAndroid Build Coastguard Worker 			link_policy = real_link_policy;
636*4dc78e53SAndroid Build Coastguard Worker 		}
637*4dc78e53SAndroid Build Coastguard Worker 	}
638*4dc78e53SAndroid Build Coastguard Worker 
639*4dc78e53SAndroid Build Coastguard Worker 	af_ops_family = link->l_af_ops;
640*4dc78e53SAndroid Build Coastguard Worker 
641*4dc78e53SAndroid Build Coastguard Worker 	err = nlmsg_parse(n, sizeof(*ifi), tb, IFLA_MAX, link_policy);
642*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
643*4dc78e53SAndroid Build Coastguard Worker 		return err;
644*4dc78e53SAndroid Build Coastguard Worker 
645*4dc78e53SAndroid Build Coastguard Worker 	err = rtnl_link_info_parse(link, tb);
646*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
647*4dc78e53SAndroid Build Coastguard Worker 		return err;
648*4dc78e53SAndroid Build Coastguard Worker 
649*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_NUM_VF]) {
650*4dc78e53SAndroid Build Coastguard Worker 		link->l_num_vf = nla_get_u32(tb[IFLA_NUM_VF]);
651*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_NUM_VF;
652*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_num_vf && tb[IFLA_VFINFO_LIST]) {
653*4dc78e53SAndroid Build Coastguard Worker 			if ((err = rtnl_link_sriov_parse_vflist(link, tb)) < 0)
654*4dc78e53SAndroid Build Coastguard Worker 				return err;
655*4dc78e53SAndroid Build Coastguard Worker 			link->ce_mask |= LINK_ATTR_VF_LIST;
656*4dc78e53SAndroid Build Coastguard Worker 		}
657*4dc78e53SAndroid Build Coastguard Worker 	}
658*4dc78e53SAndroid Build Coastguard Worker 
659*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_LINKINFO]) {
660*4dc78e53SAndroid Build Coastguard Worker 		struct nlattr *li[IFLA_INFO_MAX+1];
661*4dc78e53SAndroid Build Coastguard Worker 
662*4dc78e53SAndroid Build Coastguard Worker 		err = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO],
663*4dc78e53SAndroid Build Coastguard Worker 				       link_info_policy);
664*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0)
665*4dc78e53SAndroid Build Coastguard Worker 			return err;
666*4dc78e53SAndroid Build Coastguard Worker 
667*4dc78e53SAndroid Build Coastguard Worker 		if (li[IFLA_INFO_KIND]) {
668*4dc78e53SAndroid Build Coastguard Worker 			struct rtnl_link_info_ops *ops;
669*4dc78e53SAndroid Build Coastguard Worker 			const char *kind = nla_get_string(li[IFLA_INFO_KIND]);
670*4dc78e53SAndroid Build Coastguard Worker 			int af;
671*4dc78e53SAndroid Build Coastguard Worker 
672*4dc78e53SAndroid Build Coastguard Worker 			err = rtnl_link_set_type(link, kind);
673*4dc78e53SAndroid Build Coastguard Worker 			if (err < 0)
674*4dc78e53SAndroid Build Coastguard Worker 				return err;
675*4dc78e53SAndroid Build Coastguard Worker 
676*4dc78e53SAndroid Build Coastguard Worker 			if (   (af = nl_str2af(kind)) >= 0
677*4dc78e53SAndroid Build Coastguard Worker 			    && !link->l_af_ops
678*4dc78e53SAndroid Build Coastguard Worker 			    && (link->l_af_ops = af_lookup_and_alloc(link, af))) {
679*4dc78e53SAndroid Build Coastguard Worker 				link->l_family = af;
680*4dc78e53SAndroid Build Coastguard Worker 				if (link->l_af_ops->ao_protinfo_policy)
681*4dc78e53SAndroid Build Coastguard Worker 					tb[IFLA_PROTINFO] = (struct nlattr *)link->l_af_ops->ao_protinfo_policy;
682*4dc78e53SAndroid Build Coastguard Worker 			}
683*4dc78e53SAndroid Build Coastguard Worker 
684*4dc78e53SAndroid Build Coastguard Worker 			if (link->l_info_ops)
685*4dc78e53SAndroid Build Coastguard Worker 				release_link_info(link);
686*4dc78e53SAndroid Build Coastguard Worker 
687*4dc78e53SAndroid Build Coastguard Worker 			ops = rtnl_link_info_ops_lookup(kind);
688*4dc78e53SAndroid Build Coastguard Worker 			link->l_info_ops = ops;
689*4dc78e53SAndroid Build Coastguard Worker 
690*4dc78e53SAndroid Build Coastguard Worker 			if (ops) {
691*4dc78e53SAndroid Build Coastguard Worker 				if (ops->io_parse &&
692*4dc78e53SAndroid Build Coastguard Worker 				    (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
693*4dc78e53SAndroid Build Coastguard Worker 					err = ops->io_parse(link, li[IFLA_INFO_DATA],
694*4dc78e53SAndroid Build Coastguard Worker 							    li[IFLA_INFO_XSTATS]);
695*4dc78e53SAndroid Build Coastguard Worker 					if (err < 0)
696*4dc78e53SAndroid Build Coastguard Worker 						return err;
697*4dc78e53SAndroid Build Coastguard Worker 				} else {
698*4dc78e53SAndroid Build Coastguard Worker 					/* XXX: Warn about unparsed info? */
699*4dc78e53SAndroid Build Coastguard Worker 				}
700*4dc78e53SAndroid Build Coastguard Worker 			}
701*4dc78e53SAndroid Build Coastguard Worker 
702*4dc78e53SAndroid Build Coastguard Worker 			link->ce_mask |= LINK_ATTR_LINKINFO;
703*4dc78e53SAndroid Build Coastguard Worker 		}
704*4dc78e53SAndroid Build Coastguard Worker 
705*4dc78e53SAndroid Build Coastguard Worker 		if (li[IFLA_INFO_SLAVE_KIND]) {
706*4dc78e53SAndroid Build Coastguard Worker 			const char *kind = nla_get_string(li[IFLA_INFO_SLAVE_KIND]);
707*4dc78e53SAndroid Build Coastguard Worker 
708*4dc78e53SAndroid Build Coastguard Worker 			err = rtnl_link_set_slave_type(link, kind);
709*4dc78e53SAndroid Build Coastguard Worker 			if (err < 0)
710*4dc78e53SAndroid Build Coastguard Worker 				return err;
711*4dc78e53SAndroid Build Coastguard Worker 
712*4dc78e53SAndroid Build Coastguard Worker 			link->ce_mask |= LINK_ATTR_LINKINFO_SLAVE_KIND;
713*4dc78e53SAndroid Build Coastguard Worker 		}
714*4dc78e53SAndroid Build Coastguard Worker 	}
715*4dc78e53SAndroid Build Coastguard Worker 
716*4dc78e53SAndroid Build Coastguard Worker 	if (   tb[IFLA_PROTINFO]
717*4dc78e53SAndroid Build Coastguard Worker 	    && link->l_af_ops
718*4dc78e53SAndroid Build Coastguard Worker 	    && link->l_af_ops->ao_parse_protinfo) {
719*4dc78e53SAndroid Build Coastguard Worker 		err = link->l_af_ops->ao_parse_protinfo(link, tb[IFLA_PROTINFO],
720*4dc78e53SAndroid Build Coastguard Worker 		                                        link->l_af_data[link->l_family]);
721*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0)
722*4dc78e53SAndroid Build Coastguard Worker 			return err;
723*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_PROTINFO;
724*4dc78e53SAndroid Build Coastguard Worker 	}
725*4dc78e53SAndroid Build Coastguard Worker 
726*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_AF_SPEC]) {
727*4dc78e53SAndroid Build Coastguard Worker 		/* parsing of IFLA_AF_SPEC is dependent on the family used
728*4dc78e53SAndroid Build Coastguard Worker 		 * in the request message.
729*4dc78e53SAndroid Build Coastguard Worker 		 */
730*4dc78e53SAndroid Build Coastguard Worker 		if (   af_ops_family
731*4dc78e53SAndroid Build Coastguard Worker 		    && af_ops_family->ao_parse_af_full) {
732*4dc78e53SAndroid Build Coastguard Worker 			err = af_ops_family->ao_parse_af_full(link,
733*4dc78e53SAndroid Build Coastguard Worker 			                                      tb[IFLA_AF_SPEC],
734*4dc78e53SAndroid Build Coastguard Worker 			                                      link->l_af_data[af_ops_family->ao_family]);
735*4dc78e53SAndroid Build Coastguard Worker 			if (err < 0)
736*4dc78e53SAndroid Build Coastguard Worker 				return err;
737*4dc78e53SAndroid Build Coastguard Worker 			link->ce_mask |= LINK_ATTR_AF_SPEC;
738*4dc78e53SAndroid Build Coastguard Worker 		} else if (family == AF_UNSPEC) {
739*4dc78e53SAndroid Build Coastguard Worker 			struct nlattr *af_attr;
740*4dc78e53SAndroid Build Coastguard Worker 			int remaining;
741*4dc78e53SAndroid Build Coastguard Worker 
742*4dc78e53SAndroid Build Coastguard Worker 			nla_for_each_nested(af_attr, tb[IFLA_AF_SPEC], remaining) {
743*4dc78e53SAndroid Build Coastguard Worker 				_nl_auto_rtnl_link_af_ops struct rtnl_link_af_ops *af_ops = NULL;
744*4dc78e53SAndroid Build Coastguard Worker 
745*4dc78e53SAndroid Build Coastguard Worker 				af_ops = af_lookup_and_alloc(link, nla_type(af_attr));
746*4dc78e53SAndroid Build Coastguard Worker 				if (af_ops && af_ops->ao_parse_af) {
747*4dc78e53SAndroid Build Coastguard Worker 					char *af_data = link->l_af_data[nla_type(af_attr)];
748*4dc78e53SAndroid Build Coastguard Worker 
749*4dc78e53SAndroid Build Coastguard Worker 					err = af_ops->ao_parse_af(link, af_attr, af_data);
750*4dc78e53SAndroid Build Coastguard Worker 					if (err < 0)
751*4dc78e53SAndroid Build Coastguard Worker 						return err;
752*4dc78e53SAndroid Build Coastguard Worker 				}
753*4dc78e53SAndroid Build Coastguard Worker 			}
754*4dc78e53SAndroid Build Coastguard Worker 			link->ce_mask |= LINK_ATTR_AF_SPEC;
755*4dc78e53SAndroid Build Coastguard Worker 		} else {
756*4dc78e53SAndroid Build Coastguard Worker 			NL_DBG(3, "IFLA_AF_SPEC parsing not implemented for family %d\n",
757*4dc78e53SAndroid Build Coastguard Worker 			          family);
758*4dc78e53SAndroid Build Coastguard Worker 		}
759*4dc78e53SAndroid Build Coastguard Worker 	}
760*4dc78e53SAndroid Build Coastguard Worker 
761*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_PROMISCUITY]) {
762*4dc78e53SAndroid Build Coastguard Worker 		link->l_promiscuity = nla_get_u32(tb[IFLA_PROMISCUITY]);
763*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_PROMISCUITY;
764*4dc78e53SAndroid Build Coastguard Worker 	}
765*4dc78e53SAndroid Build Coastguard Worker 
766*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_NUM_TX_QUEUES]) {
767*4dc78e53SAndroid Build Coastguard Worker 		link->l_num_tx_queues = nla_get_u32(tb[IFLA_NUM_TX_QUEUES]);
768*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES;
769*4dc78e53SAndroid Build Coastguard Worker 	}
770*4dc78e53SAndroid Build Coastguard Worker 
771*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_NUM_RX_QUEUES]) {
772*4dc78e53SAndroid Build Coastguard Worker 		link->l_num_rx_queues = nla_get_u32(tb[IFLA_NUM_RX_QUEUES]);
773*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES;
774*4dc78e53SAndroid Build Coastguard Worker 	}
775*4dc78e53SAndroid Build Coastguard Worker 
776*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_GSO_MAX_SEGS]) {
777*4dc78e53SAndroid Build Coastguard Worker 		link->l_gso_max_segs = nla_get_u32(tb[IFLA_GSO_MAX_SEGS]);
778*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_GSO_MAX_SEGS;
779*4dc78e53SAndroid Build Coastguard Worker 	}
780*4dc78e53SAndroid Build Coastguard Worker 
781*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_GSO_MAX_SIZE]) {
782*4dc78e53SAndroid Build Coastguard Worker 		link->l_gso_max_size = nla_get_u32(tb[IFLA_GSO_MAX_SIZE]);
783*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_GSO_MAX_SIZE;
784*4dc78e53SAndroid Build Coastguard Worker 	}
785*4dc78e53SAndroid Build Coastguard Worker 
786*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_GROUP]) {
787*4dc78e53SAndroid Build Coastguard Worker 		link->l_group = nla_get_u32(tb[IFLA_GROUP]);
788*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_GROUP;
789*4dc78e53SAndroid Build Coastguard Worker 	}
790*4dc78e53SAndroid Build Coastguard Worker 
791*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_PHYS_PORT_ID]) {
792*4dc78e53SAndroid Build Coastguard Worker 		link->l_phys_port_id = nl_data_alloc_attr(tb[IFLA_PHYS_PORT_ID]);
793*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_phys_port_id == NULL)
794*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
795*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_PHYS_PORT_ID;
796*4dc78e53SAndroid Build Coastguard Worker 	}
797*4dc78e53SAndroid Build Coastguard Worker 
798*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_PHYS_PORT_NAME]) {
799*4dc78e53SAndroid Build Coastguard Worker 		nla_strlcpy(link->l_phys_port_name, tb[IFLA_PHYS_PORT_NAME], IFNAMSIZ);
800*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_PHYS_PORT_NAME;
801*4dc78e53SAndroid Build Coastguard Worker 	}
802*4dc78e53SAndroid Build Coastguard Worker 
803*4dc78e53SAndroid Build Coastguard Worker 	if (tb[IFLA_PHYS_SWITCH_ID]) {
804*4dc78e53SAndroid Build Coastguard Worker 		link->l_phys_switch_id = nl_data_alloc_attr(tb[IFLA_PHYS_SWITCH_ID]);
805*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_phys_switch_id == NULL)
806*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
807*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_PHYS_SWITCH_ID;
808*4dc78e53SAndroid Build Coastguard Worker 	}
809*4dc78e53SAndroid Build Coastguard Worker 
810*4dc78e53SAndroid Build Coastguard Worker 	return pp->pp_cb((struct nl_object *) link, pp);
811*4dc78e53SAndroid Build Coastguard Worker }
812*4dc78e53SAndroid Build Coastguard Worker 
link_request_update(struct nl_cache * cache,struct nl_sock * sk)813*4dc78e53SAndroid Build Coastguard Worker static int link_request_update(struct nl_cache *cache, struct nl_sock *sk)
814*4dc78e53SAndroid Build Coastguard Worker {
815*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_msg struct nl_msg *msg = NULL;
816*4dc78e53SAndroid Build Coastguard Worker 	int family = cache->c_iarg1;
817*4dc78e53SAndroid Build Coastguard Worker 	struct ifinfomsg hdr = { .ifi_family = family };
818*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link_af_ops *ops;
819*4dc78e53SAndroid Build Coastguard Worker 	int err;
820*4dc78e53SAndroid Build Coastguard Worker 	__u32 ext_filter_mask = RTEXT_FILTER_VF;
821*4dc78e53SAndroid Build Coastguard Worker 
822*4dc78e53SAndroid Build Coastguard Worker 	msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_DUMP);
823*4dc78e53SAndroid Build Coastguard Worker 	if (!msg)
824*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
825*4dc78e53SAndroid Build Coastguard Worker 
826*4dc78e53SAndroid Build Coastguard Worker 	if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0)
827*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MSGSIZE;
828*4dc78e53SAndroid Build Coastguard Worker 
829*4dc78e53SAndroid Build Coastguard Worker 	ops = rtnl_link_af_ops_lookup(family);
830*4dc78e53SAndroid Build Coastguard Worker 	if (ops && ops->ao_get_af) {
831*4dc78e53SAndroid Build Coastguard Worker 		err = ops->ao_get_af(msg, &ext_filter_mask);
832*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0)
833*4dc78e53SAndroid Build Coastguard Worker 			return err;
834*4dc78e53SAndroid Build Coastguard Worker 	}
835*4dc78e53SAndroid Build Coastguard Worker 
836*4dc78e53SAndroid Build Coastguard Worker 	if (ext_filter_mask) {
837*4dc78e53SAndroid Build Coastguard Worker 		err = nla_put(msg, IFLA_EXT_MASK, sizeof(ext_filter_mask), &ext_filter_mask);
838*4dc78e53SAndroid Build Coastguard Worker 		if (err < 0)
839*4dc78e53SAndroid Build Coastguard Worker 			return err;
840*4dc78e53SAndroid Build Coastguard Worker 	}
841*4dc78e53SAndroid Build Coastguard Worker 
842*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto(sk, msg);
843*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
844*4dc78e53SAndroid Build Coastguard Worker 		return 0;
845*4dc78e53SAndroid Build Coastguard Worker 
846*4dc78e53SAndroid Build Coastguard Worker 	return 0;
847*4dc78e53SAndroid Build Coastguard Worker }
848*4dc78e53SAndroid Build Coastguard Worker 
link_dump_line(struct nl_object * obj,struct nl_dump_params * p)849*4dc78e53SAndroid Build Coastguard Worker static void link_dump_line(struct nl_object *obj, struct nl_dump_params *p)
850*4dc78e53SAndroid Build Coastguard Worker {
851*4dc78e53SAndroid Build Coastguard Worker 	char buf[128];
852*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache = obj->ce_cache;
853*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link = (struct rtnl_link *) obj;
854*4dc78e53SAndroid Build Coastguard Worker 	int fetched_cache = 0;
855*4dc78e53SAndroid Build Coastguard Worker 
856*4dc78e53SAndroid Build Coastguard Worker 	if (!cache) {
857*4dc78e53SAndroid Build Coastguard Worker 		cache = nl_cache_mngt_require_safe("route/link");
858*4dc78e53SAndroid Build Coastguard Worker 		fetched_cache = 1;
859*4dc78e53SAndroid Build Coastguard Worker 	}
860*4dc78e53SAndroid Build Coastguard Worker 
861*4dc78e53SAndroid Build Coastguard Worker 	if (link->l_family != AF_UNSPEC)
862*4dc78e53SAndroid Build Coastguard Worker 		nl_dump_line(p, "%s ", nl_af2str(link->l_family, buf, sizeof(buf)));
863*4dc78e53SAndroid Build Coastguard Worker 
864*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "%s %s ", link->l_name,
865*4dc78e53SAndroid Build Coastguard Worker 		     nl_llproto2str(link->l_arptype, buf, sizeof(buf)));
866*4dc78e53SAndroid Build Coastguard Worker 
867*4dc78e53SAndroid Build Coastguard Worker 	if (link->l_addr && !nl_addr_iszero(link->l_addr))
868*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "%s ", nl_addr2str(link->l_addr, buf, sizeof(buf)));
869*4dc78e53SAndroid Build Coastguard Worker 
870*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_MASTER) {
871*4dc78e53SAndroid Build Coastguard Worker 		if (cache) {
872*4dc78e53SAndroid Build Coastguard Worker 			_nl_auto_rtnl_link struct rtnl_link *master = rtnl_link_get(cache, link->l_master);
873*4dc78e53SAndroid Build Coastguard Worker 
874*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "master %s ", master ? master->l_name : "inv");
875*4dc78e53SAndroid Build Coastguard Worker 		} else
876*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "master %d ", link->l_master);
877*4dc78e53SAndroid Build Coastguard Worker 	}
878*4dc78e53SAndroid Build Coastguard Worker 
879*4dc78e53SAndroid Build Coastguard Worker 	rtnl_link_flags2str(link->l_flags, buf, sizeof(buf));
880*4dc78e53SAndroid Build Coastguard Worker 	if (buf[0])
881*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "<%s> ", buf);
882*4dc78e53SAndroid Build Coastguard Worker 
883*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_LINK) {
884*4dc78e53SAndroid Build Coastguard Worker 		if (   cache
885*4dc78e53SAndroid Build Coastguard Worker 		    && !(link->ce_mask & LINK_ATTR_LINK_NETNSID)) {
886*4dc78e53SAndroid Build Coastguard Worker 			_nl_auto_rtnl_link struct rtnl_link *ll = rtnl_link_get(cache, link->l_link);
887*4dc78e53SAndroid Build Coastguard Worker 
888*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "slave-of %s ", ll ? ll->l_name : "NONE");
889*4dc78e53SAndroid Build Coastguard Worker 		} else
890*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "slave-of %d ", link->l_link);
891*4dc78e53SAndroid Build Coastguard Worker 	}
892*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_LINK_NETNSID)
893*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "link-netnsid %d ", link->l_link_netnsid);
894*4dc78e53SAndroid Build Coastguard Worker 
895*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_GROUP)
896*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "group %u ", link->l_group);
897*4dc78e53SAndroid Build Coastguard Worker 
898*4dc78e53SAndroid Build Coastguard Worker 	if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_LINE])
899*4dc78e53SAndroid Build Coastguard Worker 		link->l_info_ops->io_dump[NL_DUMP_LINE](link, p);
900*4dc78e53SAndroid Build Coastguard Worker 
901*4dc78e53SAndroid Build Coastguard Worker 	do_foreach_af(link, af_dump_line, p);
902*4dc78e53SAndroid Build Coastguard Worker 
903*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "\n");
904*4dc78e53SAndroid Build Coastguard Worker 
905*4dc78e53SAndroid Build Coastguard Worker 	if (fetched_cache)
906*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_put(cache);
907*4dc78e53SAndroid Build Coastguard Worker }
908*4dc78e53SAndroid Build Coastguard Worker 
link_dump_details(struct nl_object * obj,struct nl_dump_params * p)909*4dc78e53SAndroid Build Coastguard Worker static void link_dump_details(struct nl_object *obj, struct nl_dump_params *p)
910*4dc78e53SAndroid Build Coastguard Worker {
911*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link = (struct rtnl_link *) obj;
912*4dc78e53SAndroid Build Coastguard Worker 	char buf[64];
913*4dc78e53SAndroid Build Coastguard Worker 
914*4dc78e53SAndroid Build Coastguard Worker 	link_dump_line(obj, p);
915*4dc78e53SAndroid Build Coastguard Worker 
916*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "    mtu %u ", link->l_mtu);
917*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "txqlen %u weight %u ", link->l_txqlen, link->l_weight);
918*4dc78e53SAndroid Build Coastguard Worker 
919*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_QDISC)
920*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "qdisc %s ", link->l_qdisc);
921*4dc78e53SAndroid Build Coastguard Worker 
922*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_MAP && link->l_map.lm_irq)
923*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "irq %u ", link->l_map.lm_irq);
924*4dc78e53SAndroid Build Coastguard Worker 
925*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_IFINDEX)
926*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "index %u ", link->l_index);
927*4dc78e53SAndroid Build Coastguard Worker 
928*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_PROMISCUITY && link->l_promiscuity > 0)
929*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "promisc-mode (%u users) ", link->l_promiscuity);
930*4dc78e53SAndroid Build Coastguard Worker 
931*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "\n");
932*4dc78e53SAndroid Build Coastguard Worker 
933*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_IFALIAS)
934*4dc78e53SAndroid Build Coastguard Worker 		nl_dump_line(p, "    alias %s\n", link->l_ifalias);
935*4dc78e53SAndroid Build Coastguard Worker 
936*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "    ");
937*4dc78e53SAndroid Build Coastguard Worker 
938*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES)
939*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "txq %u ", link->l_num_tx_queues);
940*4dc78e53SAndroid Build Coastguard Worker 
941*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES)
942*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "rxq %u ", link->l_num_rx_queues);
943*4dc78e53SAndroid Build Coastguard Worker 
944*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_BRD)
945*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "brd %s ", nl_addr2str(link->l_bcast, buf,
946*4dc78e53SAndroid Build Coastguard Worker 						   sizeof(buf)));
947*4dc78e53SAndroid Build Coastguard Worker 
948*4dc78e53SAndroid Build Coastguard Worker 	if ((link->ce_mask & LINK_ATTR_OPERSTATE) &&
949*4dc78e53SAndroid Build Coastguard Worker 	    link->l_operstate != IF_OPER_UNKNOWN) {
950*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_operstate2str(link->l_operstate, buf, sizeof(buf));
951*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "state %s ", buf);
952*4dc78e53SAndroid Build Coastguard Worker 	}
953*4dc78e53SAndroid Build Coastguard Worker 
954*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NUM_VF)
955*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "num-vf %u ", link->l_num_vf);
956*4dc78e53SAndroid Build Coastguard Worker 
957*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "mode %s ",
958*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_mode2str(link->l_linkmode, buf, sizeof(buf)));
959*4dc78e53SAndroid Build Coastguard Worker 
960*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "carrier %s",
961*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_carrier2str(link->l_carrier, buf, sizeof(buf)));
962*4dc78e53SAndroid Build Coastguard Worker 
963*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_CARRIER_CHANGES)
964*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " carrier-changes %u", link->l_carrier_changes);
965*4dc78e53SAndroid Build Coastguard Worker 
966*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "\n");
967*4dc78e53SAndroid Build Coastguard Worker 
968*4dc78e53SAndroid Build Coastguard Worker 	if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_DETAILS])
969*4dc78e53SAndroid Build Coastguard Worker 		link->l_info_ops->io_dump[NL_DUMP_DETAILS](link, p);
970*4dc78e53SAndroid Build Coastguard Worker 
971*4dc78e53SAndroid Build Coastguard Worker 	do_foreach_af(link, af_dump_details, p);
972*4dc78e53SAndroid Build Coastguard Worker 
973*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_VF_LIST)
974*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_sriov_dump_details(link, p);
975*4dc78e53SAndroid Build Coastguard Worker }
976*4dc78e53SAndroid Build Coastguard Worker 
link_dump_stats(struct nl_object * obj,struct nl_dump_params * p)977*4dc78e53SAndroid Build Coastguard Worker static void link_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
978*4dc78e53SAndroid Build Coastguard Worker {
979*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link = (struct rtnl_link *) obj;
980*4dc78e53SAndroid Build Coastguard Worker 	char *unit, fmt[64];
981*4dc78e53SAndroid Build Coastguard Worker 	float res;
982*4dc78e53SAndroid Build Coastguard Worker 
983*4dc78e53SAndroid Build Coastguard Worker 	link_dump_details(obj, p);
984*4dc78e53SAndroid Build Coastguard Worker 
985*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "    Stats:    bytes    packets     errors "
986*4dc78e53SAndroid Build Coastguard Worker 			"   dropped   fifo-err compressed\n");
987*4dc78e53SAndroid Build Coastguard Worker 
988*4dc78e53SAndroid Build Coastguard Worker 	res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_RX_BYTES], &unit);
989*4dc78e53SAndroid Build Coastguard Worker 
990*4dc78e53SAndroid Build Coastguard Worker 	strcpy(fmt, "     RX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n");
991*4dc78e53SAndroid Build Coastguard Worker 	fmt[9] = *unit == 'B' ? '9' : '7';
992*4dc78e53SAndroid Build Coastguard Worker 
993*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, fmt, res, unit,
994*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_PACKETS],
995*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_ERRORS],
996*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_DROPPED],
997*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_FIFO_ERR],
998*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_COMPRESSED]);
999*4dc78e53SAndroid Build Coastguard Worker 
1000*4dc78e53SAndroid Build Coastguard Worker 	res = nl_cancel_down_bytes(link->l_stats[RTNL_LINK_TX_BYTES], &unit);
1001*4dc78e53SAndroid Build Coastguard Worker 
1002*4dc78e53SAndroid Build Coastguard Worker 	strcpy(fmt, "     TX %X.2f %s %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 " %10" PRIu64 "\n");
1003*4dc78e53SAndroid Build Coastguard Worker 	fmt[9] = *unit == 'B' ? '9' : '7';
1004*4dc78e53SAndroid Build Coastguard Worker 
1005*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, fmt, res, unit,
1006*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_PACKETS],
1007*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_ERRORS],
1008*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_DROPPED],
1009*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_FIFO_ERR],
1010*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_COMPRESSED]);
1011*4dc78e53SAndroid Build Coastguard Worker 
1012*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "    Errors:  length       over        crc "
1013*4dc78e53SAndroid Build Coastguard Worker 			"     frame     missed  multicast\n");
1014*4dc78e53SAndroid Build Coastguard Worker 
1015*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "     RX  %10" PRIu64 " %10" PRIu64 " %10"
1016*4dc78e53SAndroid Build Coastguard Worker 				PRIu64 " %10" PRIu64 " %10" PRIu64 " %10"
1017*4dc78e53SAndroid Build Coastguard Worker 				PRIu64 "\n",
1018*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_LEN_ERR],
1019*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_OVER_ERR],
1020*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_CRC_ERR],
1021*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_FRAME_ERR],
1022*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_RX_MISSED_ERR],
1023*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_MULTICAST]);
1024*4dc78e53SAndroid Build Coastguard Worker 
1025*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "            aborted    carrier  heartbeat "
1026*4dc78e53SAndroid Build Coastguard Worker 			"    window  collision\n");
1027*4dc78e53SAndroid Build Coastguard Worker 
1028*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "     TX  %10" PRIu64 " %10" PRIu64 " %10"
1029*4dc78e53SAndroid Build Coastguard Worker 			PRIu64 " %10" PRIu64 " %10" PRIu64 "\n",
1030*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_ABORT_ERR],
1031*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_CARRIER_ERR],
1032*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_HBEAT_ERR],
1033*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_TX_WIN_ERR],
1034*4dc78e53SAndroid Build Coastguard Worker 		link->l_stats[RTNL_LINK_COLLISIONS]);
1035*4dc78e53SAndroid Build Coastguard Worker 
1036*4dc78e53SAndroid Build Coastguard Worker 	if (link->l_info_ops && link->l_info_ops->io_dump[NL_DUMP_STATS])
1037*4dc78e53SAndroid Build Coastguard Worker 		link->l_info_ops->io_dump[NL_DUMP_STATS](link, p);
1038*4dc78e53SAndroid Build Coastguard Worker 
1039*4dc78e53SAndroid Build Coastguard Worker 	do_foreach_af(link, af_dump_stats, p);
1040*4dc78e53SAndroid Build Coastguard Worker 
1041*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_VF_LIST)
1042*4dc78e53SAndroid Build Coastguard Worker 		rtnl_link_sriov_dump_stats(link, p);
1043*4dc78e53SAndroid Build Coastguard Worker }
1044*4dc78e53SAndroid Build Coastguard Worker 
1045*4dc78e53SAndroid Build Coastguard Worker #if 0
1046*4dc78e53SAndroid Build Coastguard Worker static int link_handle_event(struct nl_object *a, struct rtnl_link_event_cb *cb)
1047*4dc78e53SAndroid Build Coastguard Worker {
1048*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *l = (struct rtnl_link *) a;
1049*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *c = dp_cache(a);
1050*4dc78e53SAndroid Build Coastguard Worker 	int nevents = 0;
1051*4dc78e53SAndroid Build Coastguard Worker 
1052*4dc78e53SAndroid Build Coastguard Worker 	if (l->l_change == ~0U) {
1053*4dc78e53SAndroid Build Coastguard Worker 		if (l->ce_msgtype == RTM_NEWLINK)
1054*4dc78e53SAndroid Build Coastguard Worker 			cb->le_register(l);
1055*4dc78e53SAndroid Build Coastguard Worker 		else
1056*4dc78e53SAndroid Build Coastguard Worker 			cb->le_unregister(l);
1057*4dc78e53SAndroid Build Coastguard Worker 
1058*4dc78e53SAndroid Build Coastguard Worker 		return 1;
1059*4dc78e53SAndroid Build Coastguard Worker 	}
1060*4dc78e53SAndroid Build Coastguard Worker 
1061*4dc78e53SAndroid Build Coastguard Worker 	if (l->l_change & IFF_SLAVE) {
1062*4dc78e53SAndroid Build Coastguard Worker 		if (l->l_flags & IFF_SLAVE) {
1063*4dc78e53SAndroid Build Coastguard Worker 			struct rtnl_link *m = rtnl_link_get(c, l->l_master);
1064*4dc78e53SAndroid Build Coastguard Worker 			cb->le_new_bonding(l, m);
1065*4dc78e53SAndroid Build Coastguard Worker 			if (m)
1066*4dc78e53SAndroid Build Coastguard Worker 				rtnl_link_put(m);
1067*4dc78e53SAndroid Build Coastguard Worker 		} else
1068*4dc78e53SAndroid Build Coastguard Worker 			cb->le_cancel_bonding(l);
1069*4dc78e53SAndroid Build Coastguard Worker 	}
1070*4dc78e53SAndroid Build Coastguard Worker 
1071*4dc78e53SAndroid Build Coastguard Worker #if 0
1072*4dc78e53SAndroid Build Coastguard Worker 	if (l->l_change & IFF_UP && l->l_change & IFF_RUNNING)
1073*4dc78e53SAndroid Build Coastguard Worker 		dp_dump_line(p, line++, "link %s changed state to %s.\n",
1074*4dc78e53SAndroid Build Coastguard Worker 			l->l_name, l->l_flags & IFF_UP ? "up" : "down");
1075*4dc78e53SAndroid Build Coastguard Worker 
1076*4dc78e53SAndroid Build Coastguard Worker 	if (l->l_change & IFF_PROMISC) {
1077*4dc78e53SAndroid Build Coastguard Worker 		dp_new_line(p, line++);
1078*4dc78e53SAndroid Build Coastguard Worker 		dp_dump(p, "link %s %s promiscuous mode.\n",
1079*4dc78e53SAndroid Build Coastguard Worker 		    l->l_name, l->l_flags & IFF_PROMISC ? "entered" : "left");
1080*4dc78e53SAndroid Build Coastguard Worker 	}
1081*4dc78e53SAndroid Build Coastguard Worker 
1082*4dc78e53SAndroid Build Coastguard Worker 	if (line == 0)
1083*4dc78e53SAndroid Build Coastguard Worker 		dp_dump_line(p, line++, "link %s sent unknown event.\n",
1084*4dc78e53SAndroid Build Coastguard Worker 			     l->l_name);
1085*4dc78e53SAndroid Build Coastguard Worker #endif
1086*4dc78e53SAndroid Build Coastguard Worker 
1087*4dc78e53SAndroid Build Coastguard Worker 	return nevents;
1088*4dc78e53SAndroid Build Coastguard Worker }
1089*4dc78e53SAndroid Build Coastguard Worker #endif
1090*4dc78e53SAndroid Build Coastguard Worker 
1091*4dc78e53SAndroid Build Coastguard Worker 
link_keygen(struct nl_object * obj,uint32_t * hashkey,uint32_t table_sz)1092*4dc78e53SAndroid Build Coastguard Worker static void link_keygen(struct nl_object *obj, uint32_t *hashkey,
1093*4dc78e53SAndroid Build Coastguard Worker         uint32_t table_sz)
1094*4dc78e53SAndroid Build Coastguard Worker {
1095*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link = (struct rtnl_link *) obj;
1096*4dc78e53SAndroid Build Coastguard Worker 	unsigned int lkey_sz;
1097*4dc78e53SAndroid Build Coastguard Worker 	struct link_hash_key {
1098*4dc78e53SAndroid Build Coastguard Worker 		uint32_t	l_index;
1099*4dc78e53SAndroid Build Coastguard Worker 		uint32_t	l_family;
1100*4dc78e53SAndroid Build Coastguard Worker 	} _nl_packed lkey;
1101*4dc78e53SAndroid Build Coastguard Worker 
1102*4dc78e53SAndroid Build Coastguard Worker 	lkey_sz = sizeof(lkey);
1103*4dc78e53SAndroid Build Coastguard Worker 	lkey.l_index = link->l_index;
1104*4dc78e53SAndroid Build Coastguard Worker 	lkey.l_family = link->l_family;
1105*4dc78e53SAndroid Build Coastguard Worker 
1106*4dc78e53SAndroid Build Coastguard Worker 	*hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz;
1107*4dc78e53SAndroid Build Coastguard Worker 
1108*4dc78e53SAndroid Build Coastguard Worker 	NL_DBG(5, "link %p key (dev %d fam %d) keysz %d, hash 0x%x\n",
1109*4dc78e53SAndroid Build Coastguard Worker 	       link, lkey.l_index, lkey.l_family, lkey_sz, *hashkey);
1110*4dc78e53SAndroid Build Coastguard Worker 
1111*4dc78e53SAndroid Build Coastguard Worker 	return;
1112*4dc78e53SAndroid Build Coastguard Worker }
1113*4dc78e53SAndroid Build Coastguard Worker 
link_compare(struct nl_object * _a,struct nl_object * _b,uint64_t attrs,int flags)1114*4dc78e53SAndroid Build Coastguard Worker static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b,
1115*4dc78e53SAndroid Build Coastguard Worker 			     uint64_t attrs, int flags)
1116*4dc78e53SAndroid Build Coastguard Worker {
1117*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *a = (struct rtnl_link *) _a;
1118*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *b = (struct rtnl_link *) _b;
1119*4dc78e53SAndroid Build Coastguard Worker 	uint64_t diff = 0;
1120*4dc78e53SAndroid Build Coastguard Worker 
1121*4dc78e53SAndroid Build Coastguard Worker #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
1122*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_IFINDEX, a->l_index != b->l_index);
1123*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_MTU, a->l_mtu != b->l_mtu);
1124*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_LINK, a->l_link != b->l_link);
1125*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_LINK_NETNSID,
1126*4dc78e53SAndroid Build Coastguard Worker 		      a->l_link_netnsid != b->l_link_netnsid);
1127*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_TXQLEN, a->l_txqlen != b->l_txqlen);
1128*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_WEIGHT, a->l_weight != b->l_weight);
1129*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_MASTER, a->l_master != b->l_master);
1130*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_FAMILY, a->l_family != b->l_family);
1131*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_OPERSTATE, a->l_operstate != b->l_operstate);
1132*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_LINKMODE, a->l_linkmode != b->l_linkmode);
1133*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_QDISC, strcmp(a->l_qdisc, b->l_qdisc));
1134*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_IFNAME, strcmp(a->l_name, b->l_name));
1135*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_ADDR, nl_addr_cmp(a->l_addr, b->l_addr));
1136*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_BRD, nl_addr_cmp(a->l_bcast, b->l_bcast));
1137*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_IFALIAS, strcmp(a->l_ifalias, b->l_ifalias));
1138*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_NUM_VF, a->l_num_vf != b->l_num_vf);
1139*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_PROMISCUITY,
1140*4dc78e53SAndroid Build Coastguard Worker 		      a->l_promiscuity != b->l_promiscuity);
1141*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_NUM_TX_QUEUES,
1142*4dc78e53SAndroid Build Coastguard Worker 		      a->l_num_tx_queues != b->l_num_tx_queues);
1143*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_NUM_RX_QUEUES,
1144*4dc78e53SAndroid Build Coastguard Worker 		      a->l_num_rx_queues != b->l_num_rx_queues);
1145*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_GROUP, a->l_group != b->l_group);
1146*4dc78e53SAndroid Build Coastguard Worker 
1147*4dc78e53SAndroid Build Coastguard Worker 	if (flags & LOOSE_COMPARISON)
1148*4dc78e53SAndroid Build Coastguard Worker 		diff |= _DIFF(LINK_ATTR_FLAGS,
1149*4dc78e53SAndroid Build Coastguard Worker 				  (a->l_flags ^ b->l_flags) & b->l_flag_mask);
1150*4dc78e53SAndroid Build Coastguard Worker 	else
1151*4dc78e53SAndroid Build Coastguard Worker 		diff |= _DIFF(LINK_ATTR_FLAGS, a->l_flags != b->l_flags);
1152*4dc78e53SAndroid Build Coastguard Worker 
1153*4dc78e53SAndroid Build Coastguard Worker 	/*
1154*4dc78e53SAndroid Build Coastguard Worker 	 * Compare LINK_ATTR_PROTINFO af_data
1155*4dc78e53SAndroid Build Coastguard Worker 	 */
1156*4dc78e53SAndroid Build Coastguard Worker 	if (a->l_family == b->l_family) {
1157*4dc78e53SAndroid Build Coastguard Worker 		if (rtnl_link_af_data_compare(a, b, a->l_family) != 0)
1158*4dc78e53SAndroid Build Coastguard Worker 			goto protinfo_mismatch;
1159*4dc78e53SAndroid Build Coastguard Worker 	}
1160*4dc78e53SAndroid Build Coastguard Worker 
1161*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_LINKINFO, rtnl_link_info_data_compare(a, b, flags) != 0);
1162*4dc78e53SAndroid Build Coastguard Worker out:
1163*4dc78e53SAndroid Build Coastguard Worker 	return diff;
1164*4dc78e53SAndroid Build Coastguard Worker 
1165*4dc78e53SAndroid Build Coastguard Worker protinfo_mismatch:
1166*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(LINK_ATTR_PROTINFO, 1);
1167*4dc78e53SAndroid Build Coastguard Worker 	goto out;
1168*4dc78e53SAndroid Build Coastguard Worker 
1169*4dc78e53SAndroid Build Coastguard Worker #undef _DIFF
1170*4dc78e53SAndroid Build Coastguard Worker }
1171*4dc78e53SAndroid Build Coastguard Worker 
1172*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl link_attrs[] = {
1173*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_MTU, mtu),
1174*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_LINK, link),
1175*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_TXQLEN, txqlen),
1176*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_WEIGHT, weight),
1177*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_MASTER, master),
1178*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_QDISC, qdisc),
1179*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_MAP, map),
1180*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_ADDR, address),
1181*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_BRD, broadcast),
1182*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_FLAGS, flags),
1183*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_IFNAME, name),
1184*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_IFINDEX, ifindex),
1185*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_FAMILY, family),
1186*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_ARPTYPE, arptype),
1187*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_STATS, stats),
1188*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_CHANGE, change),
1189*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_OPERSTATE, operstate),
1190*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_LINKMODE, linkmode),
1191*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_IFALIAS, ifalias),
1192*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_NUM_VF, num_vf),
1193*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_PROMISCUITY, promiscuity),
1194*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_NUM_TX_QUEUES, num_tx_queues),
1195*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_NUM_RX_QUEUES, num_rx_queues),
1196*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_GSO_MAX_SEGS, gso_max_segs),
1197*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_GSO_MAX_SIZE, gso_max_size),
1198*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_GROUP, group),
1199*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_CARRIER, carrier),
1200*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_CARRIER_CHANGES, carrier_changes),
1201*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_PHYS_PORT_ID, phys_port_id),
1202*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_PHYS_PORT_NAME, phys_port_name),
1203*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_PHYS_SWITCH_ID, phys_switch_id),
1204*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_NS_FD, ns_fd),
1205*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_NS_PID, ns_pid),
1206*4dc78e53SAndroid Build Coastguard Worker 	__ADD(LINK_ATTR_LINK_NETNSID, link_netnsid),
1207*4dc78e53SAndroid Build Coastguard Worker };
1208*4dc78e53SAndroid Build Coastguard Worker 
link_attrs2str(int attrs,char * buf,size_t len)1209*4dc78e53SAndroid Build Coastguard Worker static char *link_attrs2str(int attrs, char *buf, size_t len)
1210*4dc78e53SAndroid Build Coastguard Worker {
1211*4dc78e53SAndroid Build Coastguard Worker 	return __flags2str(attrs, buf, len, link_attrs,
1212*4dc78e53SAndroid Build Coastguard Worker 			   ARRAY_SIZE(link_attrs));
1213*4dc78e53SAndroid Build Coastguard Worker }
1214*4dc78e53SAndroid Build Coastguard Worker 
1215*4dc78e53SAndroid Build Coastguard Worker /**
1216*4dc78e53SAndroid Build Coastguard Worker  * @name Get / List
1217*4dc78e53SAndroid Build Coastguard Worker  * @{
1218*4dc78e53SAndroid Build Coastguard Worker  */
1219*4dc78e53SAndroid Build Coastguard Worker 
1220*4dc78e53SAndroid Build Coastguard Worker 
1221*4dc78e53SAndroid Build Coastguard Worker /**
1222*4dc78e53SAndroid Build Coastguard Worker  * Allocate link cache and fill in all configured links.
1223*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
1224*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Link address family or AF_UNSPEC
1225*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting cache.
1226*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Flags to set in link cache before filling
1227*4dc78e53SAndroid Build Coastguard Worker  *
1228*4dc78e53SAndroid Build Coastguard Worker  * Allocates and initializes a new link cache. If \c sk is valid, a netlink
1229*4dc78e53SAndroid Build Coastguard Worker  * message is sent to the kernel requesting a full dump of all configured
1230*4dc78e53SAndroid Build Coastguard Worker  * links. The returned messages are parsed and filled into the cache. If
1231*4dc78e53SAndroid Build Coastguard Worker  * the operation succeeds, the resulting cache will contain a link object for
1232*4dc78e53SAndroid Build Coastguard Worker  * each link configured in the kernel. If \c sk is NULL, returns 0 but the
1233*4dc78e53SAndroid Build Coastguard Worker  * cache is still empty.
1234*4dc78e53SAndroid Build Coastguard Worker  *
1235*4dc78e53SAndroid Build Coastguard Worker  * If \c family is set to an address family other than \c AF_UNSPEC the
1236*4dc78e53SAndroid Build Coastguard Worker  * contents of the cache can be limited to a specific address family.
1237*4dc78e53SAndroid Build Coastguard Worker  * Currently the following address families are supported:
1238*4dc78e53SAndroid Build Coastguard Worker  * - AF_BRIDGE
1239*4dc78e53SAndroid Build Coastguard Worker  * - AF_INET6
1240*4dc78e53SAndroid Build Coastguard Worker  *
1241*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_list, Get List of Links}
1242*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get()
1243*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_by_name()
1244*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1245*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_alloc_cache_flags(struct nl_sock * sk,int family,struct nl_cache ** result,unsigned int flags)1246*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_alloc_cache_flags(struct nl_sock *sk, int family,
1247*4dc78e53SAndroid Build Coastguard Worker 				struct nl_cache **result, unsigned int flags)
1248*4dc78e53SAndroid Build Coastguard Worker {
1249*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache * cache;
1250*4dc78e53SAndroid Build Coastguard Worker 	int err;
1251*4dc78e53SAndroid Build Coastguard Worker 
1252*4dc78e53SAndroid Build Coastguard Worker 	cache = nl_cache_alloc(&rtnl_link_ops);
1253*4dc78e53SAndroid Build Coastguard Worker 	if (!cache)
1254*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
1255*4dc78e53SAndroid Build Coastguard Worker 
1256*4dc78e53SAndroid Build Coastguard Worker 	cache->c_iarg1 = family;
1257*4dc78e53SAndroid Build Coastguard Worker 
1258*4dc78e53SAndroid Build Coastguard Worker 	if (flags)
1259*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_set_flags(cache, flags);
1260*4dc78e53SAndroid Build Coastguard Worker 
1261*4dc78e53SAndroid Build Coastguard Worker 	if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
1262*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_free(cache);
1263*4dc78e53SAndroid Build Coastguard Worker 		return err;
1264*4dc78e53SAndroid Build Coastguard Worker 	}
1265*4dc78e53SAndroid Build Coastguard Worker 
1266*4dc78e53SAndroid Build Coastguard Worker 	*result = cache;
1267*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1268*4dc78e53SAndroid Build Coastguard Worker }
1269*4dc78e53SAndroid Build Coastguard Worker 
1270*4dc78e53SAndroid Build Coastguard Worker /**
1271*4dc78e53SAndroid Build Coastguard Worker  * Allocate link cache and fill in all configured links.
1272*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
1273*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Link address family or AF_UNSPEC
1274*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting cache.
1275*4dc78e53SAndroid Build Coastguard Worker  *
1276*4dc78e53SAndroid Build Coastguard Worker  * Allocates and initializes a new link cache. If \c sk is valid, a netlink
1277*4dc78e53SAndroid Build Coastguard Worker  * message is sent to the kernel requesting a full dump of all configured
1278*4dc78e53SAndroid Build Coastguard Worker  * links. The returned messages are parsed and filled into the cache. If
1279*4dc78e53SAndroid Build Coastguard Worker  * the operation succeeds, the resulting cache will contain a link object for
1280*4dc78e53SAndroid Build Coastguard Worker  * each link configured in the kernel. If \c sk is NULL, returns 0 but the
1281*4dc78e53SAndroid Build Coastguard Worker  * cache is still empty.
1282*4dc78e53SAndroid Build Coastguard Worker  *
1283*4dc78e53SAndroid Build Coastguard Worker  * If \c family is set to an address family other than \c AF_UNSPEC the
1284*4dc78e53SAndroid Build Coastguard Worker  * contents of the cache can be limited to a specific address family.
1285*4dc78e53SAndroid Build Coastguard Worker  * Currently the following address families are supported:
1286*4dc78e53SAndroid Build Coastguard Worker  * - AF_BRIDGE
1287*4dc78e53SAndroid Build Coastguard Worker  * - AF_INET6
1288*4dc78e53SAndroid Build Coastguard Worker  *
1289*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_list, Get List of Links}
1290*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get()
1291*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_by_name()
1292*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1293*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_alloc_cache(struct nl_sock * sk,int family,struct nl_cache ** result)1294*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result)
1295*4dc78e53SAndroid Build Coastguard Worker {
1296*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_link_alloc_cache_flags(sk, family, result, 0);
1297*4dc78e53SAndroid Build Coastguard Worker }
1298*4dc78e53SAndroid Build Coastguard Worker 
1299*4dc78e53SAndroid Build Coastguard Worker 
1300*4dc78e53SAndroid Build Coastguard Worker /**
1301*4dc78e53SAndroid Build Coastguard Worker  * Lookup link in cache by interface index
1302*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		Link cache
1303*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
1304*4dc78e53SAndroid Build Coastguard Worker  *
1305*4dc78e53SAndroid Build Coastguard Worker  * Searches through the provided cache looking for a link with matching
1306*4dc78e53SAndroid Build Coastguard Worker  * interface index.
1307*4dc78e53SAndroid Build Coastguard Worker  *
1308*4dc78e53SAndroid Build Coastguard Worker  * @attention The reference counter of the returned link object will be
1309*4dc78e53SAndroid Build Coastguard Worker  *            incremented. Use rtnl_link_put() to release the reference.
1310*4dc78e53SAndroid Build Coastguard Worker  *
1311*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_list, Get List of Links}
1312*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_by_name()
1313*4dc78e53SAndroid Build Coastguard Worker  * @return Link object or NULL if no match was found.
1314*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get(struct nl_cache * cache,int ifindex)1315*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex)
1316*4dc78e53SAndroid Build Coastguard Worker {
1317*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link;
1318*4dc78e53SAndroid Build Coastguard Worker 
1319*4dc78e53SAndroid Build Coastguard Worker 	if (cache->c_ops != &rtnl_link_ops)
1320*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
1321*4dc78e53SAndroid Build Coastguard Worker 
1322*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(link, &cache->c_items, ce_list) {
1323*4dc78e53SAndroid Build Coastguard Worker 		if (link->l_index == ((unsigned)ifindex)) {
1324*4dc78e53SAndroid Build Coastguard Worker 			nl_object_get((struct nl_object *) link);
1325*4dc78e53SAndroid Build Coastguard Worker 			return link;
1326*4dc78e53SAndroid Build Coastguard Worker 		}
1327*4dc78e53SAndroid Build Coastguard Worker 	}
1328*4dc78e53SAndroid Build Coastguard Worker 
1329*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
1330*4dc78e53SAndroid Build Coastguard Worker }
1331*4dc78e53SAndroid Build Coastguard Worker 
1332*4dc78e53SAndroid Build Coastguard Worker /**
1333*4dc78e53SAndroid Build Coastguard Worker  * Lookup link in cache by link name
1334*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		Link cache
1335*4dc78e53SAndroid Build Coastguard Worker  * @arg name		Name of link
1336*4dc78e53SAndroid Build Coastguard Worker  *
1337*4dc78e53SAndroid Build Coastguard Worker  * Searches through the provided cache looking for a link with matching
1338*4dc78e53SAndroid Build Coastguard Worker  * link name
1339*4dc78e53SAndroid Build Coastguard Worker  *
1340*4dc78e53SAndroid Build Coastguard Worker  * @attention The reference counter of the returned link object will be
1341*4dc78e53SAndroid Build Coastguard Worker  *            incremented. Use rtnl_link_put() to release the reference.
1342*4dc78e53SAndroid Build Coastguard Worker  *
1343*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_list, Get List of Links}
1344*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get()
1345*4dc78e53SAndroid Build Coastguard Worker  * @return Link object or NULL if no match was found.
1346*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_by_name(struct nl_cache * cache,const char * name)1347*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache,
1348*4dc78e53SAndroid Build Coastguard Worker 					 const char *name)
1349*4dc78e53SAndroid Build Coastguard Worker {
1350*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link;
1351*4dc78e53SAndroid Build Coastguard Worker 
1352*4dc78e53SAndroid Build Coastguard Worker 	if (cache->c_ops != &rtnl_link_ops)
1353*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
1354*4dc78e53SAndroid Build Coastguard Worker 
1355*4dc78e53SAndroid Build Coastguard Worker 	nl_list_for_each_entry(link, &cache->c_items, ce_list) {
1356*4dc78e53SAndroid Build Coastguard Worker 		if (!strcmp(name, link->l_name)) {
1357*4dc78e53SAndroid Build Coastguard Worker 			nl_object_get((struct nl_object *) link);
1358*4dc78e53SAndroid Build Coastguard Worker 			return link;
1359*4dc78e53SAndroid Build Coastguard Worker 		}
1360*4dc78e53SAndroid Build Coastguard Worker 	}
1361*4dc78e53SAndroid Build Coastguard Worker 
1362*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
1363*4dc78e53SAndroid Build Coastguard Worker }
1364*4dc78e53SAndroid Build Coastguard Worker 
1365*4dc78e53SAndroid Build Coastguard Worker /**
1366*4dc78e53SAndroid Build Coastguard Worker  * Construct RTM_GETLINK netlink message
1367*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
1368*4dc78e53SAndroid Build Coastguard Worker  * @arg name		Name of link
1369*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting netlink message
1370*4dc78e53SAndroid Build Coastguard Worker  *
1371*4dc78e53SAndroid Build Coastguard Worker  * The behaviour of this function is identical to rtnl_link_get_kernel()
1372*4dc78e53SAndroid Build Coastguard Worker  * with the exception that it will not send the message but return it in
1373*4dc78e53SAndroid Build Coastguard Worker  * the provided return pointer instead.
1374*4dc78e53SAndroid Build Coastguard Worker  *
1375*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_kernel()
1376*4dc78e53SAndroid Build Coastguard Worker  *
1377*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1378*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_build_get_request(int ifindex,const char * name,struct nl_msg ** result)1379*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_build_get_request(int ifindex, const char *name,
1380*4dc78e53SAndroid Build Coastguard Worker 				struct nl_msg **result)
1381*4dc78e53SAndroid Build Coastguard Worker {
1382*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_msg struct nl_msg *msg = NULL;
1383*4dc78e53SAndroid Build Coastguard Worker 	struct ifinfomsg ifi;
1384*4dc78e53SAndroid Build Coastguard Worker 	__u32 vf_mask = RTEXT_FILTER_VF;
1385*4dc78e53SAndroid Build Coastguard Worker 
1386*4dc78e53SAndroid Build Coastguard Worker 	if (ifindex <= 0 && !name) {
1387*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("ifindex or name must be specified");
1388*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
1389*4dc78e53SAndroid Build Coastguard Worker 	}
1390*4dc78e53SAndroid Build Coastguard Worker 
1391*4dc78e53SAndroid Build Coastguard Worker 	memset(&ifi, 0, sizeof(ifi));
1392*4dc78e53SAndroid Build Coastguard Worker 
1393*4dc78e53SAndroid Build Coastguard Worker 	if (!(msg = nlmsg_alloc_simple(RTM_GETLINK, 0)))
1394*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
1395*4dc78e53SAndroid Build Coastguard Worker 
1396*4dc78e53SAndroid Build Coastguard Worker 	if (ifindex > 0)
1397*4dc78e53SAndroid Build Coastguard Worker 		ifi.ifi_index = ifindex;
1398*4dc78e53SAndroid Build Coastguard Worker 
1399*4dc78e53SAndroid Build Coastguard Worker 	_NL_RETURN_ON_PUT_ERR(nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO));
1400*4dc78e53SAndroid Build Coastguard Worker 
1401*4dc78e53SAndroid Build Coastguard Worker 	if (name)
1402*4dc78e53SAndroid Build Coastguard Worker 		_NL_RETURN_ON_PUT_ERR(nla_put_string(msg, IFLA_IFNAME, name));
1403*4dc78e53SAndroid Build Coastguard Worker 
1404*4dc78e53SAndroid Build Coastguard Worker 	_NL_RETURN_ON_PUT_ERR(nla_put(msg, IFLA_EXT_MASK, sizeof(vf_mask), &vf_mask));
1405*4dc78e53SAndroid Build Coastguard Worker 
1406*4dc78e53SAndroid Build Coastguard Worker 	*result = _nl_steal_pointer(&msg);
1407*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1408*4dc78e53SAndroid Build Coastguard Worker }
1409*4dc78e53SAndroid Build Coastguard Worker 
1410*4dc78e53SAndroid Build Coastguard Worker /**
1411*4dc78e53SAndroid Build Coastguard Worker  * Get a link object directly from kernel
1412*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
1413*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
1414*4dc78e53SAndroid Build Coastguard Worker  * @arg name		Name of link
1415*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting link object
1416*4dc78e53SAndroid Build Coastguard Worker  *
1417*4dc78e53SAndroid Build Coastguard Worker  * This function builds a \c RTM_GETLINK netlink message to request
1418*4dc78e53SAndroid Build Coastguard Worker  * a specific link directly from the kernel. The returned answer is
1419*4dc78e53SAndroid Build Coastguard Worker  * parsed into a struct rtnl_link object and returned via the result
1420*4dc78e53SAndroid Build Coastguard Worker  * pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was
1421*4dc78e53SAndroid Build Coastguard Worker  * found.
1422*4dc78e53SAndroid Build Coastguard Worker  *
1423*4dc78e53SAndroid Build Coastguard Worker  * Older kernels do not support lookup by name. In that case, libnl
1424*4dc78e53SAndroid Build Coastguard Worker  * will fail with -NLE_OPNOTSUPP. Note that previous version of libnl
1425*4dc78e53SAndroid Build Coastguard Worker  * failed in this case with -NLE_INVAL. You can check libnl behavior
1426*4dc78e53SAndroid Build Coastguard Worker  * using NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP capability.
1427*4dc78e53SAndroid Build Coastguard Worker  *
1428*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_direct_lookup, Lookup Single Link (Direct Lookup)}
1429*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1430*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_kernel(struct nl_sock * sk,int ifindex,const char * name,struct rtnl_link ** result)1431*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name,
1432*4dc78e53SAndroid Build Coastguard Worker 			 struct rtnl_link **result)
1433*4dc78e53SAndroid Build Coastguard Worker {
1434*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link = NULL;
1435*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_msg struct nl_msg *msg = NULL;
1436*4dc78e53SAndroid Build Coastguard Worker 	int err;
1437*4dc78e53SAndroid Build Coastguard Worker 	int syserr;
1438*4dc78e53SAndroid Build Coastguard Worker 
1439*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0)
1440*4dc78e53SAndroid Build Coastguard Worker 		return err;
1441*4dc78e53SAndroid Build Coastguard Worker 
1442*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto(sk, msg);
1443*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
1444*4dc78e53SAndroid Build Coastguard Worker 		return err;
1445*4dc78e53SAndroid Build Coastguard Worker 
1446*4dc78e53SAndroid Build Coastguard Worker 	err = nl_pickup_keep_syserr(sk, link_msg_parser, (struct nl_object **) &link, &syserr);
1447*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0) {
1448*4dc78e53SAndroid Build Coastguard Worker 		if (   syserr == -EINVAL
1449*4dc78e53SAndroid Build Coastguard Worker 		    && ifindex <= 0
1450*4dc78e53SAndroid Build Coastguard Worker 		    && name
1451*4dc78e53SAndroid Build Coastguard Worker 		    && *name) {
1452*4dc78e53SAndroid Build Coastguard Worker 			/* Older kernels do not support lookup by ifname. This was added
1453*4dc78e53SAndroid Build Coastguard Worker 			 * by commit kernel a3d1289126e7b14307074b76bf1677015ea5036f .
1454*4dc78e53SAndroid Build Coastguard Worker 			 * Detect this error case and return NLE_OPNOTSUPP instead of
1455*4dc78e53SAndroid Build Coastguard Worker 			 * NLE_INVAL. */
1456*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_OPNOTSUPP;
1457*4dc78e53SAndroid Build Coastguard Worker 		}
1458*4dc78e53SAndroid Build Coastguard Worker 		return err;
1459*4dc78e53SAndroid Build Coastguard Worker 	}
1460*4dc78e53SAndroid Build Coastguard Worker 
1461*4dc78e53SAndroid Build Coastguard Worker 	/* If an object has been returned, we also need to wait for the ACK */
1462*4dc78e53SAndroid Build Coastguard Worker 	if (err == 0 && link)
1463*4dc78e53SAndroid Build Coastguard Worker 		wait_for_ack(sk);
1464*4dc78e53SAndroid Build Coastguard Worker 
1465*4dc78e53SAndroid Build Coastguard Worker 	*result = _nl_steal_pointer(&link);
1466*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1467*4dc78e53SAndroid Build Coastguard Worker }
1468*4dc78e53SAndroid Build Coastguard Worker 
1469*4dc78e53SAndroid Build Coastguard Worker /**
1470*4dc78e53SAndroid Build Coastguard Worker  * Translate interface index to corresponding link name
1471*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		Link cache
1472*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
1473*4dc78e53SAndroid Build Coastguard Worker  * @arg dst		String to store name
1474*4dc78e53SAndroid Build Coastguard Worker  * @arg len		Length of destination string
1475*4dc78e53SAndroid Build Coastguard Worker  *
1476*4dc78e53SAndroid Build Coastguard Worker  * Translates the specified interface index to the corresponding
1477*4dc78e53SAndroid Build Coastguard Worker  * link name and stores the name in the destination string.
1478*4dc78e53SAndroid Build Coastguard Worker  *
1479*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_translate_ifindex, Translating interface index to link name}
1480*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_name2i()
1481*4dc78e53SAndroid Build Coastguard Worker  * @return Name of link or NULL if no match was found.
1482*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_i2name(struct nl_cache * cache,int ifindex,char * dst,size_t len)1483*4dc78e53SAndroid Build Coastguard Worker char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst,
1484*4dc78e53SAndroid Build Coastguard Worker 			size_t len)
1485*4dc78e53SAndroid Build Coastguard Worker {
1486*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link = NULL;
1487*4dc78e53SAndroid Build Coastguard Worker 
1488*4dc78e53SAndroid Build Coastguard Worker 	link = rtnl_link_get(cache, ifindex);
1489*4dc78e53SAndroid Build Coastguard Worker 	if (link) {
1490*4dc78e53SAndroid Build Coastguard Worker 		_nl_strncpy_trunc(dst, link->l_name, len);
1491*4dc78e53SAndroid Build Coastguard Worker 		return dst;
1492*4dc78e53SAndroid Build Coastguard Worker 	}
1493*4dc78e53SAndroid Build Coastguard Worker 
1494*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
1495*4dc78e53SAndroid Build Coastguard Worker }
1496*4dc78e53SAndroid Build Coastguard Worker 
1497*4dc78e53SAndroid Build Coastguard Worker /**
1498*4dc78e53SAndroid Build Coastguard Worker  * Translate link name to corresponding interface index
1499*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		Link cache
1500*4dc78e53SAndroid Build Coastguard Worker  * @arg name		Name of link
1501*4dc78e53SAndroid Build Coastguard Worker  *
1502*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_translate_ifindex, Translating interface index to link name}
1503*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_i2name()
1504*4dc78e53SAndroid Build Coastguard Worker  * @return Interface index or 0 if no match was found.
1505*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_name2i(struct nl_cache * cache,const char * name)1506*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_name2i(struct nl_cache *cache, const char *name)
1507*4dc78e53SAndroid Build Coastguard Worker {
1508*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link = NULL;
1509*4dc78e53SAndroid Build Coastguard Worker 
1510*4dc78e53SAndroid Build Coastguard Worker 	link = rtnl_link_get_by_name(cache, name);
1511*4dc78e53SAndroid Build Coastguard Worker 	if (link)
1512*4dc78e53SAndroid Build Coastguard Worker 		return link->l_index;
1513*4dc78e53SAndroid Build Coastguard Worker 
1514*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1515*4dc78e53SAndroid Build Coastguard Worker }
1516*4dc78e53SAndroid Build Coastguard Worker 
1517*4dc78e53SAndroid Build Coastguard Worker /** @} */
1518*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_fill_info(struct nl_msg * msg,struct rtnl_link * link)1519*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_fill_info(struct nl_msg *msg, struct rtnl_link *link)
1520*4dc78e53SAndroid Build Coastguard Worker {
1521*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_ADDR)
1522*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_ADDR(msg, IFLA_ADDRESS, link->l_addr);
1523*4dc78e53SAndroid Build Coastguard Worker 
1524*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_BRD)
1525*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_ADDR(msg, IFLA_BROADCAST, link->l_bcast);
1526*4dc78e53SAndroid Build Coastguard Worker 
1527*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_MTU)
1528*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_MTU, link->l_mtu);
1529*4dc78e53SAndroid Build Coastguard Worker 
1530*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_TXQLEN)
1531*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_TXQLEN, link->l_txqlen);
1532*4dc78e53SAndroid Build Coastguard Worker 
1533*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_WEIGHT)
1534*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_WEIGHT, link->l_weight);
1535*4dc78e53SAndroid Build Coastguard Worker 
1536*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_IFNAME)
1537*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_STRING(msg, IFLA_IFNAME, link->l_name);
1538*4dc78e53SAndroid Build Coastguard Worker 
1539*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_OPERSTATE)
1540*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, IFLA_OPERSTATE, link->l_operstate);
1541*4dc78e53SAndroid Build Coastguard Worker 
1542*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_CARRIER)
1543*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, IFLA_CARRIER, link->l_carrier);
1544*4dc78e53SAndroid Build Coastguard Worker 
1545*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_LINKMODE)
1546*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, IFLA_LINKMODE, link->l_linkmode);
1547*4dc78e53SAndroid Build Coastguard Worker 
1548*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_IFALIAS)
1549*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias);
1550*4dc78e53SAndroid Build Coastguard Worker 
1551*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_LINK)
1552*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_LINK, link->l_link);
1553*4dc78e53SAndroid Build Coastguard Worker 
1554*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_LINK_NETNSID)
1555*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_S32(msg, IFLA_LINK_NETNSID, link->l_link_netnsid);
1556*4dc78e53SAndroid Build Coastguard Worker 
1557*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_MASTER)
1558*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_MASTER, link->l_master);
1559*4dc78e53SAndroid Build Coastguard Worker 
1560*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NUM_TX_QUEUES)
1561*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_NUM_TX_QUEUES, link->l_num_tx_queues);
1562*4dc78e53SAndroid Build Coastguard Worker 
1563*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NUM_RX_QUEUES)
1564*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_NUM_RX_QUEUES, link->l_num_rx_queues);
1565*4dc78e53SAndroid Build Coastguard Worker 
1566*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NS_FD)
1567*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_NET_NS_FD, link->l_ns_fd);
1568*4dc78e53SAndroid Build Coastguard Worker 
1569*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NS_PID)
1570*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_NET_NS_PID, link->l_ns_pid);
1571*4dc78e53SAndroid Build Coastguard Worker 
1572*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1573*4dc78e53SAndroid Build Coastguard Worker 
1574*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
1575*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_MSGSIZE;
1576*4dc78e53SAndroid Build Coastguard Worker }
1577*4dc78e53SAndroid Build Coastguard Worker 
build_link_msg(int cmd,struct ifinfomsg * hdr,struct rtnl_link * link,int flags,struct nl_msg ** result)1578*4dc78e53SAndroid Build Coastguard Worker static int build_link_msg(int cmd, struct ifinfomsg *hdr,
1579*4dc78e53SAndroid Build Coastguard Worker 			  struct rtnl_link *link, int flags, struct nl_msg **result)
1580*4dc78e53SAndroid Build Coastguard Worker {
1581*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_msg struct nl_msg *msg = NULL;
1582*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *af_spec;
1583*4dc78e53SAndroid Build Coastguard Worker 
1584*4dc78e53SAndroid Build Coastguard Worker 	msg = nlmsg_alloc_simple(cmd, flags);
1585*4dc78e53SAndroid Build Coastguard Worker 	if (!msg)
1586*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
1587*4dc78e53SAndroid Build Coastguard Worker 
1588*4dc78e53SAndroid Build Coastguard Worker 	if (nlmsg_append(msg, hdr, sizeof(*hdr), NLMSG_ALIGNTO) < 0)
1589*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
1590*4dc78e53SAndroid Build Coastguard Worker 
1591*4dc78e53SAndroid Build Coastguard Worker 	if (rtnl_link_fill_info(msg, link))
1592*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
1593*4dc78e53SAndroid Build Coastguard Worker 
1594*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_GROUP)
1595*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, IFLA_GROUP, link->l_group);
1596*4dc78e53SAndroid Build Coastguard Worker 
1597*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & (LINK_ATTR_LINKINFO|LINK_ATTR_LINKINFO_SLAVE_KIND)) {
1598*4dc78e53SAndroid Build Coastguard Worker 		struct nlattr *info;
1599*4dc78e53SAndroid Build Coastguard Worker 
1600*4dc78e53SAndroid Build Coastguard Worker 		if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
1601*4dc78e53SAndroid Build Coastguard Worker 			goto nla_put_failure;
1602*4dc78e53SAndroid Build Coastguard Worker 
1603*4dc78e53SAndroid Build Coastguard Worker 		if (link->ce_mask & LINK_ATTR_LINKINFO) {
1604*4dc78e53SAndroid Build Coastguard Worker 			NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind);
1605*4dc78e53SAndroid Build Coastguard Worker 
1606*4dc78e53SAndroid Build Coastguard Worker 			if (link->l_info_ops) {
1607*4dc78e53SAndroid Build Coastguard Worker 				if (link->l_info_ops->io_put_attrs &&
1608*4dc78e53SAndroid Build Coastguard Worker 				    link->l_info_ops->io_put_attrs(msg, link) < 0)
1609*4dc78e53SAndroid Build Coastguard Worker 					goto nla_put_failure;
1610*4dc78e53SAndroid Build Coastguard Worker 			}
1611*4dc78e53SAndroid Build Coastguard Worker 		}
1612*4dc78e53SAndroid Build Coastguard Worker 
1613*4dc78e53SAndroid Build Coastguard Worker 		if (link->ce_mask & LINK_ATTR_LINKINFO_SLAVE_KIND) {
1614*4dc78e53SAndroid Build Coastguard Worker 			NLA_PUT_STRING(msg, IFLA_INFO_SLAVE_KIND, link->l_info_slave_kind);
1615*4dc78e53SAndroid Build Coastguard Worker 		}
1616*4dc78e53SAndroid Build Coastguard Worker 
1617*4dc78e53SAndroid Build Coastguard Worker 		nla_nest_end(msg, info);
1618*4dc78e53SAndroid Build Coastguard Worker 	}
1619*4dc78e53SAndroid Build Coastguard Worker 
1620*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_VF_LIST) {
1621*4dc78e53SAndroid Build Coastguard Worker 		if (rtnl_link_sriov_fill_vflist(msg, link) < 0)
1622*4dc78e53SAndroid Build Coastguard Worker 			goto nla_put_failure;
1623*4dc78e53SAndroid Build Coastguard Worker 	}
1624*4dc78e53SAndroid Build Coastguard Worker 
1625*4dc78e53SAndroid Build Coastguard Worker 	if (do_foreach_af(link, af_fill_pi, msg) < 0)
1626*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
1627*4dc78e53SAndroid Build Coastguard Worker 
1628*4dc78e53SAndroid Build Coastguard Worker 	if (!(af_spec = nla_nest_start(msg, IFLA_AF_SPEC)))
1629*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
1630*4dc78e53SAndroid Build Coastguard Worker 
1631*4dc78e53SAndroid Build Coastguard Worker 	if (do_foreach_af(link, af_fill, msg) < 0)
1632*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
1633*4dc78e53SAndroid Build Coastguard Worker 
1634*4dc78e53SAndroid Build Coastguard Worker 	nla_nest_end(msg, af_spec);
1635*4dc78e53SAndroid Build Coastguard Worker 
1636*4dc78e53SAndroid Build Coastguard Worker 	*result = _nl_steal_pointer(&msg);
1637*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1638*4dc78e53SAndroid Build Coastguard Worker 
1639*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
1640*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_MSGSIZE;
1641*4dc78e53SAndroid Build Coastguard Worker }
1642*4dc78e53SAndroid Build Coastguard Worker 
1643*4dc78e53SAndroid Build Coastguard Worker /**
1644*4dc78e53SAndroid Build Coastguard Worker  * @name Add / Modify
1645*4dc78e53SAndroid Build Coastguard Worker  * @{
1646*4dc78e53SAndroid Build Coastguard Worker  */
1647*4dc78e53SAndroid Build Coastguard Worker 
1648*4dc78e53SAndroid Build Coastguard Worker /**
1649*4dc78e53SAndroid Build Coastguard Worker  * Build a netlink message requesting the addition of new virtual link
1650*4dc78e53SAndroid Build Coastguard Worker  * @arg link		new link to add
1651*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
1652*4dc78e53SAndroid Build Coastguard Worker  * @arg result		pointer to store resulting netlink message
1653*4dc78e53SAndroid Build Coastguard Worker  *
1654*4dc78e53SAndroid Build Coastguard Worker  * The behaviour of this function is identical to rtnl_link_add() with
1655*4dc78e53SAndroid Build Coastguard Worker  * the exception that it will not send the message but return it in the
1656*4dc78e53SAndroid Build Coastguard Worker  * provided return pointer instead.
1657*4dc78e53SAndroid Build Coastguard Worker  *
1658*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_add()
1659*4dc78e53SAndroid Build Coastguard Worker  *
1660*4dc78e53SAndroid Build Coastguard Worker  * @note This operation is not supported on all kernel versions.
1661*4dc78e53SAndroid Build Coastguard Worker  *
1662*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1663*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_build_add_request(struct rtnl_link * link,int flags,struct nl_msg ** result)1664*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_build_add_request(struct rtnl_link *link, int flags,
1665*4dc78e53SAndroid Build Coastguard Worker 				struct nl_msg **result)
1666*4dc78e53SAndroid Build Coastguard Worker {
1667*4dc78e53SAndroid Build Coastguard Worker 	struct ifinfomsg ifi = {
1668*4dc78e53SAndroid Build Coastguard Worker 		.ifi_family = link->l_family,
1669*4dc78e53SAndroid Build Coastguard Worker 		.ifi_index = link->l_index,
1670*4dc78e53SAndroid Build Coastguard Worker 		.ifi_flags = link->l_flags,
1671*4dc78e53SAndroid Build Coastguard Worker 		.ifi_change = link->l_flag_mask,
1672*4dc78e53SAndroid Build Coastguard Worker 	};
1673*4dc78e53SAndroid Build Coastguard Worker 
1674*4dc78e53SAndroid Build Coastguard Worker 	return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result);
1675*4dc78e53SAndroid Build Coastguard Worker }
1676*4dc78e53SAndroid Build Coastguard Worker 
1677*4dc78e53SAndroid Build Coastguard Worker /**
1678*4dc78e53SAndroid Build Coastguard Worker  * Add virtual link
1679*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		netlink socket.
1680*4dc78e53SAndroid Build Coastguard Worker  * @arg link		new link to add
1681*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
1682*4dc78e53SAndroid Build Coastguard Worker  *
1683*4dc78e53SAndroid Build Coastguard Worker  * Builds a \c RTM_NEWLINK netlink message requesting the addition of
1684*4dc78e53SAndroid Build Coastguard Worker  * a new virtual link.
1685*4dc78e53SAndroid Build Coastguard Worker  *
1686*4dc78e53SAndroid Build Coastguard Worker  * After sending, the function will wait for the ACK or an eventual
1687*4dc78e53SAndroid Build Coastguard Worker  * error message to be received and will therefore block until the
1688*4dc78e53SAndroid Build Coastguard Worker  * operation has been completed.
1689*4dc78e53SAndroid Build Coastguard Worker  *
1690*4dc78e53SAndroid Build Coastguard Worker  * @copydoc auto_ack_warning
1691*4dc78e53SAndroid Build Coastguard Worker  *
1692*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1693*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_add(struct nl_sock * sk,struct rtnl_link * link,int flags)1694*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
1695*4dc78e53SAndroid Build Coastguard Worker {
1696*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
1697*4dc78e53SAndroid Build Coastguard Worker 	int err;
1698*4dc78e53SAndroid Build Coastguard Worker 
1699*4dc78e53SAndroid Build Coastguard Worker 	err = rtnl_link_build_add_request(link, flags, &msg);
1700*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
1701*4dc78e53SAndroid Build Coastguard Worker 		return err;
1702*4dc78e53SAndroid Build Coastguard Worker 
1703*4dc78e53SAndroid Build Coastguard Worker 	return nl_send_sync(sk, msg);
1704*4dc78e53SAndroid Build Coastguard Worker }
1705*4dc78e53SAndroid Build Coastguard Worker 
1706*4dc78e53SAndroid Build Coastguard Worker /**
1707*4dc78e53SAndroid Build Coastguard Worker  * Build a netlink message requesting the modification of link
1708*4dc78e53SAndroid Build Coastguard Worker  * @arg orig		original link to change
1709*4dc78e53SAndroid Build Coastguard Worker  * @arg changes		link containing the changes to be made
1710*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
1711*4dc78e53SAndroid Build Coastguard Worker  * @arg result		pointer to store resulting netlink message
1712*4dc78e53SAndroid Build Coastguard Worker  *
1713*4dc78e53SAndroid Build Coastguard Worker  * The behaviour of this function is identical to rtnl_link_change() with
1714*4dc78e53SAndroid Build Coastguard Worker  * the exception that it will not send the message but return it in the
1715*4dc78e53SAndroid Build Coastguard Worker  * provided return pointer instead.
1716*4dc78e53SAndroid Build Coastguard Worker  *
1717*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_change()
1718*4dc78e53SAndroid Build Coastguard Worker  *
1719*4dc78e53SAndroid Build Coastguard Worker  * @note The resulting message will have message type set to RTM_NEWLINK
1720*4dc78e53SAndroid Build Coastguard Worker  *       which may not work with older kernels. You may have to modify it
1721*4dc78e53SAndroid Build Coastguard Worker  *       to RTM_SETLINK (does not allow changing link info attributes) to
1722*4dc78e53SAndroid Build Coastguard Worker  *       have the change request work with older kernels.
1723*4dc78e53SAndroid Build Coastguard Worker  *
1724*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1725*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_build_change_request(struct rtnl_link * orig,struct rtnl_link * changes,int flags,struct nl_msg ** result)1726*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_build_change_request(struct rtnl_link *orig,
1727*4dc78e53SAndroid Build Coastguard Worker 				   struct rtnl_link *changes, int flags,
1728*4dc78e53SAndroid Build Coastguard Worker 				   struct nl_msg **result)
1729*4dc78e53SAndroid Build Coastguard Worker {
1730*4dc78e53SAndroid Build Coastguard Worker 	struct ifinfomsg ifi = {
1731*4dc78e53SAndroid Build Coastguard Worker 		.ifi_family = orig->l_family,
1732*4dc78e53SAndroid Build Coastguard Worker 		.ifi_index = orig->l_index,
1733*4dc78e53SAndroid Build Coastguard Worker 	};
1734*4dc78e53SAndroid Build Coastguard Worker 	int err, rt;
1735*4dc78e53SAndroid Build Coastguard Worker 
1736*4dc78e53SAndroid Build Coastguard Worker 	if (changes->ce_mask & LINK_ATTR_FLAGS) {
1737*4dc78e53SAndroid Build Coastguard Worker 		ifi.ifi_flags = orig->l_flags & ~changes->l_flag_mask;
1738*4dc78e53SAndroid Build Coastguard Worker 		ifi.ifi_flags |= changes->l_flags;
1739*4dc78e53SAndroid Build Coastguard Worker 		ifi.ifi_change = changes->l_flag_mask;
1740*4dc78e53SAndroid Build Coastguard Worker 	}
1741*4dc78e53SAndroid Build Coastguard Worker 
1742*4dc78e53SAndroid Build Coastguard Worker 	if (changes->l_family && changes->l_family != orig->l_family) {
1743*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("link change: family is immutable");
1744*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_IMMUTABLE;
1745*4dc78e53SAndroid Build Coastguard Worker 	}
1746*4dc78e53SAndroid Build Coastguard Worker 
1747*4dc78e53SAndroid Build Coastguard Worker 	/* Avoid unnecessary name change requests */
1748*4dc78e53SAndroid Build Coastguard Worker 	if (orig->ce_mask & LINK_ATTR_IFINDEX &&
1749*4dc78e53SAndroid Build Coastguard Worker 	    orig->ce_mask & LINK_ATTR_IFNAME &&
1750*4dc78e53SAndroid Build Coastguard Worker 	    changes->ce_mask & LINK_ATTR_IFNAME &&
1751*4dc78e53SAndroid Build Coastguard Worker 	    !strcmp(orig->l_name, changes->l_name))
1752*4dc78e53SAndroid Build Coastguard Worker 		changes->ce_mask &= ~LINK_ATTR_IFNAME;
1753*4dc78e53SAndroid Build Coastguard Worker 
1754*4dc78e53SAndroid Build Coastguard Worker 	rt = af_request_type(orig->l_family, changes);
1755*4dc78e53SAndroid Build Coastguard Worker 
1756*4dc78e53SAndroid Build Coastguard Worker 	if ((err = build_link_msg(rt, &ifi, changes, flags, result)) < 0)
1757*4dc78e53SAndroid Build Coastguard Worker 		return err;
1758*4dc78e53SAndroid Build Coastguard Worker 
1759*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1760*4dc78e53SAndroid Build Coastguard Worker }
1761*4dc78e53SAndroid Build Coastguard Worker 
1762*4dc78e53SAndroid Build Coastguard Worker /**
1763*4dc78e53SAndroid Build Coastguard Worker  * Change link
1764*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		netlink socket.
1765*4dc78e53SAndroid Build Coastguard Worker  * @arg orig		original link to be changed
1766*4dc78e53SAndroid Build Coastguard Worker  * @arg changes		link containing the changes to be made
1767*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
1768*4dc78e53SAndroid Build Coastguard Worker  *
1769*4dc78e53SAndroid Build Coastguard Worker  * Builds a \c RTM_NEWLINK netlink message requesting the change of
1770*4dc78e53SAndroid Build Coastguard Worker  * a network link. If -EOPNOTSUPP is returned by the kernel, the
1771*4dc78e53SAndroid Build Coastguard Worker  * message type will be changed to \c RTM_SETLINK and the message is
1772*4dc78e53SAndroid Build Coastguard Worker  * resent to work around older kernel versions.
1773*4dc78e53SAndroid Build Coastguard Worker  *
1774*4dc78e53SAndroid Build Coastguard Worker  * The link to be changed is looked up based on the interface index
1775*4dc78e53SAndroid Build Coastguard Worker  * supplied in the \p orig link. Optionaly the link name is used but
1776*4dc78e53SAndroid Build Coastguard Worker  * only if no interface index is provided, otherwise providing an
1777*4dc78e53SAndroid Build Coastguard Worker  * link name will result in the link name being changed.
1778*4dc78e53SAndroid Build Coastguard Worker  *
1779*4dc78e53SAndroid Build Coastguard Worker  * If no matching link exists, the function will return
1780*4dc78e53SAndroid Build Coastguard Worker  * -NLE_OBJ_NOTFOUND.
1781*4dc78e53SAndroid Build Coastguard Worker  *
1782*4dc78e53SAndroid Build Coastguard Worker  * After sending, the function will wait for the ACK or an eventual
1783*4dc78e53SAndroid Build Coastguard Worker  * error message to be received and will therefore block until the
1784*4dc78e53SAndroid Build Coastguard Worker  * operation has been completed.
1785*4dc78e53SAndroid Build Coastguard Worker  *
1786*4dc78e53SAndroid Build Coastguard Worker  * @copydoc auto_ack_warning
1787*4dc78e53SAndroid Build Coastguard Worker  *
1788*4dc78e53SAndroid Build Coastguard Worker  * @note The link name can only be changed if the link has been put
1789*4dc78e53SAndroid Build Coastguard Worker  *       in opertional down state. (~IF_UP)
1790*4dc78e53SAndroid Build Coastguard Worker  *
1791*4dc78e53SAndroid Build Coastguard Worker  * @note On versions up to 3.4.0, \c NLE_SEQ_MISMATCH would be returned if the
1792*4dc78e53SAndroid Build Coastguard Worker  *       kernel does not supports \c RTM_NEWLINK. It is advised to ignore the
1793*4dc78e53SAndroid Build Coastguard Worker  *       error code if you cannot upgrade the library.
1794*4dc78e53SAndroid Build Coastguard Worker  *
1795*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1796*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_change(struct nl_sock * sk,struct rtnl_link * orig,struct rtnl_link * changes,int flags)1797*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_change(struct nl_sock *sk, struct rtnl_link *orig,
1798*4dc78e53SAndroid Build Coastguard Worker 		     struct rtnl_link *changes, int flags)
1799*4dc78e53SAndroid Build Coastguard Worker {
1800*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_msg struct nl_msg *msg = NULL;
1801*4dc78e53SAndroid Build Coastguard Worker 	int err;
1802*4dc78e53SAndroid Build Coastguard Worker 
1803*4dc78e53SAndroid Build Coastguard Worker 	err = rtnl_link_build_change_request(orig, changes, flags, &msg);
1804*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
1805*4dc78e53SAndroid Build Coastguard Worker 		return err;
1806*4dc78e53SAndroid Build Coastguard Worker 
1807*4dc78e53SAndroid Build Coastguard Worker 	BUG_ON(msg->nm_nlh->nlmsg_seq != NL_AUTO_SEQ);
1808*4dc78e53SAndroid Build Coastguard Worker retry:
1809*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto_complete(sk, msg);
1810*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
1811*4dc78e53SAndroid Build Coastguard Worker 		return err;
1812*4dc78e53SAndroid Build Coastguard Worker 
1813*4dc78e53SAndroid Build Coastguard Worker 	err = wait_for_ack(sk);
1814*4dc78e53SAndroid Build Coastguard Worker 	if (   err == -NLE_OPNOTSUPP
1815*4dc78e53SAndroid Build Coastguard Worker 	    && msg->nm_nlh->nlmsg_type == RTM_NEWLINK) {
1816*4dc78e53SAndroid Build Coastguard Worker 		msg->nm_nlh->nlmsg_type = RTM_SETLINK;
1817*4dc78e53SAndroid Build Coastguard Worker 		msg->nm_nlh->nlmsg_seq = NL_AUTO_SEQ;
1818*4dc78e53SAndroid Build Coastguard Worker 		goto retry;
1819*4dc78e53SAndroid Build Coastguard Worker 	}
1820*4dc78e53SAndroid Build Coastguard Worker 
1821*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
1822*4dc78e53SAndroid Build Coastguard Worker 		return err;
1823*4dc78e53SAndroid Build Coastguard Worker 
1824*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1825*4dc78e53SAndroid Build Coastguard Worker }
1826*4dc78e53SAndroid Build Coastguard Worker 
1827*4dc78e53SAndroid Build Coastguard Worker /** @} */
1828*4dc78e53SAndroid Build Coastguard Worker 
1829*4dc78e53SAndroid Build Coastguard Worker /**
1830*4dc78e53SAndroid Build Coastguard Worker  * @name Delete
1831*4dc78e53SAndroid Build Coastguard Worker  * @{
1832*4dc78e53SAndroid Build Coastguard Worker  */
1833*4dc78e53SAndroid Build Coastguard Worker 
1834*4dc78e53SAndroid Build Coastguard Worker /**
1835*4dc78e53SAndroid Build Coastguard Worker  * Build a netlink message requesting the deletion of a link
1836*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link to delete
1837*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting netlink message
1838*4dc78e53SAndroid Build Coastguard Worker  *
1839*4dc78e53SAndroid Build Coastguard Worker  * The behaviour of this function is identical to rtnl_link_delete() with
1840*4dc78e53SAndroid Build Coastguard Worker  * the exception that it will not send the message but return it in the
1841*4dc78e53SAndroid Build Coastguard Worker  * provided return pointer instead.
1842*4dc78e53SAndroid Build Coastguard Worker  *
1843*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_delete()
1844*4dc78e53SAndroid Build Coastguard Worker  *
1845*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1846*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_build_delete_request(const struct rtnl_link * link,struct nl_msg ** result)1847*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_build_delete_request(const struct rtnl_link *link,
1848*4dc78e53SAndroid Build Coastguard Worker 				   struct nl_msg **result)
1849*4dc78e53SAndroid Build Coastguard Worker {
1850*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_msg struct nl_msg *msg = NULL;
1851*4dc78e53SAndroid Build Coastguard Worker 	struct ifinfomsg ifi = {
1852*4dc78e53SAndroid Build Coastguard Worker 		.ifi_index = link->l_index,
1853*4dc78e53SAndroid Build Coastguard Worker 	};
1854*4dc78e53SAndroid Build Coastguard Worker 
1855*4dc78e53SAndroid Build Coastguard Worker 	if (!(link->ce_mask & (LINK_ATTR_IFINDEX | LINK_ATTR_IFNAME))) {
1856*4dc78e53SAndroid Build Coastguard Worker 		APPBUG("ifindex or name must be specified");
1857*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
1858*4dc78e53SAndroid Build Coastguard Worker 	}
1859*4dc78e53SAndroid Build Coastguard Worker 
1860*4dc78e53SAndroid Build Coastguard Worker 	if (!(msg = nlmsg_alloc_simple(RTM_DELLINK, 0)))
1861*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
1862*4dc78e53SAndroid Build Coastguard Worker 
1863*4dc78e53SAndroid Build Coastguard Worker 	_NL_RETURN_ON_PUT_ERR(nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO));
1864*4dc78e53SAndroid Build Coastguard Worker 
1865*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_IFNAME)
1866*4dc78e53SAndroid Build Coastguard Worker 		_NL_RETURN_ON_PUT_ERR(nla_put_string(msg, IFLA_IFNAME, link->l_name));
1867*4dc78e53SAndroid Build Coastguard Worker 
1868*4dc78e53SAndroid Build Coastguard Worker 	*result = _nl_steal_pointer(&msg);
1869*4dc78e53SAndroid Build Coastguard Worker 	return 0;
1870*4dc78e53SAndroid Build Coastguard Worker }
1871*4dc78e53SAndroid Build Coastguard Worker 
1872*4dc78e53SAndroid Build Coastguard Worker /**
1873*4dc78e53SAndroid Build Coastguard Worker  * Delete link
1874*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket
1875*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link to delete
1876*4dc78e53SAndroid Build Coastguard Worker  *
1877*4dc78e53SAndroid Build Coastguard Worker  * Builds a \c RTM_DELLINK netlink message requesting the deletion of
1878*4dc78e53SAndroid Build Coastguard Worker  * a network link which has been previously added to the kernel and
1879*4dc78e53SAndroid Build Coastguard Worker  * sends the message to the kernel.
1880*4dc78e53SAndroid Build Coastguard Worker  *
1881*4dc78e53SAndroid Build Coastguard Worker  * If no matching link exists, the function will return
1882*4dc78e53SAndroid Build Coastguard Worker  * -NLE_OBJ_NOTFOUND.
1883*4dc78e53SAndroid Build Coastguard Worker  *
1884*4dc78e53SAndroid Build Coastguard Worker  * After sending, the function will wait for the ACK or an eventual
1885*4dc78e53SAndroid Build Coastguard Worker  * error message to be received and will therefore block until the
1886*4dc78e53SAndroid Build Coastguard Worker  * operation has been completed.
1887*4dc78e53SAndroid Build Coastguard Worker  *
1888*4dc78e53SAndroid Build Coastguard Worker  * @copydoc auto_ack_warning
1889*4dc78e53SAndroid Build Coastguard Worker  *
1890*4dc78e53SAndroid Build Coastguard Worker  * @note Only virtual links such as dummy interface or vlan interfaces
1891*4dc78e53SAndroid Build Coastguard Worker  *       can be deleted. It is not possible to delete physical interfaces
1892*4dc78e53SAndroid Build Coastguard Worker  *       such as ethernet interfaces or the loopback device.
1893*4dc78e53SAndroid Build Coastguard Worker  *
1894*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
1895*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_delete(struct nl_sock * sk,const struct rtnl_link * link)1896*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link)
1897*4dc78e53SAndroid Build Coastguard Worker {
1898*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
1899*4dc78e53SAndroid Build Coastguard Worker 	int err;
1900*4dc78e53SAndroid Build Coastguard Worker 
1901*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_link_build_delete_request(link, &msg)) < 0)
1902*4dc78e53SAndroid Build Coastguard Worker 		return err;
1903*4dc78e53SAndroid Build Coastguard Worker 
1904*4dc78e53SAndroid Build Coastguard Worker 	return nl_send_sync(sk, msg);
1905*4dc78e53SAndroid Build Coastguard Worker }
1906*4dc78e53SAndroid Build Coastguard Worker 
1907*4dc78e53SAndroid Build Coastguard Worker /** @} */
1908*4dc78e53SAndroid Build Coastguard Worker 
1909*4dc78e53SAndroid Build Coastguard Worker /**
1910*4dc78e53SAndroid Build Coastguard Worker  * @name Link Object
1911*4dc78e53SAndroid Build Coastguard Worker  * @{
1912*4dc78e53SAndroid Build Coastguard Worker  */
1913*4dc78e53SAndroid Build Coastguard Worker 
1914*4dc78e53SAndroid Build Coastguard Worker /**
1915*4dc78e53SAndroid Build Coastguard Worker  * Allocate link object
1916*4dc78e53SAndroid Build Coastguard Worker  *
1917*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_put()
1918*4dc78e53SAndroid Build Coastguard Worker  * @return New link object or NULL if allocation failed
1919*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_alloc(void)1920*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *rtnl_link_alloc(void)
1921*4dc78e53SAndroid Build Coastguard Worker {
1922*4dc78e53SAndroid Build Coastguard Worker 	return (struct rtnl_link *) nl_object_alloc(&link_obj_ops);
1923*4dc78e53SAndroid Build Coastguard Worker }
1924*4dc78e53SAndroid Build Coastguard Worker 
1925*4dc78e53SAndroid Build Coastguard Worker /**
1926*4dc78e53SAndroid Build Coastguard Worker  * Release a link object reference
1927*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
1928*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_put(struct rtnl_link * link)1929*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_put(struct rtnl_link *link)
1930*4dc78e53SAndroid Build Coastguard Worker {
1931*4dc78e53SAndroid Build Coastguard Worker 	nl_object_put((struct nl_object *) link);
1932*4dc78e53SAndroid Build Coastguard Worker }
1933*4dc78e53SAndroid Build Coastguard Worker 
1934*4dc78e53SAndroid Build Coastguard Worker /**
1935*4dc78e53SAndroid Build Coastguard Worker  * Set name of link object
1936*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
1937*4dc78e53SAndroid Build Coastguard Worker  * @arg name		New name
1938*4dc78e53SAndroid Build Coastguard Worker  *
1939*4dc78e53SAndroid Build Coastguard Worker  * @note To change the name of a link in the kernel, set the interface
1940*4dc78e53SAndroid Build Coastguard Worker  *       index to the link you wish to change, modify the link name using
1941*4dc78e53SAndroid Build Coastguard Worker  *       this function and pass the link object to rtnl_link_change() or
1942*4dc78e53SAndroid Build Coastguard Worker  *       rtnl_link_add().
1943*4dc78e53SAndroid Build Coastguard Worker  *
1944*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_name, Link Name}
1945*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_name()
1946*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_ifindex()
1947*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_name(struct rtnl_link * link,const char * name)1948*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_name(struct rtnl_link *link, const char *name)
1949*4dc78e53SAndroid Build Coastguard Worker {
1950*4dc78e53SAndroid Build Coastguard Worker 	_nl_strncpy_trunc(link->l_name, name, sizeof(link->l_name));
1951*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_IFNAME;
1952*4dc78e53SAndroid Build Coastguard Worker }
1953*4dc78e53SAndroid Build Coastguard Worker 
1954*4dc78e53SAndroid Build Coastguard Worker /**
1955*4dc78e53SAndroid Build Coastguard Worker  * Return name of link object
1956*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
1957*4dc78e53SAndroid Build Coastguard Worker  *
1958*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_name, Link Name}
1959*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_name()
1960*4dc78e53SAndroid Build Coastguard Worker  * @return Link name or NULL if name is not specified
1961*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_name(struct rtnl_link * link)1962*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_get_name(struct rtnl_link *link)
1963*4dc78e53SAndroid Build Coastguard Worker {
1964*4dc78e53SAndroid Build Coastguard Worker 	return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL;
1965*4dc78e53SAndroid Build Coastguard Worker }
1966*4dc78e53SAndroid Build Coastguard Worker 
1967*4dc78e53SAndroid Build Coastguard Worker /**
1968*4dc78e53SAndroid Build Coastguard Worker  * Set the group identifier of a link object
1969*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
1970*4dc78e53SAndroid Build Coastguard Worker  * @arg group		Group identifier
1971*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_group(struct rtnl_link * link,uint32_t group)1972*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_group(struct rtnl_link *link, uint32_t group)
1973*4dc78e53SAndroid Build Coastguard Worker {
1974*4dc78e53SAndroid Build Coastguard Worker 	link->l_group = group;
1975*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_GROUP;
1976*4dc78e53SAndroid Build Coastguard Worker }
1977*4dc78e53SAndroid Build Coastguard Worker 
1978*4dc78e53SAndroid Build Coastguard Worker /**
1979*4dc78e53SAndroid Build Coastguard Worker  * Return the group identifier of link object
1980*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
1981*4dc78e53SAndroid Build Coastguard Worker  *
1982*4dc78e53SAndroid Build Coastguard Worker  * @return Group identifier or 0 if not set.
1983*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_group(struct rtnl_link * link)1984*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_link_get_group(struct rtnl_link *link)
1985*4dc78e53SAndroid Build Coastguard Worker {
1986*4dc78e53SAndroid Build Coastguard Worker 	return link->l_group;
1987*4dc78e53SAndroid Build Coastguard Worker }
1988*4dc78e53SAndroid Build Coastguard Worker 
__assign_addr(struct rtnl_link * link,struct nl_addr ** pos,struct nl_addr * new,int flag)1989*4dc78e53SAndroid Build Coastguard Worker static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos,
1990*4dc78e53SAndroid Build Coastguard Worker 				 struct nl_addr *new, int flag)
1991*4dc78e53SAndroid Build Coastguard Worker {
1992*4dc78e53SAndroid Build Coastguard Worker 	if (*pos)
1993*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_put(*pos);
1994*4dc78e53SAndroid Build Coastguard Worker 
1995*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_get(new);
1996*4dc78e53SAndroid Build Coastguard Worker 	*pos = new;
1997*4dc78e53SAndroid Build Coastguard Worker 
1998*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= flag;
1999*4dc78e53SAndroid Build Coastguard Worker }
2000*4dc78e53SAndroid Build Coastguard Worker 
2001*4dc78e53SAndroid Build Coastguard Worker /**
2002*4dc78e53SAndroid Build Coastguard Worker  * Set link layer address of link object
2003*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2004*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		New link layer address
2005*4dc78e53SAndroid Build Coastguard Worker  *
2006*4dc78e53SAndroid Build Coastguard Worker  * The function increments the reference counter of the address object
2007*4dc78e53SAndroid Build Coastguard Worker  * and overwrites any existing link layer address previously assigned.
2008*4dc78e53SAndroid Build Coastguard Worker  *
2009*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_address, Link layer address}
2010*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_addr()
2011*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_addr(struct rtnl_link * link,struct nl_addr * addr)2012*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr)
2013*4dc78e53SAndroid Build Coastguard Worker {
2014*4dc78e53SAndroid Build Coastguard Worker 	__assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
2015*4dc78e53SAndroid Build Coastguard Worker }
2016*4dc78e53SAndroid Build Coastguard Worker 
2017*4dc78e53SAndroid Build Coastguard Worker /**
2018*4dc78e53SAndroid Build Coastguard Worker  * Return link layer address of link object
2019*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2020*4dc78e53SAndroid Build Coastguard Worker  *
2021*4dc78e53SAndroid Build Coastguard Worker  * @copydoc pointer_lifetime_warning
2022*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_address, Link Layer Address}
2023*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_addr()
2024*4dc78e53SAndroid Build Coastguard Worker  * @return Link layer address or NULL if not set.
2025*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_addr(struct rtnl_link * link)2026*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link)
2027*4dc78e53SAndroid Build Coastguard Worker {
2028*4dc78e53SAndroid Build Coastguard Worker 	return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL;
2029*4dc78e53SAndroid Build Coastguard Worker }
2030*4dc78e53SAndroid Build Coastguard Worker 
2031*4dc78e53SAndroid Build Coastguard Worker /**
2032*4dc78e53SAndroid Build Coastguard Worker  * Set link layer broadcast address of link object
2033*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2034*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		New broadcast address
2035*4dc78e53SAndroid Build Coastguard Worker  *
2036*4dc78e53SAndroid Build Coastguard Worker  * The function increments the reference counter of the address object
2037*4dc78e53SAndroid Build Coastguard Worker  * and overwrites any existing link layer broadcast address previously
2038*4dc78e53SAndroid Build Coastguard Worker  * assigned.
2039*4dc78e53SAndroid Build Coastguard Worker  *
2040*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_broadcast, Link Layer Broadcast Address}
2041*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_broadcast()
2042*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_broadcast(struct rtnl_link * link,struct nl_addr * addr)2043*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr)
2044*4dc78e53SAndroid Build Coastguard Worker {
2045*4dc78e53SAndroid Build Coastguard Worker 	__assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD);
2046*4dc78e53SAndroid Build Coastguard Worker }
2047*4dc78e53SAndroid Build Coastguard Worker 
2048*4dc78e53SAndroid Build Coastguard Worker /**
2049*4dc78e53SAndroid Build Coastguard Worker  * Return link layer broadcast address of link object
2050*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2051*4dc78e53SAndroid Build Coastguard Worker  *
2052*4dc78e53SAndroid Build Coastguard Worker  * @copydoc pointer_lifetime_warning
2053*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_address, Link Layer Address}
2054*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_broadcast()
2055*4dc78e53SAndroid Build Coastguard Worker  * @return Link layer address or NULL if not set.
2056*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_broadcast(struct rtnl_link * link)2057*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link)
2058*4dc78e53SAndroid Build Coastguard Worker {
2059*4dc78e53SAndroid Build Coastguard Worker 	return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL;
2060*4dc78e53SAndroid Build Coastguard Worker }
2061*4dc78e53SAndroid Build Coastguard Worker 
2062*4dc78e53SAndroid Build Coastguard Worker /**
2063*4dc78e53SAndroid Build Coastguard Worker  * Set flags of link object
2064*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2065*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Flags
2066*4dc78e53SAndroid Build Coastguard Worker  *
2067*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_flags()
2068*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_unset_flags()
2069*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_flags(struct rtnl_link * link,unsigned int flags)2070*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags)
2071*4dc78e53SAndroid Build Coastguard Worker {
2072*4dc78e53SAndroid Build Coastguard Worker 	link->l_flag_mask |= flags;
2073*4dc78e53SAndroid Build Coastguard Worker 	link->l_flags |= flags;
2074*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_FLAGS;
2075*4dc78e53SAndroid Build Coastguard Worker }
2076*4dc78e53SAndroid Build Coastguard Worker 
2077*4dc78e53SAndroid Build Coastguard Worker /**
2078*4dc78e53SAndroid Build Coastguard Worker  * Unset flags of link object
2079*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2080*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Flags
2081*4dc78e53SAndroid Build Coastguard Worker  *
2082*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_flags()
2083*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_flags()
2084*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_unset_flags(struct rtnl_link * link,unsigned int flags)2085*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags)
2086*4dc78e53SAndroid Build Coastguard Worker {
2087*4dc78e53SAndroid Build Coastguard Worker 	link->l_flag_mask |= flags;
2088*4dc78e53SAndroid Build Coastguard Worker 	link->l_flags &= ~flags;
2089*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_FLAGS;
2090*4dc78e53SAndroid Build Coastguard Worker }
2091*4dc78e53SAndroid Build Coastguard Worker 
2092*4dc78e53SAndroid Build Coastguard Worker /**
2093*4dc78e53SAndroid Build Coastguard Worker  * Return flags of link object
2094*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2095*4dc78e53SAndroid Build Coastguard Worker  *
2096*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_flags, Link Flags}
2097*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_flags()
2098*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_unset_flags()
2099*4dc78e53SAndroid Build Coastguard Worker  * @return Link flags or 0 if none have been set.
2100*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_flags(struct rtnl_link * link)2101*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_link_get_flags(struct rtnl_link *link)
2102*4dc78e53SAndroid Build Coastguard Worker {
2103*4dc78e53SAndroid Build Coastguard Worker 	return link->l_flags;
2104*4dc78e53SAndroid Build Coastguard Worker }
2105*4dc78e53SAndroid Build Coastguard Worker 
2106*4dc78e53SAndroid Build Coastguard Worker /**
2107*4dc78e53SAndroid Build Coastguard Worker  * Set address family of link object
2108*4dc78e53SAndroid Build Coastguard Worker  *
2109*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_family()
2110*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_family(struct rtnl_link * link,int family)2111*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_family(struct rtnl_link *link, int family)
2112*4dc78e53SAndroid Build Coastguard Worker {
2113*4dc78e53SAndroid Build Coastguard Worker 	link->l_family = family;
2114*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_FAMILY;
2115*4dc78e53SAndroid Build Coastguard Worker 
2116*4dc78e53SAndroid Build Coastguard Worker 	if (link->l_af_ops) {
2117*4dc78e53SAndroid Build Coastguard Worker 		int ao_family = link->l_af_ops->ao_family;
2118*4dc78e53SAndroid Build Coastguard Worker 
2119*4dc78e53SAndroid Build Coastguard Worker 		af_free(link, link->l_af_ops, link->l_af_data[ao_family], NULL);
2120*4dc78e53SAndroid Build Coastguard Worker 		link->l_af_data[ao_family] = NULL;
2121*4dc78e53SAndroid Build Coastguard Worker 	}
2122*4dc78e53SAndroid Build Coastguard Worker 
2123*4dc78e53SAndroid Build Coastguard Worker 	link->l_af_ops = af_lookup_and_alloc(link, family);
2124*4dc78e53SAndroid Build Coastguard Worker }
2125*4dc78e53SAndroid Build Coastguard Worker 
2126*4dc78e53SAndroid Build Coastguard Worker /**
2127*4dc78e53SAndroid Build Coastguard Worker  * Return address family of link object
2128*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2129*4dc78e53SAndroid Build Coastguard Worker  *
2130*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_family()
2131*4dc78e53SAndroid Build Coastguard Worker  * @return Address family or \c AF_UNSPEC if not specified.
2132*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_family(struct rtnl_link * link)2133*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_family(struct rtnl_link *link)
2134*4dc78e53SAndroid Build Coastguard Worker {
2135*4dc78e53SAndroid Build Coastguard Worker 	return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC;
2136*4dc78e53SAndroid Build Coastguard Worker }
2137*4dc78e53SAndroid Build Coastguard Worker 
2138*4dc78e53SAndroid Build Coastguard Worker /**
2139*4dc78e53SAndroid Build Coastguard Worker  * Set hardware type of link object
2140*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2141*4dc78e53SAndroid Build Coastguard Worker  * @arg arptype		New hardware type \c (ARPHRD_*)
2142*4dc78e53SAndroid Build Coastguard Worker  *
2143*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_arptype, Hardware Type}
2144*4dc78e53SAndroid Build Coastguard Worker  * @copydoc read_only_attribute
2145*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_arptype()
2146*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_arptype(struct rtnl_link * link,unsigned int arptype)2147*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype)
2148*4dc78e53SAndroid Build Coastguard Worker {
2149*4dc78e53SAndroid Build Coastguard Worker 	link->l_arptype = arptype;
2150*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_ARPTYPE;
2151*4dc78e53SAndroid Build Coastguard Worker }
2152*4dc78e53SAndroid Build Coastguard Worker 
2153*4dc78e53SAndroid Build Coastguard Worker /**
2154*4dc78e53SAndroid Build Coastguard Worker  * Get hardware type of link object
2155*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2156*4dc78e53SAndroid Build Coastguard Worker  *
2157*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_arptype, Hardware Type}
2158*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_arptype()
2159*4dc78e53SAndroid Build Coastguard Worker  * @return Hardware type \c (ARPHRD_ETHER *) or \c ARPHRD_VOID
2160*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_arptype(struct rtnl_link * link)2161*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_link_get_arptype(struct rtnl_link *link)
2162*4dc78e53SAndroid Build Coastguard Worker {
2163*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_ARPTYPE)
2164*4dc78e53SAndroid Build Coastguard Worker 		return link->l_arptype;
2165*4dc78e53SAndroid Build Coastguard Worker 	else
2166*4dc78e53SAndroid Build Coastguard Worker 		return ARPHRD_VOID;
2167*4dc78e53SAndroid Build Coastguard Worker }
2168*4dc78e53SAndroid Build Coastguard Worker 
2169*4dc78e53SAndroid Build Coastguard Worker /**
2170*4dc78e53SAndroid Build Coastguard Worker  * Set interface index of link object
2171*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2172*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index
2173*4dc78e53SAndroid Build Coastguard Worker  *
2174*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_ifindex, Interface Index}
2175*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_ifindex()
2176*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_ifindex(struct rtnl_link * link,int ifindex)2177*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
2178*4dc78e53SAndroid Build Coastguard Worker {
2179*4dc78e53SAndroid Build Coastguard Worker 	link->l_index = ifindex;
2180*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_IFINDEX;
2181*4dc78e53SAndroid Build Coastguard Worker }
2182*4dc78e53SAndroid Build Coastguard Worker 
2183*4dc78e53SAndroid Build Coastguard Worker 
2184*4dc78e53SAndroid Build Coastguard Worker /**
2185*4dc78e53SAndroid Build Coastguard Worker  * Return interface index of link object
2186*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2187*4dc78e53SAndroid Build Coastguard Worker  *
2188*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_ifindex, Interface Index}
2189*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_ifindex()
2190*4dc78e53SAndroid Build Coastguard Worker  * @return Interface index or 0 if not set.
2191*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_ifindex(struct rtnl_link * link)2192*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_ifindex(struct rtnl_link *link)
2193*4dc78e53SAndroid Build Coastguard Worker {
2194*4dc78e53SAndroid Build Coastguard Worker 	return link->l_index;
2195*4dc78e53SAndroid Build Coastguard Worker }
2196*4dc78e53SAndroid Build Coastguard Worker 
2197*4dc78e53SAndroid Build Coastguard Worker /**
2198*4dc78e53SAndroid Build Coastguard Worker  * Set Maximum Transmission Unit of link object
2199*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2200*4dc78e53SAndroid Build Coastguard Worker  * @arg mtu		New MTU value in number of bytes
2201*4dc78e53SAndroid Build Coastguard Worker  *
2202*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_mtu, Maximum Transmission Unit}
2203*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_mtu()
2204*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_mtu(struct rtnl_link * link,unsigned int mtu)2205*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu)
2206*4dc78e53SAndroid Build Coastguard Worker {
2207*4dc78e53SAndroid Build Coastguard Worker 	link->l_mtu = mtu;
2208*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_MTU;
2209*4dc78e53SAndroid Build Coastguard Worker }
2210*4dc78e53SAndroid Build Coastguard Worker 
2211*4dc78e53SAndroid Build Coastguard Worker /**
2212*4dc78e53SAndroid Build Coastguard Worker  * Return maximum transmission unit of link object
2213*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2214*4dc78e53SAndroid Build Coastguard Worker  *
2215*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_mtu, Maximum Transmission Unit}
2216*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_mtu()
2217*4dc78e53SAndroid Build Coastguard Worker  * @return MTU in bytes or 0 if not set
2218*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_mtu(struct rtnl_link * link)2219*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_link_get_mtu(struct rtnl_link *link)
2220*4dc78e53SAndroid Build Coastguard Worker {
2221*4dc78e53SAndroid Build Coastguard Worker 	return link->l_mtu;
2222*4dc78e53SAndroid Build Coastguard Worker }
2223*4dc78e53SAndroid Build Coastguard Worker 
2224*4dc78e53SAndroid Build Coastguard Worker /**
2225*4dc78e53SAndroid Build Coastguard Worker  * Set transmission queue length
2226*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2227*4dc78e53SAndroid Build Coastguard Worker  * @arg txqlen		New queue length
2228*4dc78e53SAndroid Build Coastguard Worker  *
2229*4dc78e53SAndroid Build Coastguard Worker  * The unit is dependant on the link type. The most common units is number
2230*4dc78e53SAndroid Build Coastguard Worker  * of packets.
2231*4dc78e53SAndroid Build Coastguard Worker  *
2232*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_txqlen, Transmission Queue Length}
2233*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_txqlen(struct rtnl_link * link,unsigned int txqlen)2234*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen)
2235*4dc78e53SAndroid Build Coastguard Worker {
2236*4dc78e53SAndroid Build Coastguard Worker 	link->l_txqlen = txqlen;
2237*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_TXQLEN;
2238*4dc78e53SAndroid Build Coastguard Worker }
2239*4dc78e53SAndroid Build Coastguard Worker 
2240*4dc78e53SAndroid Build Coastguard Worker /**
2241*4dc78e53SAndroid Build Coastguard Worker  * Return transmission queue length
2242*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2243*4dc78e53SAndroid Build Coastguard Worker  *
2244*4dc78e53SAndroid Build Coastguard Worker  * The unit is dependant on the link type. The most common units is number
2245*4dc78e53SAndroid Build Coastguard Worker  * of packets.
2246*4dc78e53SAndroid Build Coastguard Worker  *
2247*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_txqlen, Transmission Queue Length}
2248*4dc78e53SAndroid Build Coastguard Worker  * @return queue length or 0 if not specified.
2249*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_txqlen(struct rtnl_link * link)2250*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
2251*4dc78e53SAndroid Build Coastguard Worker {
2252*4dc78e53SAndroid Build Coastguard Worker 	return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0;
2253*4dc78e53SAndroid Build Coastguard Worker }
2254*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_set_link(struct rtnl_link * link,int ifindex)2255*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_link(struct rtnl_link *link, int ifindex)
2256*4dc78e53SAndroid Build Coastguard Worker {
2257*4dc78e53SAndroid Build Coastguard Worker 	link->l_link = ifindex;
2258*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_LINK;
2259*4dc78e53SAndroid Build Coastguard Worker }
2260*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_get_link(struct rtnl_link * link)2261*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_link(struct rtnl_link *link)
2262*4dc78e53SAndroid Build Coastguard Worker {
2263*4dc78e53SAndroid Build Coastguard Worker 	return link->l_link;
2264*4dc78e53SAndroid Build Coastguard Worker }
2265*4dc78e53SAndroid Build Coastguard Worker 
2266*4dc78e53SAndroid Build Coastguard Worker /**
2267*4dc78e53SAndroid Build Coastguard Worker  * Set the netnsid of the link
2268*4dc78e53SAndroid Build Coastguard Worker  * @arg link            Link object
2269*4dc78e53SAndroid Build Coastguard Worker  * @link_netnsid        the netnsid to set
2270*4dc78e53SAndroid Build Coastguard Worker  *
2271*4dc78e53SAndroid Build Coastguard Worker  * Sets the IFLA_LINK_NETNSID attribute of the link
2272*4dc78e53SAndroid Build Coastguard Worker  * @returns 0 on success
2273*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_link_netnsid(struct rtnl_link * link,int32_t link_netnsid)2274*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_set_link_netnsid(struct rtnl_link *link, int32_t link_netnsid)
2275*4dc78e53SAndroid Build Coastguard Worker {
2276*4dc78e53SAndroid Build Coastguard Worker 	link->l_link_netnsid = link_netnsid;
2277*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_LINK_NETNSID;
2278*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2279*4dc78e53SAndroid Build Coastguard Worker }
2280*4dc78e53SAndroid Build Coastguard Worker 
2281*4dc78e53SAndroid Build Coastguard Worker /**
2282*4dc78e53SAndroid Build Coastguard Worker  * Get the netnsid of the link
2283*4dc78e53SAndroid Build Coastguard Worker  * @arg link            Link object
2284*4dc78e53SAndroid Build Coastguard Worker  * @out_link_netnsid    the netnsid
2285*4dc78e53SAndroid Build Coastguard Worker  *
2286*4dc78e53SAndroid Build Coastguard Worker  * Gets the IFLA_LINK_NETNSID attribute of the link
2287*4dc78e53SAndroid Build Coastguard Worker  * or returns an error if the value is unset.
2288*4dc78e53SAndroid Build Coastguard Worker  *
2289*4dc78e53SAndroid Build Coastguard Worker  * @returns 0 on success
2290*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_link_netnsid(const struct rtnl_link * link,int32_t * out_link_netnsid)2291*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_link_netnsid(const struct rtnl_link *link, int32_t *out_link_netnsid)
2292*4dc78e53SAndroid Build Coastguard Worker {
2293*4dc78e53SAndroid Build Coastguard Worker 	if (!(link->ce_mask & LINK_ATTR_LINK_NETNSID))
2294*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
2295*4dc78e53SAndroid Build Coastguard Worker 
2296*4dc78e53SAndroid Build Coastguard Worker 	*out_link_netnsid = link->l_link_netnsid;
2297*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2298*4dc78e53SAndroid Build Coastguard Worker }
2299*4dc78e53SAndroid Build Coastguard Worker 
2300*4dc78e53SAndroid Build Coastguard Worker /**
2301*4dc78e53SAndroid Build Coastguard Worker  * Set master link of link object
2302*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2303*4dc78e53SAndroid Build Coastguard Worker  * @arg ifindex		Interface index of master link
2304*4dc78e53SAndroid Build Coastguard Worker  *
2305*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_master()
2306*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_master(struct rtnl_link * link,int ifindex)2307*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_master(struct rtnl_link *link, int ifindex)
2308*4dc78e53SAndroid Build Coastguard Worker {
2309*4dc78e53SAndroid Build Coastguard Worker 	link->l_master = ifindex;
2310*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_MASTER;
2311*4dc78e53SAndroid Build Coastguard Worker }
2312*4dc78e53SAndroid Build Coastguard Worker 
2313*4dc78e53SAndroid Build Coastguard Worker /**
2314*4dc78e53SAndroid Build Coastguard Worker  * Return master link of link object
2315*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2316*4dc78e53SAndroid Build Coastguard Worker  *
2317*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_master()
2318*4dc78e53SAndroid Build Coastguard Worker  * @return Interface index of master link or 0 if not specified
2319*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_master(struct rtnl_link * link)2320*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_master(struct rtnl_link *link)
2321*4dc78e53SAndroid Build Coastguard Worker {
2322*4dc78e53SAndroid Build Coastguard Worker 	return link->l_master;
2323*4dc78e53SAndroid Build Coastguard Worker }
2324*4dc78e53SAndroid Build Coastguard Worker 
2325*4dc78e53SAndroid Build Coastguard Worker /**
2326*4dc78e53SAndroid Build Coastguard Worker  * Set carrier of link object
2327*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2328*4dc78e53SAndroid Build Coastguard Worker  * @arg status		New carrier status
2329*4dc78e53SAndroid Build Coastguard Worker  *
2330*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_carrier()
2331*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_carrier(struct rtnl_link * link,uint8_t status)2332*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_carrier(struct rtnl_link *link, uint8_t status)
2333*4dc78e53SAndroid Build Coastguard Worker {
2334*4dc78e53SAndroid Build Coastguard Worker 	link->l_carrier = status;
2335*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_CARRIER;
2336*4dc78e53SAndroid Build Coastguard Worker }
2337*4dc78e53SAndroid Build Coastguard Worker 
2338*4dc78e53SAndroid Build Coastguard Worker /**
2339*4dc78e53SAndroid Build Coastguard Worker  * Return carrier status of link object
2340*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2341*4dc78e53SAndroid Build Coastguard Worker  *
2342*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_master()
2343*4dc78e53SAndroid Build Coastguard Worker  * @return Carrier state.
2344*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_carrier(struct rtnl_link * link)2345*4dc78e53SAndroid Build Coastguard Worker uint8_t rtnl_link_get_carrier(struct rtnl_link *link)
2346*4dc78e53SAndroid Build Coastguard Worker {
2347*4dc78e53SAndroid Build Coastguard Worker 	return link->l_carrier;
2348*4dc78e53SAndroid Build Coastguard Worker }
2349*4dc78e53SAndroid Build Coastguard Worker 
2350*4dc78e53SAndroid Build Coastguard Worker /**
2351*4dc78e53SAndroid Build Coastguard Worker  * Return carrier on/off changes of link object
2352*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2353*4dc78e53SAndroid Build Coastguard Worker  * @arg carrier_changes	Pointer to store number of carrier changes
2354*4dc78e53SAndroid Build Coastguard Worker  *
2355*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success, negative error number otherwise
2356*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_carrier_changes(struct rtnl_link * link,uint32_t * carrier_changes)2357*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_carrier_changes(struct rtnl_link *link, uint32_t *carrier_changes)
2358*4dc78e53SAndroid Build Coastguard Worker {
2359*4dc78e53SAndroid Build Coastguard Worker 	if (!(link->ce_mask & LINK_ATTR_CARRIER_CHANGES))
2360*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOATTR;
2361*4dc78e53SAndroid Build Coastguard Worker 
2362*4dc78e53SAndroid Build Coastguard Worker 	if (carrier_changes)
2363*4dc78e53SAndroid Build Coastguard Worker 		*carrier_changes = link->l_carrier_changes;
2364*4dc78e53SAndroid Build Coastguard Worker 
2365*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2366*4dc78e53SAndroid Build Coastguard Worker }
2367*4dc78e53SAndroid Build Coastguard Worker 
2368*4dc78e53SAndroid Build Coastguard Worker /**
2369*4dc78e53SAndroid Build Coastguard Worker  * Set operational status of link object
2370*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2371*4dc78e53SAndroid Build Coastguard Worker  * @arg status		New opertional status
2372*4dc78e53SAndroid Build Coastguard Worker  *
2373*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_operstate, Operational Status}}
2374*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_operstate()
2375*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_operstate(struct rtnl_link * link,uint8_t status)2376*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t status)
2377*4dc78e53SAndroid Build Coastguard Worker {
2378*4dc78e53SAndroid Build Coastguard Worker 	link->l_operstate = status;
2379*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_OPERSTATE;
2380*4dc78e53SAndroid Build Coastguard Worker }
2381*4dc78e53SAndroid Build Coastguard Worker 
2382*4dc78e53SAndroid Build Coastguard Worker /**
2383*4dc78e53SAndroid Build Coastguard Worker  * Return operational status of link object
2384*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2385*4dc78e53SAndroid Build Coastguard Worker  *
2386*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_operstate, Operational Status}
2387*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_operstate()
2388*4dc78e53SAndroid Build Coastguard Worker  * @return Opertional state or \c IF_OPER_UNKNOWN
2389*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_operstate(struct rtnl_link * link)2390*4dc78e53SAndroid Build Coastguard Worker uint8_t rtnl_link_get_operstate(struct rtnl_link *link)
2391*4dc78e53SAndroid Build Coastguard Worker {
2392*4dc78e53SAndroid Build Coastguard Worker 	return link->l_operstate;
2393*4dc78e53SAndroid Build Coastguard Worker }
2394*4dc78e53SAndroid Build Coastguard Worker 
2395*4dc78e53SAndroid Build Coastguard Worker /**
2396*4dc78e53SAndroid Build Coastguard Worker  * Set link mode of link object
2397*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2398*4dc78e53SAndroid Build Coastguard Worker  * @arg mode		New link mode
2399*4dc78e53SAndroid Build Coastguard Worker  *
2400*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_mode, Mode}
2401*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_linkmode()
2402*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_linkmode(struct rtnl_link * link,uint8_t mode)2403*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode)
2404*4dc78e53SAndroid Build Coastguard Worker {
2405*4dc78e53SAndroid Build Coastguard Worker 	link->l_linkmode = mode;
2406*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_LINKMODE;
2407*4dc78e53SAndroid Build Coastguard Worker }
2408*4dc78e53SAndroid Build Coastguard Worker 
2409*4dc78e53SAndroid Build Coastguard Worker /**
2410*4dc78e53SAndroid Build Coastguard Worker  * Return link mode of link object
2411*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2412*4dc78e53SAndroid Build Coastguard Worker  *
2413*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_mode, Mode}
2414*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_linkmode()
2415*4dc78e53SAndroid Build Coastguard Worker  * @return Link mode or \c IF_LINK_MODE_DEFAULT
2416*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_linkmode(struct rtnl_link * link)2417*4dc78e53SAndroid Build Coastguard Worker uint8_t rtnl_link_get_linkmode(struct rtnl_link *link)
2418*4dc78e53SAndroid Build Coastguard Worker {
2419*4dc78e53SAndroid Build Coastguard Worker 	return link->l_linkmode;
2420*4dc78e53SAndroid Build Coastguard Worker }
2421*4dc78e53SAndroid Build Coastguard Worker 
2422*4dc78e53SAndroid Build Coastguard Worker /**
2423*4dc78e53SAndroid Build Coastguard Worker  * Return alias name of link object (SNMP IfAlias)
2424*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2425*4dc78e53SAndroid Build Coastguard Worker  *
2426*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_alias, Alias}
2427*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_ifalias()
2428*4dc78e53SAndroid Build Coastguard Worker  * @return Alias name or NULL if not set.
2429*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_ifalias(struct rtnl_link * link)2430*4dc78e53SAndroid Build Coastguard Worker const char *rtnl_link_get_ifalias(struct rtnl_link *link)
2431*4dc78e53SAndroid Build Coastguard Worker {
2432*4dc78e53SAndroid Build Coastguard Worker 	return link->l_ifalias;
2433*4dc78e53SAndroid Build Coastguard Worker }
2434*4dc78e53SAndroid Build Coastguard Worker 
2435*4dc78e53SAndroid Build Coastguard Worker /**
2436*4dc78e53SAndroid Build Coastguard Worker  * Set alias name of link object (SNMP IfAlias)
2437*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2438*4dc78e53SAndroid Build Coastguard Worker  * @arg alias		Alias name or NULL to unset
2439*4dc78e53SAndroid Build Coastguard Worker  *
2440*4dc78e53SAndroid Build Coastguard Worker  * Sets the alias name of the link to the specified name. The alias
2441*4dc78e53SAndroid Build Coastguard Worker  * name can be unset by specyfing NULL as the alias. The name will
2442*4dc78e53SAndroid Build Coastguard Worker  * be strdup()ed, so no need to provide a persistent character string.
2443*4dc78e53SAndroid Build Coastguard Worker  *
2444*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_alias, Alias}
2445*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_ifalias()
2446*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_ifalias(struct rtnl_link * link,const char * alias)2447*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias)
2448*4dc78e53SAndroid Build Coastguard Worker {
2449*4dc78e53SAndroid Build Coastguard Worker 	free(link->l_ifalias);
2450*4dc78e53SAndroid Build Coastguard Worker 
2451*4dc78e53SAndroid Build Coastguard Worker 	if (alias) {
2452*4dc78e53SAndroid Build Coastguard Worker 		link->l_ifalias = strdup(alias);
2453*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_IFALIAS;
2454*4dc78e53SAndroid Build Coastguard Worker 	} else {
2455*4dc78e53SAndroid Build Coastguard Worker 		link->l_ifalias = NULL;
2456*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask &= ~LINK_ATTR_IFALIAS;
2457*4dc78e53SAndroid Build Coastguard Worker 	}
2458*4dc78e53SAndroid Build Coastguard Worker }
2459*4dc78e53SAndroid Build Coastguard Worker 
2460*4dc78e53SAndroid Build Coastguard Worker /**
2461*4dc78e53SAndroid Build Coastguard Worker  * Set queueing discipline name of link object
2462*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2463*4dc78e53SAndroid Build Coastguard Worker  * @arg name		Name of queueing discipline
2464*4dc78e53SAndroid Build Coastguard Worker  *
2465*4dc78e53SAndroid Build Coastguard Worker  * @copydoc read_only_attribute
2466*4dc78e53SAndroid Build Coastguard Worker  *
2467*4dc78e53SAndroid Build Coastguard Worker  * For more information on how to modify the qdisc of a link, see section
2468*4dc78e53SAndroid Build Coastguard Worker  * @ref_route{route_tc, Traffic Control}.
2469*4dc78e53SAndroid Build Coastguard Worker  *
2470*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_qdisc, Queueing Discipline Name}
2471*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_qdisc()
2472*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_qdisc(struct rtnl_link * link,const char * name)2473*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name)
2474*4dc78e53SAndroid Build Coastguard Worker {
2475*4dc78e53SAndroid Build Coastguard Worker 	_nl_strncpy_trunc(link->l_qdisc, name, sizeof(link->l_qdisc));
2476*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_QDISC;
2477*4dc78e53SAndroid Build Coastguard Worker }
2478*4dc78e53SAndroid Build Coastguard Worker 
2479*4dc78e53SAndroid Build Coastguard Worker /**
2480*4dc78e53SAndroid Build Coastguard Worker  * Return name of queueing discipline of link object
2481*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2482*4dc78e53SAndroid Build Coastguard Worker  *
2483*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_attr_qdisc, Queueing Discipline Name}
2484*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_qdisc()
2485*4dc78e53SAndroid Build Coastguard Worker  * @return Name of qdisc or NULL if not specified.
2486*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_qdisc(struct rtnl_link * link)2487*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_get_qdisc(struct rtnl_link *link)
2488*4dc78e53SAndroid Build Coastguard Worker {
2489*4dc78e53SAndroid Build Coastguard Worker 	return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL;
2490*4dc78e53SAndroid Build Coastguard Worker }
2491*4dc78e53SAndroid Build Coastguard Worker 
2492*4dc78e53SAndroid Build Coastguard Worker 
2493*4dc78e53SAndroid Build Coastguard Worker /**
2494*4dc78e53SAndroid Build Coastguard Worker  * Return number of PCI virtual functions of link object
2495*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2496*4dc78e53SAndroid Build Coastguard Worker  * @arg num_vf		Pointer to store number of VFs
2497*4dc78e53SAndroid Build Coastguard Worker  *
2498*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or -NLE_OPNOTSUPP if not available
2499*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_num_vf(struct rtnl_link * link,uint32_t * num_vf)2500*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf)
2501*4dc78e53SAndroid Build Coastguard Worker {
2502*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_NUM_VF) {
2503*4dc78e53SAndroid Build Coastguard Worker 		*num_vf = link->l_num_vf;
2504*4dc78e53SAndroid Build Coastguard Worker 		return 0;
2505*4dc78e53SAndroid Build Coastguard Worker 	} else
2506*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_OPNOTSUPP;
2507*4dc78e53SAndroid Build Coastguard Worker }
2508*4dc78e53SAndroid Build Coastguard Worker 
2509*4dc78e53SAndroid Build Coastguard Worker /**
2510*4dc78e53SAndroid Build Coastguard Worker  * Return value of link statistics counter
2511*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2512*4dc78e53SAndroid Build Coastguard Worker  * @arg id		Identifier of statistical counter
2513*4dc78e53SAndroid Build Coastguard Worker  *
2514*4dc78e53SAndroid Build Coastguard Worker  * @return Value of counter or 0 if not specified.
2515*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_stat(struct rtnl_link * link,rtnl_link_stat_id_t id)2516*4dc78e53SAndroid Build Coastguard Worker uint64_t rtnl_link_get_stat(struct rtnl_link *link, rtnl_link_stat_id_t id)
2517*4dc78e53SAndroid Build Coastguard Worker {
2518*4dc78e53SAndroid Build Coastguard Worker 	if (id > RTNL_LINK_STATS_MAX)
2519*4dc78e53SAndroid Build Coastguard Worker 		return 0;
2520*4dc78e53SAndroid Build Coastguard Worker 
2521*4dc78e53SAndroid Build Coastguard Worker 	return link->l_stats[id];
2522*4dc78e53SAndroid Build Coastguard Worker }
2523*4dc78e53SAndroid Build Coastguard Worker 
2524*4dc78e53SAndroid Build Coastguard Worker /**
2525*4dc78e53SAndroid Build Coastguard Worker  * Set value of link statistics counter
2526*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2527*4dc78e53SAndroid Build Coastguard Worker  * @arg id		Identifier of statistical counter
2528*4dc78e53SAndroid Build Coastguard Worker  * @arg value		New value
2529*4dc78e53SAndroid Build Coastguard Worker  *
2530*4dc78e53SAndroid Build Coastguard Worker  * \note Changing the value of a statistical counter will not change the
2531*4dc78e53SAndroid Build Coastguard Worker  *       value in the kernel.
2532*4dc78e53SAndroid Build Coastguard Worker  *
2533*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code
2534*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_stat(struct rtnl_link * link,rtnl_link_stat_id_t id,const uint64_t value)2535*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_set_stat(struct rtnl_link *link, rtnl_link_stat_id_t id,
2536*4dc78e53SAndroid Build Coastguard Worker 		       const uint64_t value)
2537*4dc78e53SAndroid Build Coastguard Worker {
2538*4dc78e53SAndroid Build Coastguard Worker 	if (id > RTNL_LINK_STATS_MAX)
2539*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
2540*4dc78e53SAndroid Build Coastguard Worker 
2541*4dc78e53SAndroid Build Coastguard Worker 	link->l_stats[id] = value;
2542*4dc78e53SAndroid Build Coastguard Worker 
2543*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2544*4dc78e53SAndroid Build Coastguard Worker }
2545*4dc78e53SAndroid Build Coastguard Worker 
2546*4dc78e53SAndroid Build Coastguard Worker /**
2547*4dc78e53SAndroid Build Coastguard Worker  * Set type of link object
2548*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2549*4dc78e53SAndroid Build Coastguard Worker  * @arg type		Name of link type
2550*4dc78e53SAndroid Build Coastguard Worker  *
2551*4dc78e53SAndroid Build Coastguard Worker  * Looks up the link type module and prepares the link to store type
2552*4dc78e53SAndroid Build Coastguard Worker  * specific attributes. If a type has been assigned already it will
2553*4dc78e53SAndroid Build Coastguard Worker  * be released with all link type specific attributes lost.
2554*4dc78e53SAndroid Build Coastguard Worker  *
2555*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_modules, Link Modules}
2556*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
2557*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_type(struct rtnl_link * link,const char * type)2558*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_set_type(struct rtnl_link *link, const char *type)
2559*4dc78e53SAndroid Build Coastguard Worker {
2560*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link_info_ops *io;
2561*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_free char *kind = NULL;
2562*4dc78e53SAndroid Build Coastguard Worker 	int err;
2563*4dc78e53SAndroid Build Coastguard Worker 
2564*4dc78e53SAndroid Build Coastguard Worker 	free(link->l_info_kind);
2565*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask &= ~LINK_ATTR_LINKINFO;
2566*4dc78e53SAndroid Build Coastguard Worker 	release_link_info(link);
2567*4dc78e53SAndroid Build Coastguard Worker 
2568*4dc78e53SAndroid Build Coastguard Worker 	if (!type)
2569*4dc78e53SAndroid Build Coastguard Worker 		return 0;
2570*4dc78e53SAndroid Build Coastguard Worker 
2571*4dc78e53SAndroid Build Coastguard Worker 	kind = strdup(type);
2572*4dc78e53SAndroid Build Coastguard Worker 	if (!kind)
2573*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
2574*4dc78e53SAndroid Build Coastguard Worker 
2575*4dc78e53SAndroid Build Coastguard Worker 	io = rtnl_link_info_ops_lookup(type);
2576*4dc78e53SAndroid Build Coastguard Worker 	if (io) {
2577*4dc78e53SAndroid Build Coastguard Worker 		if (io->io_alloc && (err = io->io_alloc(link)) < 0) {
2578*4dc78e53SAndroid Build Coastguard Worker 			_nl_clear_free(&kind);
2579*4dc78e53SAndroid Build Coastguard Worker 			return err;
2580*4dc78e53SAndroid Build Coastguard Worker 		}
2581*4dc78e53SAndroid Build Coastguard Worker 
2582*4dc78e53SAndroid Build Coastguard Worker 		link->l_info_ops = io;
2583*4dc78e53SAndroid Build Coastguard Worker 	}
2584*4dc78e53SAndroid Build Coastguard Worker 
2585*4dc78e53SAndroid Build Coastguard Worker 	link->l_info_kind = _nl_steal_pointer(&kind);
2586*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_LINKINFO;
2587*4dc78e53SAndroid Build Coastguard Worker 
2588*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2589*4dc78e53SAndroid Build Coastguard Worker }
2590*4dc78e53SAndroid Build Coastguard Worker 
2591*4dc78e53SAndroid Build Coastguard Worker /**
2592*4dc78e53SAndroid Build Coastguard Worker  * Return type of link
2593*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2594*4dc78e53SAndroid Build Coastguard Worker  *
2595*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_modules, Link Modules}
2596*4dc78e53SAndroid Build Coastguard Worker  * @return Name of link type or NULL if not specified.
2597*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_type(struct rtnl_link * link)2598*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_get_type(struct rtnl_link *link)
2599*4dc78e53SAndroid Build Coastguard Worker {
2600*4dc78e53SAndroid Build Coastguard Worker 	return link->l_info_kind;
2601*4dc78e53SAndroid Build Coastguard Worker }
2602*4dc78e53SAndroid Build Coastguard Worker 
2603*4dc78e53SAndroid Build Coastguard Worker /**
2604*4dc78e53SAndroid Build Coastguard Worker  * Set type of slave link object
2605*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object (slave)
2606*4dc78e53SAndroid Build Coastguard Worker  * @arg type		Name of link type
2607*4dc78e53SAndroid Build Coastguard Worker  *
2608*4dc78e53SAndroid Build Coastguard Worker  * If a slave type has been assigned already it will be released.
2609*4dc78e53SAndroid Build Coastguard Worker  *
2610*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_modules, Link Modules}
2611*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
2612*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_slave_type(struct rtnl_link * link,const char * type)2613*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_set_slave_type(struct rtnl_link *link, const char *type)
2614*4dc78e53SAndroid Build Coastguard Worker {
2615*4dc78e53SAndroid Build Coastguard Worker 	char *kind = NULL;
2616*4dc78e53SAndroid Build Coastguard Worker 
2617*4dc78e53SAndroid Build Coastguard Worker 	if (type) {
2618*4dc78e53SAndroid Build Coastguard Worker 		kind = strdup(type);
2619*4dc78e53SAndroid Build Coastguard Worker 		if (!kind)
2620*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
2621*4dc78e53SAndroid Build Coastguard Worker 	}
2622*4dc78e53SAndroid Build Coastguard Worker 
2623*4dc78e53SAndroid Build Coastguard Worker 	free(link->l_info_slave_kind);
2624*4dc78e53SAndroid Build Coastguard Worker 	link->l_info_slave_kind = kind;
2625*4dc78e53SAndroid Build Coastguard Worker 
2626*4dc78e53SAndroid Build Coastguard Worker 	if (kind)
2627*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_LINKINFO_SLAVE_KIND;
2628*4dc78e53SAndroid Build Coastguard Worker 	else
2629*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask &= ~LINK_ATTR_LINKINFO_SLAVE_KIND;
2630*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2631*4dc78e53SAndroid Build Coastguard Worker }
2632*4dc78e53SAndroid Build Coastguard Worker 
2633*4dc78e53SAndroid Build Coastguard Worker /**
2634*4dc78e53SAndroid Build Coastguard Worker  * Return type of enslaved link
2635*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2636*4dc78e53SAndroid Build Coastguard Worker  *
2637*4dc78e53SAndroid Build Coastguard Worker  * @route_doc{link_modules, Link Modules}
2638*4dc78e53SAndroid Build Coastguard Worker  * @return Name of enslaved link type or NULL if not specified.
2639*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_slave_type(const struct rtnl_link * link)2640*4dc78e53SAndroid Build Coastguard Worker const char *rtnl_link_get_slave_type(const struct rtnl_link *link)
2641*4dc78e53SAndroid Build Coastguard Worker {
2642*4dc78e53SAndroid Build Coastguard Worker 	return link->l_info_slave_kind;
2643*4dc78e53SAndroid Build Coastguard Worker }
2644*4dc78e53SAndroid Build Coastguard Worker 
2645*4dc78e53SAndroid Build Coastguard Worker 
2646*4dc78e53SAndroid Build Coastguard Worker /**
2647*4dc78e53SAndroid Build Coastguard Worker  * Set link promiscuity count
2648*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2649*4dc78e53SAndroid Build Coastguard Worker  * @arg count		New promiscuity count
2650*4dc78e53SAndroid Build Coastguard Worker  *
2651*4dc78e53SAndroid Build Coastguard Worker  * @copydoc read_only_attribute
2652*4dc78e53SAndroid Build Coastguard Worker  *
2653*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_promiscuity()
2654*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_promiscuity(struct rtnl_link * link,uint32_t count)2655*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count)
2656*4dc78e53SAndroid Build Coastguard Worker {
2657*4dc78e53SAndroid Build Coastguard Worker 	link->l_promiscuity = count;
2658*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_PROMISCUITY;
2659*4dc78e53SAndroid Build Coastguard Worker }
2660*4dc78e53SAndroid Build Coastguard Worker 
2661*4dc78e53SAndroid Build Coastguard Worker /**
2662*4dc78e53SAndroid Build Coastguard Worker  * Return link promiscuity count
2663*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2664*4dc78e53SAndroid Build Coastguard Worker  *
2665*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_set_promiscuity()
2666*4dc78e53SAndroid Build Coastguard Worker  * @return Link promiscuity count or 0
2667*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_promiscuity(struct rtnl_link * link)2668*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link)
2669*4dc78e53SAndroid Build Coastguard Worker {
2670*4dc78e53SAndroid Build Coastguard Worker 	return link->l_promiscuity;
2671*4dc78e53SAndroid Build Coastguard Worker }
2672*4dc78e53SAndroid Build Coastguard Worker 
2673*4dc78e53SAndroid Build Coastguard Worker /**
2674*4dc78e53SAndroid Build Coastguard Worker  * Set number of TX queues
2675*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2676*4dc78e53SAndroid Build Coastguard Worker  * @arg nqueues		Number of queues
2677*4dc78e53SAndroid Build Coastguard Worker  *
2678*4dc78e53SAndroid Build Coastguard Worker  * Sets the number of TX queues of the link object. The value is considered
2679*4dc78e53SAndroid Build Coastguard Worker  * by the kernel when creating network devices that can be created via
2680*4dc78e53SAndroid Build Coastguard Worker  * netlink. The value will be passed on to alloc_netdev_mqs()
2681*4dc78e53SAndroid Build Coastguard Worker  *
2682*4dc78e53SAndroid Build Coastguard Worker  * Therefore use of rtnl_link_set_num_tx_queues() only makes sense in
2683*4dc78e53SAndroid Build Coastguard Worker  * combination with rtnl_link_add() or if the link object is used as a filter.
2684*4dc78e53SAndroid Build Coastguard Worker  *
2685*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_num_tx_queues()
2686*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_num_tx_queues(struct rtnl_link * link,uint32_t nqueues)2687*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues)
2688*4dc78e53SAndroid Build Coastguard Worker {
2689*4dc78e53SAndroid Build Coastguard Worker 	link->l_num_tx_queues = nqueues;
2690*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_NUM_TX_QUEUES;
2691*4dc78e53SAndroid Build Coastguard Worker }
2692*4dc78e53SAndroid Build Coastguard Worker 
2693*4dc78e53SAndroid Build Coastguard Worker /**
2694*4dc78e53SAndroid Build Coastguard Worker  * Return number of TX queues
2695*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2696*4dc78e53SAndroid Build Coastguard Worker  *
2697*4dc78e53SAndroid Build Coastguard Worker  * @return Number of TX queues or 0
2698*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_num_tx_queues(struct rtnl_link * link)2699*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link)
2700*4dc78e53SAndroid Build Coastguard Worker {
2701*4dc78e53SAndroid Build Coastguard Worker 	return link->l_num_tx_queues;
2702*4dc78e53SAndroid Build Coastguard Worker }
2703*4dc78e53SAndroid Build Coastguard Worker 
2704*4dc78e53SAndroid Build Coastguard Worker /**
2705*4dc78e53SAndroid Build Coastguard Worker  * Set number of RX queues
2706*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2707*4dc78e53SAndroid Build Coastguard Worker  * @arg nqueues		Number of queues
2708*4dc78e53SAndroid Build Coastguard Worker  *
2709*4dc78e53SAndroid Build Coastguard Worker  * Sets the number of RX queues of the link object. The value is considered
2710*4dc78e53SAndroid Build Coastguard Worker  * by the kernel when creating network devices that can be created via
2711*4dc78e53SAndroid Build Coastguard Worker  * netlink. The value will be passed on to alloc_netdev_mqs()
2712*4dc78e53SAndroid Build Coastguard Worker  *
2713*4dc78e53SAndroid Build Coastguard Worker  * Therefore use of rtnl_link_set_num_rx_queues() only makes sense in
2714*4dc78e53SAndroid Build Coastguard Worker  * combination with rtnl_link_add() or if the link object is used as a filter.
2715*4dc78e53SAndroid Build Coastguard Worker  *
2716*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_get_num_rx_queues()
2717*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_num_rx_queues(struct rtnl_link * link,uint32_t nqueues)2718*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues)
2719*4dc78e53SAndroid Build Coastguard Worker {
2720*4dc78e53SAndroid Build Coastguard Worker 	link->l_num_rx_queues = nqueues;
2721*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_NUM_RX_QUEUES;
2722*4dc78e53SAndroid Build Coastguard Worker }
2723*4dc78e53SAndroid Build Coastguard Worker 
2724*4dc78e53SAndroid Build Coastguard Worker /**
2725*4dc78e53SAndroid Build Coastguard Worker  * Return number of RX queues
2726*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2727*4dc78e53SAndroid Build Coastguard Worker  *
2728*4dc78e53SAndroid Build Coastguard Worker  * @return Number of RX queues or 0
2729*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_num_rx_queues(struct rtnl_link * link)2730*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link)
2731*4dc78e53SAndroid Build Coastguard Worker {
2732*4dc78e53SAndroid Build Coastguard Worker 	return link->l_num_rx_queues;
2733*4dc78e53SAndroid Build Coastguard Worker }
2734*4dc78e53SAndroid Build Coastguard Worker 
2735*4dc78e53SAndroid Build Coastguard Worker /**
2736*4dc78e53SAndroid Build Coastguard Worker  * Return maximum number of segments for generic segmentation offload
2737*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2738*4dc78e53SAndroid Build Coastguard Worker  * @arg gso_max_segs	Pointer to store maximum number GSO segments
2739*4dc78e53SAndroid Build Coastguard Worker  *
2740*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success, negative error number otherwise
2741*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_gso_max_segs(struct rtnl_link * link,uint32_t * gso_max_segs)2742*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_gso_max_segs(struct rtnl_link *link, uint32_t *gso_max_segs)
2743*4dc78e53SAndroid Build Coastguard Worker {
2744*4dc78e53SAndroid Build Coastguard Worker 	if (!(link->ce_mask & LINK_ATTR_GSO_MAX_SEGS))
2745*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOATTR;
2746*4dc78e53SAndroid Build Coastguard Worker 
2747*4dc78e53SAndroid Build Coastguard Worker 	if (gso_max_segs)
2748*4dc78e53SAndroid Build Coastguard Worker 		*gso_max_segs = link->l_gso_max_segs;
2749*4dc78e53SAndroid Build Coastguard Worker 
2750*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2751*4dc78e53SAndroid Build Coastguard Worker }
2752*4dc78e53SAndroid Build Coastguard Worker 
2753*4dc78e53SAndroid Build Coastguard Worker /**
2754*4dc78e53SAndroid Build Coastguard Worker  * Return maximum size for generic segmentation offload
2755*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2756*4dc78e53SAndroid Build Coastguard Worker  * @arg gso_max_segs	Pointer to store maximum GSO size
2757*4dc78e53SAndroid Build Coastguard Worker  *
2758*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success, negative error number otherwise
2759*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_gso_max_size(struct rtnl_link * link,uint32_t * gso_max_size)2760*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_gso_max_size(struct rtnl_link *link, uint32_t *gso_max_size)
2761*4dc78e53SAndroid Build Coastguard Worker {
2762*4dc78e53SAndroid Build Coastguard Worker 	if (!(link->ce_mask & LINK_ATTR_GSO_MAX_SIZE))
2763*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOATTR;
2764*4dc78e53SAndroid Build Coastguard Worker 
2765*4dc78e53SAndroid Build Coastguard Worker 	if (gso_max_size)
2766*4dc78e53SAndroid Build Coastguard Worker 		*gso_max_size = link->l_gso_max_size;
2767*4dc78e53SAndroid Build Coastguard Worker 
2768*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2769*4dc78e53SAndroid Build Coastguard Worker }
2770*4dc78e53SAndroid Build Coastguard Worker 
2771*4dc78e53SAndroid Build Coastguard Worker /**
2772*4dc78e53SAndroid Build Coastguard Worker  * Return physical port id of link object
2773*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2774*4dc78e53SAndroid Build Coastguard Worker  *
2775*4dc78e53SAndroid Build Coastguard Worker  * @return Physical port id or NULL if not set.
2776*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_phys_port_id(struct rtnl_link * link)2777*4dc78e53SAndroid Build Coastguard Worker struct nl_data *rtnl_link_get_phys_port_id(struct rtnl_link *link)
2778*4dc78e53SAndroid Build Coastguard Worker {
2779*4dc78e53SAndroid Build Coastguard Worker 	return link->l_phys_port_id;
2780*4dc78e53SAndroid Build Coastguard Worker }
2781*4dc78e53SAndroid Build Coastguard Worker 
2782*4dc78e53SAndroid Build Coastguard Worker /**
2783*4dc78e53SAndroid Build Coastguard Worker  * Return physical port name of link object
2784*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2785*4dc78e53SAndroid Build Coastguard Worker  *
2786*4dc78e53SAndroid Build Coastguard Worker  * @return Physical port name or NULL if not set.
2787*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_phys_port_name(struct rtnl_link * link)2788*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_get_phys_port_name(struct rtnl_link *link)
2789*4dc78e53SAndroid Build Coastguard Worker {
2790*4dc78e53SAndroid Build Coastguard Worker 	return link->l_phys_port_name;
2791*4dc78e53SAndroid Build Coastguard Worker }
2792*4dc78e53SAndroid Build Coastguard Worker 
2793*4dc78e53SAndroid Build Coastguard Worker /*
2794*4dc78e53SAndroid Build Coastguard Worker  * Return physical switch id of link object
2795*4dc78e53SAndroid Build Coastguard Worker  * @arg link		Link object
2796*4dc78e53SAndroid Build Coastguard Worker  *
2797*4dc78e53SAndroid Build Coastguard Worker  * @return Physical switch id or NULL if not set.
2798*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_phys_switch_id(struct rtnl_link * link)2799*4dc78e53SAndroid Build Coastguard Worker struct nl_data *rtnl_link_get_phys_switch_id(struct rtnl_link *link)
2800*4dc78e53SAndroid Build Coastguard Worker {
2801*4dc78e53SAndroid Build Coastguard Worker 	return link->l_phys_switch_id;
2802*4dc78e53SAndroid Build Coastguard Worker }
2803*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_set_ns_fd(struct rtnl_link * link,int fd)2804*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_ns_fd(struct rtnl_link *link, int fd)
2805*4dc78e53SAndroid Build Coastguard Worker {
2806*4dc78e53SAndroid Build Coastguard Worker 	link->l_ns_fd = fd;
2807*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_NS_FD;
2808*4dc78e53SAndroid Build Coastguard Worker }
2809*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_get_ns_fd(struct rtnl_link * link)2810*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_get_ns_fd(struct rtnl_link *link)
2811*4dc78e53SAndroid Build Coastguard Worker {
2812*4dc78e53SAndroid Build Coastguard Worker 	return link->l_ns_fd;
2813*4dc78e53SAndroid Build Coastguard Worker }
2814*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_set_ns_pid(struct rtnl_link * link,pid_t pid)2815*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_ns_pid(struct rtnl_link *link, pid_t pid)
2816*4dc78e53SAndroid Build Coastguard Worker {
2817*4dc78e53SAndroid Build Coastguard Worker 	link->l_ns_pid = pid;
2818*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_NS_PID;
2819*4dc78e53SAndroid Build Coastguard Worker }
2820*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_get_ns_pid(struct rtnl_link * link)2821*4dc78e53SAndroid Build Coastguard Worker pid_t rtnl_link_get_ns_pid(struct rtnl_link *link)
2822*4dc78e53SAndroid Build Coastguard Worker {
2823*4dc78e53SAndroid Build Coastguard Worker 	return link->l_ns_pid;
2824*4dc78e53SAndroid Build Coastguard Worker }
2825*4dc78e53SAndroid Build Coastguard Worker 
2826*4dc78e53SAndroid Build Coastguard Worker /** @} */
2827*4dc78e53SAndroid Build Coastguard Worker 
2828*4dc78e53SAndroid Build Coastguard Worker /**
2829*4dc78e53SAndroid Build Coastguard Worker  * @name Master/Slave
2830*4dc78e53SAndroid Build Coastguard Worker  * @{
2831*4dc78e53SAndroid Build Coastguard Worker  */
2832*4dc78e53SAndroid Build Coastguard Worker 
2833*4dc78e53SAndroid Build Coastguard Worker /**
2834*4dc78e53SAndroid Build Coastguard Worker  * Enslave slave link to master link
2835*4dc78e53SAndroid Build Coastguard Worker  * @arg sock		netlink socket
2836*4dc78e53SAndroid Build Coastguard Worker  * @arg master		ifindex of master link
2837*4dc78e53SAndroid Build Coastguard Worker  * @arg slave		ifindex of slave link
2838*4dc78e53SAndroid Build Coastguard Worker  *
2839*4dc78e53SAndroid Build Coastguard Worker  * This function is identical to rtnl_link_enslave() except that
2840*4dc78e53SAndroid Build Coastguard Worker  * it takes interface indices instead of rtnl_link objects.
2841*4dc78e53SAndroid Build Coastguard Worker  *
2842*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_enslave()
2843*4dc78e53SAndroid Build Coastguard Worker  *
2844*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
2845*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_enslave_ifindex(struct nl_sock * sock,int master,int slave)2846*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave)
2847*4dc78e53SAndroid Build Coastguard Worker {
2848*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link = NULL;
2849*4dc78e53SAndroid Build Coastguard Worker 	int err;
2850*4dc78e53SAndroid Build Coastguard Worker 
2851*4dc78e53SAndroid Build Coastguard Worker 	if (!(link = rtnl_link_alloc()))
2852*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
2853*4dc78e53SAndroid Build Coastguard Worker 
2854*4dc78e53SAndroid Build Coastguard Worker 	rtnl_link_set_ifindex(link, slave);
2855*4dc78e53SAndroid Build Coastguard Worker 	rtnl_link_set_master(link, master);
2856*4dc78e53SAndroid Build Coastguard Worker 
2857*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_link_change(sock, link, link, 0)) < 0)
2858*4dc78e53SAndroid Build Coastguard Worker 		return err;
2859*4dc78e53SAndroid Build Coastguard Worker 
2860*4dc78e53SAndroid Build Coastguard Worker 	_nl_clear_pointer(&link, rtnl_link_put);
2861*4dc78e53SAndroid Build Coastguard Worker 
2862*4dc78e53SAndroid Build Coastguard Worker 	/*
2863*4dc78e53SAndroid Build Coastguard Worker 	 * Due to the kernel not signaling whether this operation is
2864*4dc78e53SAndroid Build Coastguard Worker 	 * supported or not, we will retrieve the attribute to see  if the
2865*4dc78e53SAndroid Build Coastguard Worker 	 * request was successful. If the master assigned remains unchanged
2866*4dc78e53SAndroid Build Coastguard Worker 	 * we will return NLE_OPNOTSUPP to allow performing backwards
2867*4dc78e53SAndroid Build Coastguard Worker 	 * compatibility of some sort.
2868*4dc78e53SAndroid Build Coastguard Worker 	 */
2869*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0)
2870*4dc78e53SAndroid Build Coastguard Worker 		return err;
2871*4dc78e53SAndroid Build Coastguard Worker 
2872*4dc78e53SAndroid Build Coastguard Worker 	if (rtnl_link_get_master(link) != master)
2873*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_OPNOTSUPP;
2874*4dc78e53SAndroid Build Coastguard Worker 
2875*4dc78e53SAndroid Build Coastguard Worker 	return 0;
2876*4dc78e53SAndroid Build Coastguard Worker }
2877*4dc78e53SAndroid Build Coastguard Worker 
2878*4dc78e53SAndroid Build Coastguard Worker /**
2879*4dc78e53SAndroid Build Coastguard Worker  * Enslave slave link to master link
2880*4dc78e53SAndroid Build Coastguard Worker  * @arg sock		netlink socket
2881*4dc78e53SAndroid Build Coastguard Worker  * @arg master		master link
2882*4dc78e53SAndroid Build Coastguard Worker  * @arg slave		slave link
2883*4dc78e53SAndroid Build Coastguard Worker  *
2884*4dc78e53SAndroid Build Coastguard Worker  * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to
2885*4dc78e53SAndroid Build Coastguard Worker  * the master and sends the request via the specified netlink socket.
2886*4dc78e53SAndroid Build Coastguard Worker  *
2887*4dc78e53SAndroid Build Coastguard Worker  * @note The feature of enslaving/releasing via netlink has only been added
2888*4dc78e53SAndroid Build Coastguard Worker  *       recently to the kernel (Feb 2011). Also, the kernel does not signal
2889*4dc78e53SAndroid Build Coastguard Worker  *       if the operation is not supported. Therefore this function will
2890*4dc78e53SAndroid Build Coastguard Worker  *       verify if the master assignment has changed and will return
2891*4dc78e53SAndroid Build Coastguard Worker  *       -NLE_OPNOTSUPP if it did not.
2892*4dc78e53SAndroid Build Coastguard Worker  *
2893*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_enslave_ifindex()
2894*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_release()
2895*4dc78e53SAndroid Build Coastguard Worker  *
2896*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
2897*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_enslave(struct nl_sock * sock,struct rtnl_link * master,struct rtnl_link * slave)2898*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_enslave(struct nl_sock *sock, struct rtnl_link *master,
2899*4dc78e53SAndroid Build Coastguard Worker 		      struct rtnl_link *slave)
2900*4dc78e53SAndroid Build Coastguard Worker {
2901*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_link_enslave_ifindex(sock, rtnl_link_get_ifindex(master),
2902*4dc78e53SAndroid Build Coastguard Worker 					 rtnl_link_get_ifindex(slave));
2903*4dc78e53SAndroid Build Coastguard Worker }
2904*4dc78e53SAndroid Build Coastguard Worker 
2905*4dc78e53SAndroid Build Coastguard Worker /**
2906*4dc78e53SAndroid Build Coastguard Worker  * Release slave link from its master
2907*4dc78e53SAndroid Build Coastguard Worker  * @arg sock		netlink socket
2908*4dc78e53SAndroid Build Coastguard Worker  * @arg slave		slave link
2909*4dc78e53SAndroid Build Coastguard Worker  *
2910*4dc78e53SAndroid Build Coastguard Worker  * This function is identical to rtnl_link_release() except that
2911*4dc78e53SAndroid Build Coastguard Worker  * it takes an interface index instead of a rtnl_link object.
2912*4dc78e53SAndroid Build Coastguard Worker  *
2913*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_release()
2914*4dc78e53SAndroid Build Coastguard Worker  *
2915*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
2916*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_release_ifindex(struct nl_sock * sock,int slave)2917*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_release_ifindex(struct nl_sock *sock, int slave)
2918*4dc78e53SAndroid Build Coastguard Worker {
2919*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_link_enslave_ifindex(sock, 0, slave);
2920*4dc78e53SAndroid Build Coastguard Worker }
2921*4dc78e53SAndroid Build Coastguard Worker 
2922*4dc78e53SAndroid Build Coastguard Worker /**
2923*4dc78e53SAndroid Build Coastguard Worker  * Release slave link from its master
2924*4dc78e53SAndroid Build Coastguard Worker  * @arg sock		netlink socket
2925*4dc78e53SAndroid Build Coastguard Worker  * @arg slave		slave link
2926*4dc78e53SAndroid Build Coastguard Worker  *
2927*4dc78e53SAndroid Build Coastguard Worker  * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from
2928*4dc78e53SAndroid Build Coastguard Worker  * its master and sends the request via the specified netlink socket.
2929*4dc78e53SAndroid Build Coastguard Worker  *
2930*4dc78e53SAndroid Build Coastguard Worker  * @note The feature of enslaving/releasing via netlink has only been added
2931*4dc78e53SAndroid Build Coastguard Worker  *       recently to the kernel (Feb 2011). Also, the kernel does not signal
2932*4dc78e53SAndroid Build Coastguard Worker  *       if the operation is not supported. Therefore this function will
2933*4dc78e53SAndroid Build Coastguard Worker  *       verify if the master assignment has changed and will return
2934*4dc78e53SAndroid Build Coastguard Worker  *       -NLE_OPNOTSUPP if it did not.
2935*4dc78e53SAndroid Build Coastguard Worker  *
2936*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_release_ifindex()
2937*4dc78e53SAndroid Build Coastguard Worker  * @see rtnl_link_enslave()
2938*4dc78e53SAndroid Build Coastguard Worker  *
2939*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
2940*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_release(struct nl_sock * sock,struct rtnl_link * slave)2941*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave)
2942*4dc78e53SAndroid Build Coastguard Worker {
2943*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_link_release_ifindex(sock, rtnl_link_get_ifindex(slave));
2944*4dc78e53SAndroid Build Coastguard Worker }
2945*4dc78e53SAndroid Build Coastguard Worker 
2946*4dc78e53SAndroid Build Coastguard Worker /** @} */
2947*4dc78e53SAndroid Build Coastguard Worker 
2948*4dc78e53SAndroid Build Coastguard Worker /**
2949*4dc78e53SAndroid Build Coastguard Worker  * @name Utilities
2950*4dc78e53SAndroid Build Coastguard Worker  * @{
2951*4dc78e53SAndroid Build Coastguard Worker  */
2952*4dc78e53SAndroid Build Coastguard Worker 
2953*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl link_flags[] = {
2954*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_LOOPBACK, loopback),
2955*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_BROADCAST, broadcast),
2956*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_POINTOPOINT, pointopoint),
2957*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_MULTICAST, multicast),
2958*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_NOARP, noarp),
2959*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_ALLMULTI, allmulti),
2960*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_PROMISC, promisc),
2961*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_MASTER, master),
2962*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_SLAVE, slave),
2963*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_DEBUG, debug),
2964*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_DYNAMIC, dynamic),
2965*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_AUTOMEDIA, automedia),
2966*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_PORTSEL, portsel),
2967*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_NOTRAILERS, notrailers),
2968*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_UP, up),
2969*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_RUNNING, running),
2970*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_LOWER_UP, lowerup),
2971*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_DORMANT, dormant),
2972*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IFF_ECHO, echo),
2973*4dc78e53SAndroid Build Coastguard Worker };
2974*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_flags2str(int flags,char * buf,size_t len)2975*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_flags2str(int flags, char *buf, size_t len)
2976*4dc78e53SAndroid Build Coastguard Worker {
2977*4dc78e53SAndroid Build Coastguard Worker 	return __flags2str(flags, buf, len, link_flags,
2978*4dc78e53SAndroid Build Coastguard Worker 			   ARRAY_SIZE(link_flags));
2979*4dc78e53SAndroid Build Coastguard Worker }
2980*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_str2flags(const char * name)2981*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_str2flags(const char *name)
2982*4dc78e53SAndroid Build Coastguard Worker {
2983*4dc78e53SAndroid Build Coastguard Worker 	return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
2984*4dc78e53SAndroid Build Coastguard Worker }
2985*4dc78e53SAndroid Build Coastguard Worker 
2986*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl link_stats[] = {
2987*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_PACKETS, rx_packets),
2988*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_PACKETS, tx_packets),
2989*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_BYTES, rx_bytes),
2990*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_BYTES, tx_bytes),
2991*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_ERRORS, rx_errors),
2992*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_ERRORS, tx_errors),
2993*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_DROPPED, rx_dropped),
2994*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_DROPPED, tx_dropped),
2995*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed),
2996*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed),
2997*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err),
2998*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err),
2999*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err),
3000*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err),
3001*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err),
3002*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err),
3003*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err),
3004*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err),
3005*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err),
3006*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err),
3007*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err),
3008*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_COLLISIONS, collisions),
3009*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_MULTICAST, multicast),
3010*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INPKTS, Ip6InReceives),
3011*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INHDRERRORS, Ip6InHdrErrors),
3012*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INTOOBIGERRORS, Ip6InTooBigErrors),
3013*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INNOROUTES, Ip6InNoRoutes),
3014*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INADDRERRORS, Ip6InAddrErrors),
3015*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INUNKNOWNPROTOS, Ip6InUnknownProtos),
3016*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INTRUNCATEDPKTS, Ip6InTruncatedPkts),
3017*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INDISCARDS, Ip6InDiscards),
3018*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INDELIVERS, Ip6InDelivers),
3019*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTFORWDATAGRAMS, Ip6OutForwDatagrams),
3020*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTPKTS, Ip6OutRequests),
3021*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTDISCARDS, Ip6OutDiscards),
3022*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTNOROUTES, Ip6OutNoRoutes),
3023*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_REASMTIMEOUT, Ip6ReasmTimeout),
3024*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_REASMREQDS, Ip6ReasmReqds),
3025*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_REASMOKS, Ip6ReasmOKs),
3026*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_REASMFAILS, Ip6ReasmFails),
3027*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_FRAGOKS, Ip6FragOKs),
3028*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_FRAGFAILS, Ip6FragFails),
3029*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_FRAGCREATES, Ip6FragCreates),
3030*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INMCASTPKTS, Ip6InMcastPkts),
3031*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTMCASTPKTS, Ip6OutMcastPkts),
3032*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INBCASTPKTS, Ip6InBcastPkts),
3033*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTBCASTPKTS, Ip6OutBcastPkts),
3034*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INOCTETS, Ip6InOctets),
3035*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTOCTETS, Ip6OutOctets),
3036*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INMCASTOCTETS, Ip6InMcastOctets),
3037*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTMCASTOCTETS, Ip6OutMcastOctets),
3038*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_INBCASTOCTETS, Ip6InBcastOctets),
3039*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_OUTBCASTOCTETS, Ip6OutBcastOctets),
3040*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_ICMP6_INMSGS, ICMP6_InMsgs),
3041*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors),
3042*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs),
3043*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors),
3044*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_ICMP6_CSUMERRORS, ICMP6_InCsumErrors),
3045*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_CSUMERRORS, Ip6_InCsumErrors),
3046*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_NOECTPKTS, Ip6_InNoECTPkts),
3047*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_ECT1PKTS, Ip6_InECT1Pkts),
3048*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_ECT0PKTS, Ip6_InECT0Pkts),
3049*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_IP6_CEPKTS, Ip6_InCEPkts),
3050*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_RX_NOHANDLER, rx_nohandler),
3051*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RTNL_LINK_REASM_OVERLAPS, ReasmOverlaps),
3052*4dc78e53SAndroid Build Coastguard Worker };
3053*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_stat2str(int st,char * buf,size_t len)3054*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_stat2str(int st, char *buf, size_t len)
3055*4dc78e53SAndroid Build Coastguard Worker {
3056*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
3057*4dc78e53SAndroid Build Coastguard Worker }
3058*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_str2stat(const char * name)3059*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_str2stat(const char *name)
3060*4dc78e53SAndroid Build Coastguard Worker {
3061*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
3062*4dc78e53SAndroid Build Coastguard Worker }
3063*4dc78e53SAndroid Build Coastguard Worker 
3064*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl link_operstates[] = {
3065*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_OPER_UNKNOWN, unknown),
3066*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_OPER_NOTPRESENT, notpresent),
3067*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_OPER_DOWN, down),
3068*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown),
3069*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_OPER_TESTING, testing),
3070*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_OPER_DORMANT, dormant),
3071*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_OPER_UP, up),
3072*4dc78e53SAndroid Build Coastguard Worker };
3073*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_operstate2str(uint8_t st,char * buf,size_t len)3074*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_operstate2str(uint8_t st, char *buf, size_t len)
3075*4dc78e53SAndroid Build Coastguard Worker {
3076*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(st, buf, len, link_operstates,
3077*4dc78e53SAndroid Build Coastguard Worker 			  ARRAY_SIZE(link_operstates));
3078*4dc78e53SAndroid Build Coastguard Worker }
3079*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_str2operstate(const char * name)3080*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_str2operstate(const char *name)
3081*4dc78e53SAndroid Build Coastguard Worker {
3082*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, link_operstates,
3083*4dc78e53SAndroid Build Coastguard Worker 			  ARRAY_SIZE(link_operstates));
3084*4dc78e53SAndroid Build Coastguard Worker }
3085*4dc78e53SAndroid Build Coastguard Worker 
3086*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl link_modes[] = {
3087*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_LINK_MODE_DEFAULT, default),
3088*4dc78e53SAndroid Build Coastguard Worker 	__ADD(IF_LINK_MODE_DORMANT, dormant),
3089*4dc78e53SAndroid Build Coastguard Worker };
3090*4dc78e53SAndroid Build Coastguard Worker 
3091*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl carrier_states[] = {
3092*4dc78e53SAndroid Build Coastguard Worker 	__ADD(0, down),
3093*4dc78e53SAndroid Build Coastguard Worker 	__ADD(1, up),
3094*4dc78e53SAndroid Build Coastguard Worker };
3095*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_mode2str(uint8_t st,char * buf,size_t len)3096*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len)
3097*4dc78e53SAndroid Build Coastguard Worker {
3098*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
3099*4dc78e53SAndroid Build Coastguard Worker }
3100*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_str2mode(const char * name)3101*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_str2mode(const char *name)
3102*4dc78e53SAndroid Build Coastguard Worker {
3103*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
3104*4dc78e53SAndroid Build Coastguard Worker }
3105*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_carrier2str(uint8_t st,char * buf,size_t len)3106*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_carrier2str(uint8_t st, char *buf, size_t len)
3107*4dc78e53SAndroid Build Coastguard Worker {
3108*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(st, buf, len, carrier_states,
3109*4dc78e53SAndroid Build Coastguard Worker 			  ARRAY_SIZE(carrier_states));
3110*4dc78e53SAndroid Build Coastguard Worker }
3111*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_str2carrier(const char * name)3112*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_str2carrier(const char *name)
3113*4dc78e53SAndroid Build Coastguard Worker {
3114*4dc78e53SAndroid Build Coastguard Worker 	return __str2type(name, carrier_states, ARRAY_SIZE(carrier_states));
3115*4dc78e53SAndroid Build Coastguard Worker }
3116*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_has_vf_list(struct rtnl_link * link)3117*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_has_vf_list(struct rtnl_link *link) {
3118*4dc78e53SAndroid Build Coastguard Worker 	if (link->ce_mask & LINK_ATTR_VF_LIST)
3119*4dc78e53SAndroid Build Coastguard Worker 		return 1;
3120*4dc78e53SAndroid Build Coastguard Worker 	else
3121*4dc78e53SAndroid Build Coastguard Worker 		return 0;
3122*4dc78e53SAndroid Build Coastguard Worker }
3123*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_set_vf_list(struct rtnl_link * link)3124*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_vf_list(struct rtnl_link *link)
3125*4dc78e53SAndroid Build Coastguard Worker {
3126*4dc78e53SAndroid Build Coastguard Worker 	if (!rtnl_link_has_vf_list(link))
3127*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask |= LINK_ATTR_VF_LIST;
3128*4dc78e53SAndroid Build Coastguard Worker }
3129*4dc78e53SAndroid Build Coastguard Worker 
rtnl_link_unset_vf_list(struct rtnl_link * link)3130*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_unset_vf_list(struct rtnl_link *link)
3131*4dc78e53SAndroid Build Coastguard Worker {
3132*4dc78e53SAndroid Build Coastguard Worker 	if (rtnl_link_has_vf_list(link))
3133*4dc78e53SAndroid Build Coastguard Worker 		link->ce_mask &= ~LINK_ATTR_VF_LIST;
3134*4dc78e53SAndroid Build Coastguard Worker }
3135*4dc78e53SAndroid Build Coastguard Worker 
3136*4dc78e53SAndroid Build Coastguard Worker /** @} */
3137*4dc78e53SAndroid Build Coastguard Worker 
3138*4dc78e53SAndroid Build Coastguard Worker /**
3139*4dc78e53SAndroid Build Coastguard Worker  * @name Deprecated Functions
3140*4dc78e53SAndroid Build Coastguard Worker  */
3141*4dc78e53SAndroid Build Coastguard Worker 
3142*4dc78e53SAndroid Build Coastguard Worker /**
3143*4dc78e53SAndroid Build Coastguard Worker  * @deprecated Use of this function is deprecated, use rtnl_link_set_type()
3144*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_info_type(struct rtnl_link * link,const char * type)3145*4dc78e53SAndroid Build Coastguard Worker int rtnl_link_set_info_type(struct rtnl_link *link, const char *type)
3146*4dc78e53SAndroid Build Coastguard Worker {
3147*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_link_set_type(link, type);
3148*4dc78e53SAndroid Build Coastguard Worker }
3149*4dc78e53SAndroid Build Coastguard Worker 
3150*4dc78e53SAndroid Build Coastguard Worker /**
3151*4dc78e53SAndroid Build Coastguard Worker  * @deprecated Use of this function is deprecated, use rtnl_link_get_type()
3152*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_info_type(struct rtnl_link * link)3153*4dc78e53SAndroid Build Coastguard Worker char *rtnl_link_get_info_type(struct rtnl_link *link)
3154*4dc78e53SAndroid Build Coastguard Worker {
3155*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_link_get_type(link);
3156*4dc78e53SAndroid Build Coastguard Worker }
3157*4dc78e53SAndroid Build Coastguard Worker 
3158*4dc78e53SAndroid Build Coastguard Worker /**
3159*4dc78e53SAndroid Build Coastguard Worker  * @deprecated The weight attribute is unused and obsoleted in all recent kernels
3160*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_set_weight(struct rtnl_link * link,unsigned int weight)3161*4dc78e53SAndroid Build Coastguard Worker void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight)
3162*4dc78e53SAndroid Build Coastguard Worker {
3163*4dc78e53SAndroid Build Coastguard Worker 	link->l_weight = weight;
3164*4dc78e53SAndroid Build Coastguard Worker 	link->ce_mask |= LINK_ATTR_WEIGHT;
3165*4dc78e53SAndroid Build Coastguard Worker }
3166*4dc78e53SAndroid Build Coastguard Worker 
3167*4dc78e53SAndroid Build Coastguard Worker /**
3168*4dc78e53SAndroid Build Coastguard Worker  * @deprecated The weight attribute is unused and obsoleted in all recent kernels
3169*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_link_get_weight(struct rtnl_link * link)3170*4dc78e53SAndroid Build Coastguard Worker unsigned int rtnl_link_get_weight(struct rtnl_link *link)
3171*4dc78e53SAndroid Build Coastguard Worker {
3172*4dc78e53SAndroid Build Coastguard Worker 	return link->l_weight;
3173*4dc78e53SAndroid Build Coastguard Worker }
3174*4dc78e53SAndroid Build Coastguard Worker 
3175*4dc78e53SAndroid Build Coastguard Worker /** @} */
3176*4dc78e53SAndroid Build Coastguard Worker 
3177*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops link_obj_ops = {
3178*4dc78e53SAndroid Build Coastguard Worker 	.oo_name		= "route/link",
3179*4dc78e53SAndroid Build Coastguard Worker 	.oo_size		= sizeof(struct rtnl_link),
3180*4dc78e53SAndroid Build Coastguard Worker 	.oo_free_data		= link_free_data,
3181*4dc78e53SAndroid Build Coastguard Worker 	.oo_clone		= link_clone,
3182*4dc78e53SAndroid Build Coastguard Worker 	.oo_dump = {
3183*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_LINE]	= link_dump_line,
3184*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_DETAILS]	= link_dump_details,
3185*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_STATS]	= link_dump_stats,
3186*4dc78e53SAndroid Build Coastguard Worker 	},
3187*4dc78e53SAndroid Build Coastguard Worker 	.oo_compare		= link_compare,
3188*4dc78e53SAndroid Build Coastguard Worker 	.oo_keygen		= link_keygen,
3189*4dc78e53SAndroid Build Coastguard Worker 	.oo_attrs2str		= link_attrs2str,
3190*4dc78e53SAndroid Build Coastguard Worker 	.oo_id_attrs		= LINK_ATTR_IFINDEX | LINK_ATTR_FAMILY,
3191*4dc78e53SAndroid Build Coastguard Worker };
3192*4dc78e53SAndroid Build Coastguard Worker 
3193*4dc78e53SAndroid Build Coastguard Worker static struct nl_af_group link_groups[] = {
3194*4dc78e53SAndroid Build Coastguard Worker 	{ AF_UNSPEC,	RTNLGRP_LINK },
3195*4dc78e53SAndroid Build Coastguard Worker 	{ AF_BRIDGE,    RTNLGRP_LINK },
3196*4dc78e53SAndroid Build Coastguard Worker 	{ AF_INET6,     RTNLGRP_IPV6_IFINFO },
3197*4dc78e53SAndroid Build Coastguard Worker 	{ END_OF_GROUP_LIST },
3198*4dc78e53SAndroid Build Coastguard Worker };
3199*4dc78e53SAndroid Build Coastguard Worker 
3200*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_link_ops = {
3201*4dc78e53SAndroid Build Coastguard Worker 	.co_name		= "route/link",
3202*4dc78e53SAndroid Build Coastguard Worker 	.co_hdrsize		= sizeof(struct ifinfomsg),
3203*4dc78e53SAndroid Build Coastguard Worker 	.co_msgtypes		= {
3204*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_NEWLINK, NL_ACT_NEW, "new" },
3205*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_DELLINK, NL_ACT_DEL, "del" },
3206*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_GETLINK, NL_ACT_GET, "get" },
3207*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_SETLINK, NL_ACT_CHANGE, "set" },
3208*4dc78e53SAndroid Build Coastguard Worker 					END_OF_MSGTYPES_LIST,
3209*4dc78e53SAndroid Build Coastguard Worker 				  },
3210*4dc78e53SAndroid Build Coastguard Worker 	.co_protocol		= NETLINK_ROUTE,
3211*4dc78e53SAndroid Build Coastguard Worker 	.co_groups		= link_groups,
3212*4dc78e53SAndroid Build Coastguard Worker 	.co_request_update	= link_request_update,
3213*4dc78e53SAndroid Build Coastguard Worker 	.co_msg_parser		= link_msg_parser,
3214*4dc78e53SAndroid Build Coastguard Worker 	.co_obj_ops		= &link_obj_ops,
3215*4dc78e53SAndroid Build Coastguard Worker };
3216*4dc78e53SAndroid Build Coastguard Worker 
link_init(void)3217*4dc78e53SAndroid Build Coastguard Worker static void _nl_init link_init(void)
3218*4dc78e53SAndroid Build Coastguard Worker {
3219*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_register(&rtnl_link_ops);
3220*4dc78e53SAndroid Build Coastguard Worker }
3221*4dc78e53SAndroid Build Coastguard Worker 
link_exit(void)3222*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit link_exit(void)
3223*4dc78e53SAndroid Build Coastguard Worker {
3224*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_unregister(&rtnl_link_ops);
3225*4dc78e53SAndroid Build Coastguard Worker }
3226*4dc78e53SAndroid Build Coastguard Worker 
3227*4dc78e53SAndroid Build Coastguard Worker /** @} */
3228