libnl  3.2.7
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  nl_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  *
1446  * @copydetails nl_object_put()
1447  */
1448 void rtnl_link_put(struct rtnl_link *link)
1449 {
1450  nl_object_put((struct nl_object *) link);
1451 }
1452 
1453 /**
1454  * Set name of link object
1455  * @arg link Link object
1456  * @arg name New name
1457  *
1458  * @note To change the name of a link in the kernel, set the interface
1459  * index to the link you wish to change, modify the link name using
1460  * this function and pass the link object to rtnl_link_change() or
1461  * rtnl_link_add().
1462  *
1463  * @route_doc{link_attr_name, Link Name}
1464  * @see rtnl_link_get_name()
1465  * @see rtnl_link_set_ifindex()
1466  */
1467 void rtnl_link_set_name(struct rtnl_link *link, const char *name)
1468 {
1469  strncpy(link->l_name, name, sizeof(link->l_name) - 1);
1470  link->ce_mask |= LINK_ATTR_IFNAME;
1471 }
1472 
1473 /**
1474  * Return name of link object
1475  * @arg link Link object
1476  *
1477  * @route_doc{link_attr_name, Link Name}
1478  * @see rtnl_link_set_name()
1479  * @return Link name or NULL if name is not specified
1480  */
1481 char *rtnl_link_get_name(struct rtnl_link *link)
1482 {
1483  return link->ce_mask & LINK_ATTR_IFNAME ? link->l_name : NULL;
1484 }
1485 
1486 static inline void __assign_addr(struct rtnl_link *link, struct nl_addr **pos,
1487  struct nl_addr *new, int flag)
1488 {
1489  if (*pos)
1490  nl_addr_put(*pos);
1491 
1492  nl_addr_get(new);
1493  *pos = new;
1494 
1495  link->ce_mask |= flag;
1496 }
1497 
1498 /**
1499  * Set link layer address of link object
1500  * @arg link Link object
1501  * @arg addr New link layer address
1502  *
1503  * The function increments the reference counter of the address object
1504  * and overwrites any existing link layer address previously assigned.
1505  *
1506  * @route_doc{link_attr_address, Link layer address}
1507  * @see rtnl_link_get_addr()
1508  */
1509 void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr)
1510 {
1511  __assign_addr(link, &link->l_addr, addr, LINK_ATTR_ADDR);
1512 }
1513 
1514 /**
1515  * Return link layer address of link object
1516  * @arg link Link object
1517  *
1518  * @copydoc pointer_lifetime_warning
1519  * @route_doc{link_attr_address, Link Layer Address}
1520  * @see rtnl_link_set_addr()
1521  * @return Link layer address or NULL if not set.
1522  */
1523 struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link)
1524 {
1525  return link->ce_mask & LINK_ATTR_ADDR ? link->l_addr : NULL;
1526 }
1527 
1528 /**
1529  * Set link layer broadcast address of link object
1530  * @arg link Link object
1531  * @arg addr New broadcast address
1532  *
1533  * The function increments the reference counter of the address object
1534  * and overwrites any existing link layer broadcast address previously
1535  * assigned.
1536  *
1537  * @route_doc{link_attr_broadcast, Link Layer Broadcast Address}
1538  * @see rtnl_link_get_broadcast()
1539  */
1540 void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr)
1541 {
1542  __assign_addr(link, &link->l_bcast, addr, LINK_ATTR_BRD);
1543 }
1544 
1545 /**
1546  * Return link layer broadcast address of link object
1547  * @arg link Link object
1548  *
1549  * @copydoc pointer_lifetime_warning
1550  * @route_doc{link_attr_address, Link Layer Address}
1551  * @see rtnl_link_set_broadcast()
1552  * @return Link layer address or NULL if not set.
1553  */
1554 struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link)
1555 {
1556  return link->ce_mask & LINK_ATTR_BRD ? link->l_bcast : NULL;
1557 }
1558 
1559 /**
1560  * Set flags of link object
1561  * @arg link Link object
1562  * @arg flags Flags
1563  *
1564  * @see rtnl_link_get_flags()
1565  * @see rtnl_link_unset_flags()
1566  */
1567 void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags)
1568 {
1569  link->l_flag_mask |= flags;
1570  link->l_flags |= flags;
1571  link->ce_mask |= LINK_ATTR_FLAGS;
1572 }
1573 
1574 /**
1575  * Unset flags of link object
1576  * @arg link Link object
1577  * @arg flags Flags
1578  *
1579  * @see rtnl_link_set_flags()
1580  * @see rtnl_link_get_flags()
1581  */
1582 void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags)
1583 {
1584  link->l_flag_mask |= flags;
1585  link->l_flags &= ~flags;
1586  link->ce_mask |= LINK_ATTR_FLAGS;
1587 }
1588 
1589 /**
1590  * Return flags of link object
1591  * @arg link Link object
1592  *
1593  * @route_doc{link_attr_flags, Link Flags}
1594  * @see rtnl_link_set_flags()
1595  * @see rtnl_link_unset_flags()
1596  * @return Link flags or 0 if none have been set.
1597  */
1598 unsigned int rtnl_link_get_flags(struct rtnl_link *link)
1599 {
1600  return link->l_flags;
1601 }
1602 
1603 /**
1604  * Set address family of link object
1605  *
1606  * @see rtnl_link_get_family()
1607  */
1608 void rtnl_link_set_family(struct rtnl_link *link, int family)
1609 {
1610  link->l_family = family;
1611  link->ce_mask |= LINK_ATTR_FAMILY;
1612 }
1613 
1614 /**
1615  * Return address family of link object
1616  * @arg link Link object
1617  *
1618  * @see rtnl_link_set_family()
1619  * @return Address family or \c AF_UNSPEC if not specified.
1620  */
1622 {
1623  return link->ce_mask & LINK_ATTR_FAMILY ? link->l_family : AF_UNSPEC;
1624 }
1625 
1626 /**
1627  * Set hardware type of link object
1628  * @arg link Link object
1629  * @arg arptype New hardware type \c (ARPHRD_*)
1630  *
1631  * @route_doc{link_attr_arptype, Hardware Type}
1632  * @copydoc read_only_attribute
1633  * @see rtnl_link_get_arptype()
1634  */
1635 void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype)
1636 {
1637  link->l_arptype = arptype;
1638  link->ce_mask |= LINK_ATTR_ARPTYPE;
1639 }
1640 
1641 /**
1642  * Get hardware type of link object
1643  * @arg link Link object
1644  *
1645  * @route_doc{link_attr_arptype, Hardware Type}
1646  * @see rtnl_link_set_arptype()
1647  * @return Hardware type \c (ARPHRD_ETHER *) or \c ARPHRD_VOID
1648  */
1649 unsigned int rtnl_link_get_arptype(struct rtnl_link *link)
1650 {
1651  if (link->ce_mask & LINK_ATTR_ARPTYPE)
1652  return link->l_arptype;
1653  else
1654  return ARPHRD_VOID;
1655 }
1656 
1657 /**
1658  * Set interface index of link object
1659  * @arg link Link object
1660  * @arg ifindex Interface index
1661  *
1662  * @route_doc{link_attr_ifindex, Interface Index}
1663  * @see rtnl_link_get_ifindex()
1664  */
1665 void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex)
1666 {
1667  link->l_index = ifindex;
1668  link->ce_mask |= LINK_ATTR_IFINDEX;
1669 }
1670 
1671 
1672 /**
1673  * Return interface index of link object
1674  * @arg link Link object
1675  *
1676  * @route_doc{link_attr_ifindex, Interface Index}
1677  * @see rtnl_link_set_ifindex()
1678  * @return Interface index or 0 if not set.
1679  */
1681 {
1682  return link->l_index;
1683 }
1684 
1685 /**
1686  * Set Maximum Transmission Unit of link object
1687  * @arg link Link object
1688  * @arg mtu New MTU value in number of bytes
1689  *
1690  * @route_doc{link_attr_mtu, Maximum Transmission Unit}
1691  * @see rtnl_link_get_mtu()
1692  */
1693 void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu)
1694 {
1695  link->l_mtu = mtu;
1696  link->ce_mask |= LINK_ATTR_MTU;
1697 }
1698 
1699 /**
1700  * Return maximum transmission unit of link object
1701  * @arg link Link object
1702  *
1703  * @route_doc{link_attr_mtu, Maximum Transmission Unit}
1704  * @see rtnl_link_set_mtu()
1705  * @return MTU in bytes or 0 if not set
1706  */
1707 unsigned int rtnl_link_get_mtu(struct rtnl_link *link)
1708 {
1709  return link->l_mtu;
1710 }
1711 
1712 /**
1713  * Set transmission queue length
1714  * @arg link Link object
1715  * @arg txqlen New queue length
1716  *
1717  * The unit is dependant on the link type. The most common units is number
1718  * of packets.
1719  *
1720  * @route_doc{link_attr_txqlen, Transmission Queue Length}
1721  */
1722 void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen)
1723 {
1724  link->l_txqlen = txqlen;
1725  link->ce_mask |= LINK_ATTR_TXQLEN;
1726 }
1727 
1728 /**
1729  * Return transmission queue length
1730  * @arg link Link object
1731  *
1732  * The unit is dependant on the link type. The most common units is number
1733  * of packets.
1734  *
1735  * @route_doc{link_attr_txqlen, Transmission Queue Length}
1736  * @return queue length or 0 if not specified.
1737  */
1738 unsigned int rtnl_link_get_txqlen(struct rtnl_link *link)
1739 {
1740  return link->ce_mask & LINK_ATTR_TXQLEN ? link->l_txqlen : 0;
1741 }
1742 
1743 void rtnl_link_set_link(struct rtnl_link *link, int ifindex)
1744 {
1745  link->l_link = ifindex;
1746  link->ce_mask |= LINK_ATTR_LINK;
1747 }
1748 
1749 int rtnl_link_get_link(struct rtnl_link *link)
1750 {
1751  return link->l_link;
1752 }
1753 
1754 /**
1755  * Set master link of link object
1756  * @arg link Link object
1757  * @arg ifindex Interface index of master link
1758  *
1759  * @see rtnl_link_get_master()
1760  */
1761 void rtnl_link_set_master(struct rtnl_link *link, int ifindex)
1762 {
1763  link->l_master = ifindex;
1764  link->ce_mask |= LINK_ATTR_MASTER;
1765 }
1766 
1767 /**
1768  * Return master link of link object
1769  * @arg link Link object
1770  *
1771  * @see rtnl_link_set_master()
1772  * @return Interface index of master link or 0 if not specified
1773  */
1775 {
1776  return link->l_master;
1777 }
1778 
1779 /**
1780  * Set operational status of link object
1781  * @arg link Link object
1782  * @arg status New opertional status
1783  *
1784  * @route_doc{link_attr_operstate, Operational Status}}
1785  * @see rtnl_link_get_operstate()
1786  */
1787 void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t status)
1788 {
1789  link->l_operstate = status;
1790  link->ce_mask |= LINK_ATTR_OPERSTATE;
1791 }
1792 
1793 /**
1794  * Return operational status of link object
1795  * @arg link Link object
1796  *
1797  * @route_doc{link_attr_operstate, Operational Status}
1798  * @see rtnl_link_set_operstate()
1799  * @return Opertional state or \c IF_OPER_UNKNOWN
1800  */
1801 uint8_t rtnl_link_get_operstate(struct rtnl_link *link)
1802 {
1803  return link->l_operstate;
1804 }
1805 
1806 /**
1807  * Set link mode of link object
1808  * @arg link Link object
1809  * @arg mode New link mode
1810  *
1811  * @route_doc{link_attr_mode, Mode}
1812  * @see rtnl_link_get_linkmode()
1813  */
1814 void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode)
1815 {
1816  link->l_linkmode = mode;
1817  link->ce_mask |= LINK_ATTR_LINKMODE;
1818 }
1819 
1820 /**
1821  * Return link mode of link object
1822  * @arg link Link object
1823  *
1824  * @route_doc{link_attr_mode, Mode}
1825  * @see rtnl_link_get_linkmode()
1826  * @return Link mode or \c IF_LINK_MODE_DEFAULT
1827  */
1828 uint8_t rtnl_link_get_linkmode(struct rtnl_link *link)
1829 {
1830  return link->l_linkmode;
1831 }
1832 
1833 /**
1834  * Return alias name of link object (SNMP IfAlias)
1835  * @arg link Link object
1836  *
1837  * @route_doc{link_attr_alias, Alias}
1838  * @see rtnl_link_set_ifalias()
1839  * @return Alias name or NULL if not set.
1840  */
1841 const char *rtnl_link_get_ifalias(struct rtnl_link *link)
1842 {
1843  return link->l_ifalias;
1844 }
1845 
1846 /**
1847  * Set alias name of link object (SNMP IfAlias)
1848  * @arg link Link object
1849  * @arg alias Alias name or NULL to unset
1850  *
1851  * Sets the alias name of the link to the specified name. The alias
1852  * name can be unset by specyfing NULL as the alias. The name will
1853  * be strdup()ed, so no need to provide a persistent character string.
1854  *
1855  * @route_doc{link_attr_alias, Alias}
1856  * @see rtnl_link_get_ifalias()
1857  */
1858 void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias)
1859 {
1860  free(link->l_ifalias);
1861  link->ce_mask &= ~LINK_ATTR_IFALIAS;
1862 
1863  if (alias) {
1864  link->l_ifalias = strdup(alias);
1865  link->ce_mask |= LINK_ATTR_IFALIAS;
1866  }
1867 }
1868 
1869 /**
1870  * Set queueing discipline name of link object
1871  * @arg link Link object
1872  * @arg name Name of queueing discipline
1873  *
1874  * @copydoc read_only_attribute
1875  *
1876  * For more information on how to modify the qdisc of a link, see section
1877  * @ref_route{route_tc, Traffic Control}.
1878  *
1879  * @route_doc{link_attr_qdisc, Queueing Discipline Name}
1880  * @see rtnl_link_get_qdisc()
1881  */
1882 void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name)
1883 {
1884  strncpy(link->l_qdisc, name, sizeof(link->l_qdisc) - 1);
1885  link->ce_mask |= LINK_ATTR_QDISC;
1886 }
1887 
1888 /**
1889  * Return name of queueing discipline of link object
1890  * @arg link Link object
1891  *
1892  * @route_doc{link_attr_qdisc, Queueing Discipline Name}
1893  * @see rtnl_link_set_qdisc()
1894  * @return Name of qdisc or NULL if not specified.
1895  */
1896 char *rtnl_link_get_qdisc(struct rtnl_link *link)
1897 {
1898  return link->ce_mask & LINK_ATTR_QDISC ? link->l_qdisc : NULL;
1899 }
1900 
1901 
1902 /**
1903  * Return number of PCI virtual functions of link object
1904  * @arg link Link object
1905  * @arg num_vf Pointer to store number of VFs
1906  *
1907  * @return 0 on success or -NLE_OPNOTSUPP if not available
1908  */
1909 int rtnl_link_get_num_vf(struct rtnl_link *link, uint32_t *num_vf)
1910 {
1911  if (link->ce_mask & LINK_ATTR_NUM_VF) {
1912  *num_vf = link->l_num_vf;
1913  return 0;
1914  } else
1915  return -NLE_OPNOTSUPP;
1916 }
1917 
1918 /**
1919  * Return value of link statistics counter
1920  * @arg link Link object
1921  * @arg id Identifier of statistical counter
1922  *
1923  * @return Value of counter or 0 if not specified.
1924  */
1926 {
1927  if (id > RTNL_LINK_STATS_MAX)
1928  return 0;
1929 
1930  return link->l_stats[id];
1931 }
1932 
1933 /**
1934  * Set value of link statistics counter
1935  * @arg link Link object
1936  * @arg id Identifier of statistical counter
1937  * @arg value New value
1938  *
1939  * \note Changing the value of a statistical counter will not change the
1940  * value in the kernel.
1941  *
1942  * @return 0 on success or a negative error code
1943  */
1945  const uint64_t value)
1946 {
1947  if (id > RTNL_LINK_STATS_MAX)
1948  return -NLE_INVAL;
1949 
1950  link->l_stats[id] = value;
1951 
1952  return 0;
1953 }
1954 
1955 /**
1956  * Set type of link object
1957  * @arg link Link object
1958  * @arg type Name of link type
1959  *
1960  * Looks up the link type module and prepares the link to store type
1961  * specific attributes. If a type has been assigned already it will
1962  * be released with all link type specific attributes lost.
1963  *
1964  * @route_doc{link_modules, Link Modules}
1965  * @return 0 on success or a negative errror code.
1966  */
1967 int rtnl_link_set_type(struct rtnl_link *link, const char *type)
1968 {
1969  struct rtnl_link_info_ops *io;
1970  int err;
1971  char *kind;
1972 
1973  free(link->l_info_kind);
1974  link->ce_mask &= ~LINK_ATTR_LINKINFO;
1975  if (link->l_info_ops)
1976  release_link_info(link);
1977 
1978  if (!type)
1979  return 0;
1980 
1981  kind = strdup(type);
1982  if (!kind)
1983  return -NLE_NOMEM;
1984 
1985  io = rtnl_link_info_ops_lookup(type);
1986  if (io) {
1987  if (io->io_alloc && (err = io->io_alloc(link)) < 0)
1988  goto errout;
1989 
1990  link->l_info_ops = io;
1991  }
1992 
1993  link->l_info_kind = kind;
1994  link->ce_mask |= LINK_ATTR_LINKINFO;
1995 
1996  return 0;
1997 
1998 errout:
1999  free(kind);
2000  return err;
2001 }
2002 
2003 /**
2004  * Return type of link
2005  * @arg link Link object
2006  *
2007  * @route_doc{link_modules, Link Modules}
2008  * @return Name of link type or NULL if not specified.
2009  */
2010 char *rtnl_link_get_type(struct rtnl_link *link)
2011 {
2012  return link->l_info_kind;
2013 }
2014 
2015 /** @} */
2016 
2017 /**
2018  * @name Master/Slave
2019  * @{
2020  */
2021 
2022 /**
2023  * Enslave slave link to master link
2024  * @arg sock netlink socket
2025  * @arg master ifindex of master link
2026  * @arg slave ifindex of slave link
2027  *
2028  * This function is identical to rtnl_link_enslave() except that
2029  * it takes interface indices instead of rtnl_link objects.
2030  *
2031  * @see rtnl_link_enslave()
2032  *
2033  * @return 0 on success or a negative error code.
2034  */
2035 int rtnl_link_enslave_ifindex(struct nl_sock *sock, int master, int slave)
2036 {
2037  struct rtnl_link *link;
2038  int err;
2039 
2040  if (!(link = rtnl_link_alloc()))
2041  return -NLE_NOMEM;
2042 
2043  rtnl_link_set_ifindex(link, slave);
2044  rtnl_link_set_master(link, master);
2045 
2046  if ((err = rtnl_link_change(sock, link, link, 0)) < 0)
2047  goto errout;
2048 
2049  rtnl_link_put(link);
2050 
2051  /*
2052  * Due to the kernel not signaling whether this opertion is
2053  * supported or not, we will retrieve the attribute to see if the
2054  * request was successful. If the master assigned remains unchanged
2055  * we will return NLE_OPNOTSUPP to allow performing backwards
2056  * compatibility of some sort.
2057  */
2058  if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0)
2059  return err;
2060 
2061  if (rtnl_link_get_master(link) != master)
2062  err = -NLE_OPNOTSUPP;
2063 
2064 errout:
2065  rtnl_link_put(link);
2066 
2067  return err;
2068 }
2069 
2070 /**
2071  * Enslave slave link to master link
2072  * @arg sock netlink socket
2073  * @arg master master link
2074  * @arg slave slave link
2075  *
2076  * Constructs a RTM_NEWLINK or RTM_SETLINK message adding the slave to
2077  * the master and sends the request via the specified netlink socket.
2078  *
2079  * @note The feature of enslaving/releasing via netlink has only been added
2080  * recently to the kernel (Feb 2011). Also, the kernel does not signal
2081  * if the operation is not supported. Therefore this function will
2082  * verify if the master assignment has changed and will return
2083  * -NLE_OPNOTSUPP if it did not.
2084  *
2085  * @see rtnl_link_enslave_ifindex()
2086  * @see rtnl_link_release()
2087  *
2088  * @return 0 on success or a negative error code.
2089  */
2090 int rtnl_link_enslave(struct nl_sock *sock, struct rtnl_link *master,
2091  struct rtnl_link *slave)
2092 {
2093  return rtnl_link_enslave_ifindex(sock, rtnl_link_get_ifindex(master),
2094  rtnl_link_get_ifindex(slave));
2095 }
2096 
2097 /**
2098  * Release slave link from its master
2099  * @arg sock netlink socket
2100  * @arg slave slave link
2101  *
2102  * This function is identical to rtnl_link_release() except that
2103  * it takes an interface index instead of a rtnl_link object.
2104  *
2105  * @see rtnl_link_release()
2106  *
2107  * @return 0 on success or a negative error code.
2108  */
2109 int rtnl_link_release_ifindex(struct nl_sock *sock, int slave)
2110 {
2111  return rtnl_link_enslave_ifindex(sock, 0, slave);
2112 }
2113 
2114 /**
2115  * Release slave link from its master
2116  * @arg sock netlink socket
2117  * @arg slave slave link
2118  *
2119  * Constructs a RTM_NEWLINK or RTM_SETLINK message releasing the slave from
2120  * its master and sends the request via the specified netlink socket.
2121  *
2122  * @note The feature of enslaving/releasing via netlink has only been added
2123  * recently to the kernel (Feb 2011). Also, the kernel does not signal
2124  * if the operation is not supported. Therefore this function will
2125  * verify if the master assignment has changed and will return
2126  * -NLE_OPNOTSUPP if it did not.
2127  *
2128  * @see rtnl_link_release_ifindex()
2129  * @see rtnl_link_enslave()
2130  *
2131  * @return 0 on success or a negative error code.
2132  */
2133 int rtnl_link_release(struct nl_sock *sock, struct rtnl_link *slave)
2134 {
2135  return rtnl_link_release_ifindex(sock, rtnl_link_get_ifindex(slave));
2136 }
2137 
2138 /** @} */
2139 
2140 /**
2141  * @name Utilities
2142  * @{
2143  */
2144 
2145 static const struct trans_tbl link_flags[] = {
2146  __ADD(IFF_LOOPBACK, loopback)
2147  __ADD(IFF_BROADCAST, broadcast)
2148  __ADD(IFF_POINTOPOINT, pointopoint)
2149  __ADD(IFF_MULTICAST, multicast)
2150  __ADD(IFF_NOARP, noarp)
2151  __ADD(IFF_ALLMULTI, allmulti)
2152  __ADD(IFF_PROMISC, promisc)
2153  __ADD(IFF_MASTER, master)
2154  __ADD(IFF_SLAVE, slave)
2155  __ADD(IFF_DEBUG, debug)
2156  __ADD(IFF_DYNAMIC, dynamic)
2157  __ADD(IFF_AUTOMEDIA, automedia)
2158  __ADD(IFF_PORTSEL, portsel)
2159  __ADD(IFF_NOTRAILERS, notrailers)
2160  __ADD(IFF_UP, up)
2161  __ADD(IFF_RUNNING, running)
2162  __ADD(IFF_LOWER_UP, lowerup)
2163  __ADD(IFF_DORMANT, dormant)
2164  __ADD(IFF_ECHO, echo)
2165 };
2166 
2167 char *rtnl_link_flags2str(int flags, char *buf, size_t len)
2168 {
2169  return __flags2str(flags, buf, len, link_flags,
2170  ARRAY_SIZE(link_flags));
2171 }
2172 
2173 int rtnl_link_str2flags(const char *name)
2174 {
2175  return __str2flags(name, link_flags, ARRAY_SIZE(link_flags));
2176 }
2177 
2178 static const struct trans_tbl link_stats[] = {
2179  __ADD(RTNL_LINK_RX_PACKETS, rx_packets)
2180  __ADD(RTNL_LINK_TX_PACKETS, tx_packets)
2181  __ADD(RTNL_LINK_RX_BYTES, rx_bytes)
2182  __ADD(RTNL_LINK_TX_BYTES, tx_bytes)
2183  __ADD(RTNL_LINK_RX_ERRORS, rx_errors)
2184  __ADD(RTNL_LINK_TX_ERRORS, tx_errors)
2185  __ADD(RTNL_LINK_RX_DROPPED, rx_dropped)
2186  __ADD(RTNL_LINK_TX_DROPPED, tx_dropped)
2187  __ADD(RTNL_LINK_RX_COMPRESSED, rx_compressed)
2188  __ADD(RTNL_LINK_TX_COMPRESSED, tx_compressed)
2189  __ADD(RTNL_LINK_RX_FIFO_ERR, rx_fifo_err)
2190  __ADD(RTNL_LINK_TX_FIFO_ERR, tx_fifo_err)
2191  __ADD(RTNL_LINK_RX_LEN_ERR, rx_len_err)
2192  __ADD(RTNL_LINK_RX_OVER_ERR, rx_over_err)
2193  __ADD(RTNL_LINK_RX_CRC_ERR, rx_crc_err)
2194  __ADD(RTNL_LINK_RX_FRAME_ERR, rx_frame_err)
2195  __ADD(RTNL_LINK_RX_MISSED_ERR, rx_missed_err)
2196  __ADD(RTNL_LINK_TX_ABORT_ERR, tx_abort_err)
2197  __ADD(RTNL_LINK_TX_CARRIER_ERR, tx_carrier_err)
2198  __ADD(RTNL_LINK_TX_HBEAT_ERR, tx_hbeat_err)
2199  __ADD(RTNL_LINK_TX_WIN_ERR, tx_win_err)
2200  __ADD(RTNL_LINK_COLLISIONS, collisions)
2201  __ADD(RTNL_LINK_MULTICAST, multicast)
2202  __ADD(RTNL_LINK_IP6_INPKTS, Ip6InReceives)
2203  __ADD(RTNL_LINK_IP6_INHDRERRORS, Ip6InHdrErrors)
2204  __ADD(RTNL_LINK_IP6_INTOOBIGERRORS, Ip6InTooBigErrors)
2205  __ADD(RTNL_LINK_IP6_INNOROUTES, Ip6InNoRoutes)
2206  __ADD(RTNL_LINK_IP6_INADDRERRORS, Ip6InAddrErrors)
2207  __ADD(RTNL_LINK_IP6_INUNKNOWNPROTOS, Ip6InUnknownProtos)
2208  __ADD(RTNL_LINK_IP6_INTRUNCATEDPKTS, Ip6InTruncatedPkts)
2209  __ADD(RTNL_LINK_IP6_INDISCARDS, Ip6InDiscards)
2210  __ADD(RTNL_LINK_IP6_INDELIVERS, Ip6InDelivers)
2211  __ADD(RTNL_LINK_IP6_OUTFORWDATAGRAMS, Ip6OutForwDatagrams)
2212  __ADD(RTNL_LINK_IP6_OUTPKTS, Ip6OutRequests)
2213  __ADD(RTNL_LINK_IP6_OUTDISCARDS, Ip6OutDiscards)
2214  __ADD(RTNL_LINK_IP6_OUTNOROUTES, Ip6OutNoRoutes)
2215  __ADD(RTNL_LINK_IP6_REASMTIMEOUT, Ip6ReasmTimeout)
2216  __ADD(RTNL_LINK_IP6_REASMREQDS, Ip6ReasmReqds)
2217  __ADD(RTNL_LINK_IP6_REASMOKS, Ip6ReasmOKs)
2218  __ADD(RTNL_LINK_IP6_REASMFAILS, Ip6ReasmFails)
2219  __ADD(RTNL_LINK_IP6_FRAGOKS, Ip6FragOKs)
2220  __ADD(RTNL_LINK_IP6_FRAGFAILS, Ip6FragFails)
2221  __ADD(RTNL_LINK_IP6_FRAGCREATES, Ip6FragCreates)
2222  __ADD(RTNL_LINK_IP6_INMCASTPKTS, Ip6InMcastPkts)
2223  __ADD(RTNL_LINK_IP6_OUTMCASTPKTS, Ip6OutMcastPkts)
2224  __ADD(RTNL_LINK_IP6_INBCASTPKTS, Ip6InBcastPkts)
2225  __ADD(RTNL_LINK_IP6_OUTBCASTPKTS, Ip6OutBcastPkts)
2226  __ADD(RTNL_LINK_IP6_INOCTETS, Ip6InOctets)
2227  __ADD(RTNL_LINK_IP6_OUTOCTETS, Ip6OutOctets)
2228  __ADD(RTNL_LINK_IP6_INMCASTOCTETS, Ip6InMcastOctets)
2229  __ADD(RTNL_LINK_IP6_OUTMCASTOCTETS, Ip6OutMcastOctets)
2230  __ADD(RTNL_LINK_IP6_INBCASTOCTETS, Ip6InBcastOctets)
2231  __ADD(RTNL_LINK_IP6_OUTBCASTOCTETS, Ip6OutBcastOctets)
2232  __ADD(RTNL_LINK_ICMP6_INMSGS, ICMP6_InMsgs)
2233  __ADD(RTNL_LINK_ICMP6_INERRORS, ICMP6_InErrors)
2234  __ADD(RTNL_LINK_ICMP6_OUTMSGS, ICMP6_OutMsgs)
2235  __ADD(RTNL_LINK_ICMP6_OUTERRORS, ICMP6_OutErrors)
2236 };
2237 
2238 char *rtnl_link_stat2str(int st, char *buf, size_t len)
2239 {
2240  return __type2str(st, buf, len, link_stats, ARRAY_SIZE(link_stats));
2241 }
2242 
2243 int rtnl_link_str2stat(const char *name)
2244 {
2245  return __str2type(name, link_stats, ARRAY_SIZE(link_stats));
2246 }
2247 
2248 static const struct trans_tbl link_operstates[] = {
2249  __ADD(IF_OPER_UNKNOWN, unknown)
2250  __ADD(IF_OPER_NOTPRESENT, notpresent)
2251  __ADD(IF_OPER_DOWN, down)
2252  __ADD(IF_OPER_LOWERLAYERDOWN, lowerlayerdown)
2253  __ADD(IF_OPER_TESTING, testing)
2254  __ADD(IF_OPER_DORMANT, dormant)
2255  __ADD(IF_OPER_UP, up)
2256 };
2257 
2258 char *rtnl_link_operstate2str(uint8_t st, char *buf, size_t len)
2259 {
2260  return __type2str(st, buf, len, link_operstates,
2261  ARRAY_SIZE(link_operstates));
2262 }
2263 
2264 int rtnl_link_str2operstate(const char *name)
2265 {
2266  return __str2type(name, link_operstates,
2267  ARRAY_SIZE(link_operstates));
2268 }
2269 
2270 static const struct trans_tbl link_modes[] = {
2271  __ADD(IF_LINK_MODE_DEFAULT, default)
2272  __ADD(IF_LINK_MODE_DORMANT, dormant)
2273 };
2274 
2275 char *rtnl_link_mode2str(uint8_t st, char *buf, size_t len)
2276 {
2277  return __type2str(st, buf, len, link_modes, ARRAY_SIZE(link_modes));
2278 }
2279 
2280 int rtnl_link_str2mode(const char *name)
2281 {
2282  return __str2type(name, link_modes, ARRAY_SIZE(link_modes));
2283 }
2284 
2285 /** @} */
2286 
2287 /**
2288  * @name Deprecated Functions
2289  */
2290 
2291 /**
2292  * @deprecated Use of this function is deprecated, use rtnl_link_set_type()
2293  */
2294 int rtnl_link_set_info_type(struct rtnl_link *link, const char *type)
2295 {
2296  return rtnl_link_set_type(link, type);
2297 }
2298 
2299 /**
2300  * @deprecated Use of this function is deprecated, use rtnl_link_get_type()
2301  */
2303 {
2304  return rtnl_link_get_type(link);
2305 }
2306 
2307 /**
2308  * @deprecated The weight attribute is unused and obsoleted in all recent kernels
2309  */
2310 void rtnl_link_set_weight(struct rtnl_link *link, unsigned int weight)
2311 {
2312  link->l_weight = weight;
2313  link->ce_mask |= LINK_ATTR_WEIGHT;
2314 }
2315 
2316 /**
2317  * @deprecated The weight attribute is unused and obsoleted in all recent kernels
2318  */
2319 unsigned int rtnl_link_get_weight(struct rtnl_link *link)
2320 {
2321  return link->l_weight;
2322 }
2323 
2324 /** @} */
2325 
2326 static struct nl_object_ops link_obj_ops = {
2327  .oo_name = "route/link",
2328  .oo_size = sizeof(struct rtnl_link),
2329  .oo_free_data = link_free_data,
2330  .oo_clone = link_clone,
2331  .oo_dump = {
2332  [NL_DUMP_LINE] = link_dump_line,
2333  [NL_DUMP_DETAILS] = link_dump_details,
2334  [NL_DUMP_STATS] = link_dump_stats,
2335  },
2336  .oo_compare = link_compare,
2337  .oo_attrs2str = link_attrs2str,
2338  .oo_id_attrs = LINK_ATTR_IFINDEX,
2339 };
2340 
2341 static struct nl_af_group link_groups[] = {
2342  { AF_UNSPEC, RTNLGRP_LINK },
2343  { END_OF_GROUP_LIST },
2344 };
2345 
2346 static struct nl_cache_ops rtnl_link_ops = {
2347  .co_name = "route/link",
2348  .co_hdrsize = sizeof(struct ifinfomsg),
2349  .co_msgtypes = {
2350  { RTM_NEWLINK, NL_ACT_NEW, "new" },
2351  { RTM_DELLINK, NL_ACT_DEL, "del" },
2352  { RTM_GETLINK, NL_ACT_GET, "get" },
2353  { RTM_SETLINK, NL_ACT_CHANGE, "set" },
2354  END_OF_MSGTYPES_LIST,
2355  },
2356  .co_protocol = NETLINK_ROUTE,
2357  .co_groups = link_groups,
2358  .co_request_update = link_request_update,
2359  .co_msg_parser = link_msg_parser,
2360  .co_event_filter = link_event_filter,
2361  .co_obj_ops = &link_obj_ops,
2362 };
2363 
2364 static void __init link_init(void)
2365 {
2366  nl_cache_mngt_register(&rtnl_link_ops);
2367 }
2368 
2369 static void __exit link_exit(void)
2370 {
2371  nl_cache_mngt_unregister(&rtnl_link_ops);
2372 }
2373 
2374 /** @} */