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