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