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