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