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