Home | History | Annotate | Download | only in route
      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 (at) 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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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 
   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 
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   1692 uint32_t rtnl_link_get_group(struct rtnl_link *link)
   1693 {
   1694 	return link->l_group;
   1695 }
   1696 
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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 
   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 
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   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  */
   2356 struct nl_data *rtnl_link_get_phys_port_id(struct rtnl_link *link)
   2357 {
   2358 	return link->l_phys_port_id;
   2359 }
   2360 
   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 
   2367 int rtnl_link_get_ns_fd(struct rtnl_link *link)
   2368 {
   2369 	return link->l_ns_fd;
   2370 }
   2371 
   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 
   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  */
   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  */
   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  */
   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  */
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2659 int rtnl_link_str2mode(const char *name)
   2660 {
   2661 	return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
   2662 }
   2663 
   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 
   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  */
   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  */
   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  */
   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  */
   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 
   2755 static void __init link_init(void)
   2756 {
   2757 	nl_cache_mngt_register(&rtnl_link_ops);
   2758 }
   2759 
   2760 static void __exit link_exit(void)
   2761 {
   2762 	nl_cache_mngt_unregister(&rtnl_link_ops);
   2763 }
   2764 
   2765 /** @} */
   2766