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