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