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