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