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