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