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