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