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