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