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
65static struct nl_cache_ops rtnl_link_ops;
66static struct nl_object_ops link_obj_ops;
67/** @endcond */
68
69static 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
87static 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
98static 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
110static 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
131static 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
142static 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
153static 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
164static 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
190static 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
206static 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
231static 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
269struct 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
298static 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
304int 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
478static 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);
635errout:
636	rtnl_link_af_ops_put(af_ops);
637	rtnl_link_put(link);
638	return err;
639}
640
641static 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
648static 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
704static 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
766static 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
832static 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
878static 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
900static 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
943out:
944	return diff;
945
946protinfo_mismatch:
947	diff |= LINK_DIFF(PROTINFO, 1);
948	goto out;
949
950#undef LINK_DIFF
951}
952
953static 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
982static 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 */
1018int 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 */
1053struct 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 */
1085struct 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 */
1117int 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
1145nla_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 */
1166int 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 */
1208char * 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 */
1231int 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
1247int 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
1299nla_put_failure:
1300	return -NLE_MSGSIZE;
1301}
1302
1303static 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
1350nla_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 */
1376int 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 */
1405int 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 */
1437int 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
1469errout:
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 */
1504int 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
1514retry:
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
1525errout:
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 */
1550int 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
1575nla_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 */
1604int 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 */
1628struct 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 */
1637void 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 */
1656void 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 */
1670char *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 */
1680void 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 */
1692uint32_t rtnl_link_get_group(struct rtnl_link *link)
1693{
1694	return link->l_group;
1695}
1696
1697static 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 */
1720void 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 */
1734struct 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 */
1751void 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 */
1765struct 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 */
1778void 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 */
1793void 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 */
1809unsigned 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 */
1819void 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 */
1840int 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 */
1854void 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 */
1868unsigned 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 */
1884void 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 */
1899int 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 */
1912void 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 */
1926unsigned 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 */
1941void 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 */
1957unsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
1958{
1959	return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0;
1960}
1961
1962void 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
1968int 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 */
1980void 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 */
1993int 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 */
2005void 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 */
2018uint8_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 */
2031void 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 */
2045uint8_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 */
2058void 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 */
2072uint8_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 */
2085const 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 */
2102void 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 */
2128void 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 */
2142char *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 */
2155int 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 */
2171uint64_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 */
2190int 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 */
2213int 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
2244errout:
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 */
2256char *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 */
2270void 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 */
2283uint32_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 */
2302void 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 */
2314uint32_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 */
2333void 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 */
2345uint32_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 */
2356struct nl_data *rtnl_link_get_phys_port_id(struct rtnl_link *link)
2357{
2358	return link->l_phys_port_id;
2359}
2360
2361void 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
2367int rtnl_link_get_ns_fd(struct rtnl_link *link)
2368{
2369	return link->l_ns_fd;
2370}
2371
2372void 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
2378pid_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 */
2403int 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
2432errout:
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 */
2458int 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 */
2477int 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 */
2501int 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
2513static 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
2535char *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
2541int rtnl_link_str2flags(const char *name)
2542{
2543	return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
2544}
2545
2546static 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
2612char *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
2617int rtnl_link_str2stat(const char *name)
2618{
2619	return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
2620}
2621
2622static 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
2632char *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
2638int rtnl_link_str2operstate(const char *name)
2639{
2640	return __str2type(name, link_operstates,
2641			  ARRAY_SIZE(link_operstates));
2642}
2643
2644static const struct trans_tbl link_modes[] = {
2645	__ADD(IF_LINK_MODE_DEFAULT, default)
2646	__ADD(IF_LINK_MODE_DORMANT, dormant)
2647};
2648
2649static const struct trans_tbl carrier_states[] = {
2650	__ADD(IF_CARRIER_DOWN, down)
2651	__ADD(IF_CARRIER_UP, up)
2652};
2653
2654char *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
2659int rtnl_link_str2mode(const char *name)
2660{
2661	return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
2662}
2663
2664char *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
2670int 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 */
2684int 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 */
2692char *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 */
2700void 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 */
2709unsigned int rtnl_link_get_weight(struct rtnl_link *link)
2710{
2711	return link->l_weight;
2712}
2713
2714/** @} */
2715
2716static 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
2732static struct nl_af_group link_groups[] = {
2733	{ AF_UNSPEC,	RTNLGRP_LINK },
2734	{ AF_BRIDGE,    RTNLGRP_LINK },
2735	{ END_OF_GROUP_LIST },
2736};
2737
2738static 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
2755static void __init link_init(void)
2756{
2757	nl_cache_mngt_register(&rtnl_link_ops);
2758}
2759
2760static void __exit link_exit(void)
2761{
2762	nl_cache_mngt_unregister(&rtnl_link_ops);
2763}
2764
2765/** @} */
2766