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