libnl  3.5.0
addr.c
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * lib/route/addr.c Addresses
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation version 2.1
8  * of the License.
9  *
10  * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
11  * Copyright (c) 2003-2006 Baruch Even <baruch@ev-en.org>,
12  * Mediatrix Telecom, inc. <ericb@mediatrix.com>
13  */
14 
15 /**
16  * @ingroup rtnl
17  * @defgroup rtaddr Addresses
18  * @brief
19  *
20  * @note The maximum size of an address label is IFNAMSIZ.
21  *
22  * @note The address may not contain a prefix length if the peer address
23  * has been specified already.
24  *
25  * @par 1) Address Addition
26  * @code
27  * // Allocate an empty address object to be filled out with the attributes
28  * // of the new address.
29  * struct rtnl_addr *addr = rtnl_addr_alloc();
30  *
31  * // Fill out the mandatory attributes of the new address. Setting the
32  * // local address will automatically set the address family and the
33  * // prefix length to the correct values.
34  * rtnl_addr_set_ifindex(addr, ifindex);
35  * rtnl_addr_set_local(addr, local_addr);
36  *
37  * // The label of the address can be specified, currently only supported
38  * // by IPv4 and DECnet.
39  * rtnl_addr_set_label(addr, "mylabel");
40  *
41  * // The peer address can be specified if necessary, in either case a peer
42  * // address will be sent to the kernel in order to fullfil the interface
43  * // requirements. If none is set, it will equal the local address.
44  * // Note: Real peer addresses are only supported by IPv4 for now.
45  * rtnl_addr_set_peer(addr, peer_addr);
46  *
47  * // In case you want to have the address have a scope other than global
48  * // it may be overwritten using rtnl_addr_set_scope(). The scope currently
49  * // cannot be set for IPv6 addresses.
50  * rtnl_addr_set_scope(addr, rtnl_str2scope("site"));
51  *
52  * // Broadcast address may be specified using the relevant
53  * // functions, the address family will be verified if one of the other
54  * // addresses has been set already. Currently only works for IPv4.
55  * rtnl_addr_set_broadcast(addr, broadcast_addr);
56  *
57  * // Build the netlink message and send it to the kernel, the operation will
58  * // block until the operation has been completed. Alternatively the required
59  * // netlink message can be built using rtnl_addr_build_add_request() to be
60  * // sent out using nl_send_auto_complete().
61  * rtnl_addr_add(sk, addr, 0);
62  *
63  * // Free the memory
64  * rtnl_addr_put(addr);
65  * @endcode
66  *
67  * @par 2) Address Deletion
68  * @code
69  * // Allocate an empty address object to be filled out with the attributes
70  * // matching the address to be deleted. Alternatively a fully equipped
71  * // address object out of a cache can be used instead.
72  * struct rtnl_addr *addr = rtnl_addr_alloc();
73  *
74  * // The only mandatory parameter besides the address family is the interface
75  * // index the address is on, i.e. leaving out all other parameters will
76  * // result in all addresses of the specified address family interface tuple
77  * // to be deleted.
78  * rtnl_addr_set_ifindex(addr, ifindex);
79  *
80  * // Specyfing the address family manually is only required if neither the
81  * // local nor peer address have been specified.
82  * rtnl_addr_set_family(addr, AF_INET);
83  *
84  * // Specyfing the local address is optional but the best choice to delete
85  * // specific addresses.
86  * rtnl_addr_set_local(addr, local_addr);
87  *
88  * // The label of the address can be specified, currently only supported
89  * // by IPv4 and DECnet.
90  * rtnl_addr_set_label(addr, "mylabel");
91  *
92  * // The peer address can be specified if necessary, in either case a peer
93  * // address will be sent to the kernel in order to fullfil the interface
94  * // requirements. If none is set, it will equal the local address.
95  * // Note: Real peer addresses are only supported by IPv4 for now.
96  * rtnl_addr_set_peer(addr, peer_addr);
97  *
98  * // Build the netlink message and send it to the kernel, the operation will
99  * // block until the operation has been completed. Alternatively the required
100  * // netlink message can be built using rtnl_addr_build_delete_request()
101  * // to be sent out using nl_send_auto_complete().
102  * rtnl_addr_delete(sk, addr, 0);
103  *
104  * // Free the memory
105  * rtnl_addr_put(addr);
106  * @endcode
107  * @{
108  */
109 
110 #include <netlink-private/netlink.h>
111 #include <netlink/netlink.h>
112 #include <netlink/route/rtnl.h>
113 #include <netlink/route/addr.h>
114 #include <netlink/route/route.h>
115 #include <netlink/route/link.h>
116 #include <netlink/utils.h>
117 
118 /** @cond SKIP */
119 #define ADDR_ATTR_FAMILY 0x0001
120 #define ADDR_ATTR_PREFIXLEN 0x0002
121 #define ADDR_ATTR_FLAGS 0x0004
122 #define ADDR_ATTR_SCOPE 0x0008
123 #define ADDR_ATTR_IFINDEX 0x0010
124 #define ADDR_ATTR_LABEL 0x0020
125 #define ADDR_ATTR_CACHEINFO 0x0040
126 #define ADDR_ATTR_PEER 0x0080
127 #define ADDR_ATTR_LOCAL 0x0100
128 #define ADDR_ATTR_BROADCAST 0x0200
129 #define ADDR_ATTR_MULTICAST 0x0400
130 #define ADDR_ATTR_ANYCAST 0x0800
131 
132 static struct nl_cache_ops rtnl_addr_ops;
133 static struct nl_object_ops addr_obj_ops;
134 /** @endcond */
135 
136 static void addr_constructor(struct nl_object *obj)
137 {
138  struct rtnl_addr *addr = nl_object_priv(obj);
139 
140  addr->a_scope = RT_SCOPE_NOWHERE;
141 }
142 
143 static void addr_free_data(struct nl_object *obj)
144 {
145  struct rtnl_addr *addr = nl_object_priv(obj);
146 
147  if (!addr)
148  return;
149 
150  nl_addr_put(addr->a_peer);
151  nl_addr_put(addr->a_local);
152  nl_addr_put(addr->a_bcast);
153  nl_addr_put(addr->a_multicast);
154  nl_addr_put(addr->a_anycast);
155  rtnl_link_put(addr->a_link);
156 }
157 
158 static int addr_clone(struct nl_object *_dst, struct nl_object *_src)
159 {
160  struct rtnl_addr *dst = nl_object_priv(_dst);
161  struct rtnl_addr *src = nl_object_priv(_src);
162 
163  if (src->a_link) {
164  nl_object_get(OBJ_CAST(src->a_link));
165  dst->a_link = src->a_link;
166  }
167 
168  if (src->a_peer)
169  if (!(dst->a_peer = nl_addr_clone(src->a_peer)))
170  return -NLE_NOMEM;
171 
172  if (src->a_local)
173  if (!(dst->a_local = nl_addr_clone(src->a_local)))
174  return -NLE_NOMEM;
175 
176  if (src->a_bcast)
177  if (!(dst->a_bcast = nl_addr_clone(src->a_bcast)))
178  return -NLE_NOMEM;
179 
180  if (src->a_multicast)
181  if (!(dst->a_multicast = nl_addr_clone(src->a_multicast)))
182  return -NLE_NOMEM;
183 
184  if (src->a_anycast)
185  if (!(dst->a_anycast = nl_addr_clone(src->a_anycast)))
186  return -NLE_NOMEM;
187 
188  return 0;
189 }
190 
191 static struct nla_policy addr_policy[IFA_MAX+1] = {
192  [IFA_LABEL] = { .type = NLA_STRING,
193  .maxlen = IFNAMSIZ },
194  [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) },
195 };
196 
197 static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
198  struct nlmsghdr *nlh, struct nl_parser_param *pp)
199 {
200  struct rtnl_addr *addr;
201  struct ifaddrmsg *ifa;
202  struct nlattr *tb[IFA_MAX+1];
203  int err, family;
204  struct nl_cache *link_cache;
205  struct nl_addr *plen_addr = NULL;
206 
207  addr = rtnl_addr_alloc();
208  if (!addr)
209  return -NLE_NOMEM;
210 
211  addr->ce_msgtype = nlh->nlmsg_type;
212 
213  err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy);
214  if (err < 0)
215  goto errout;
216 
217  ifa = nlmsg_data(nlh);
218  addr->a_family = family = ifa->ifa_family;
219  addr->a_prefixlen = ifa->ifa_prefixlen;
220  addr->a_scope = ifa->ifa_scope;
221  addr->a_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) :
222  ifa->ifa_flags;
223  addr->a_ifindex = ifa->ifa_index;
224 
225  addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN |
226  ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX);
227 
228  if (tb[IFA_LABEL]) {
229  nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ);
230  addr->ce_mask |= ADDR_ATTR_LABEL;
231  }
232 
233  /* IPv6 only */
234  if (tb[IFA_CACHEINFO]) {
235  struct ifa_cacheinfo *ca;
236 
237  ca = nla_data(tb[IFA_CACHEINFO]);
238  addr->a_cacheinfo.aci_prefered = ca->ifa_prefered;
239  addr->a_cacheinfo.aci_valid = ca->ifa_valid;
240  addr->a_cacheinfo.aci_cstamp = ca->cstamp;
241  addr->a_cacheinfo.aci_tstamp = ca->tstamp;
242  addr->ce_mask |= ADDR_ATTR_CACHEINFO;
243  }
244 
245  if (family == AF_INET) {
246  uint32_t null = 0;
247 
248  /* for IPv4/AF_INET, kernel always sets IFA_LOCAL and IFA_ADDRESS, unless it
249  * is effectively 0.0.0.0. */
250  if (tb[IFA_LOCAL])
251  addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family);
252  else
253  addr->a_local = nl_addr_build(family, &null, sizeof (null));
254  if (!addr->a_local)
255  goto errout_nomem;
256  addr->ce_mask |= ADDR_ATTR_LOCAL;
257 
258  if (tb[IFA_ADDRESS])
259  addr->a_peer = nl_addr_alloc_attr(tb[IFA_ADDRESS], family);
260  else
261  addr->a_peer = nl_addr_build(family, &null, sizeof (null));
262  if (!addr->a_peer)
263  goto errout_nomem;
264 
265  if (!nl_addr_cmp (addr->a_local, addr->a_peer)) {
266  /* having IFA_ADDRESS equal to IFA_LOCAL does not really mean
267  * there is no peer. It means the peer is equal to the local address,
268  * which is the case for "normal" addresses.
269  *
270  * Still, clear the peer and pretend it is unset for backward
271  * compatibility. */
272  nl_addr_put(addr->a_peer);
273  addr->a_peer = NULL;
274  } else
275  addr->ce_mask |= ADDR_ATTR_PEER;
276 
277  plen_addr = addr->a_local;
278  } else {
279  if (tb[IFA_LOCAL]) {
280  addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family);
281  if (!addr->a_local)
282  goto errout_nomem;
283  addr->ce_mask |= ADDR_ATTR_LOCAL;
284  plen_addr = addr->a_local;
285  }
286 
287  if (tb[IFA_ADDRESS]) {
288  struct nl_addr *a;
289 
290  a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family);
291  if (!a)
292  goto errout_nomem;
293 
294  /* IPv6 sends the local address as IFA_ADDRESS with
295  * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS
296  * with IFA_ADDRESS being the peer address if they differ */
297  if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) {
298  nl_addr_put(addr->a_local);
299  addr->a_local = a;
300  addr->ce_mask |= ADDR_ATTR_LOCAL;
301  } else {
302  addr->a_peer = a;
303  addr->ce_mask |= ADDR_ATTR_PEER;
304  }
305 
306  plen_addr = a;
307  }
308  }
309 
310  if (plen_addr)
311  nl_addr_set_prefixlen(plen_addr, addr->a_prefixlen);
312 
313  /* IPv4 only */
314  if (tb[IFA_BROADCAST]) {
315  addr->a_bcast = nl_addr_alloc_attr(tb[IFA_BROADCAST], family);
316  if (!addr->a_bcast)
317  goto errout_nomem;
318 
319  addr->ce_mask |= ADDR_ATTR_BROADCAST;
320  }
321 
322  /* IPv6 only */
323  if (tb[IFA_MULTICAST]) {
324  addr->a_multicast = nl_addr_alloc_attr(tb[IFA_MULTICAST],
325  family);
326  if (!addr->a_multicast)
327  goto errout_nomem;
328 
329  addr->ce_mask |= ADDR_ATTR_MULTICAST;
330  }
331 
332  /* IPv6 only */
333  if (tb[IFA_ANYCAST]) {
334  addr->a_anycast = nl_addr_alloc_attr(tb[IFA_ANYCAST],
335  family);
336  if (!addr->a_anycast)
337  goto errout_nomem;
338 
339  addr->ce_mask |= ADDR_ATTR_ANYCAST;
340  }
341 
342  if ((link_cache = __nl_cache_mngt_require("route/link"))) {
343  struct rtnl_link *link;
344 
345  if ((link = rtnl_link_get(link_cache, addr->a_ifindex))) {
346  rtnl_addr_set_link(addr, link);
347 
348  /* rtnl_addr_set_link incs refcnt */
349  rtnl_link_put(link);
350  }
351  }
352 
353  err = pp->pp_cb((struct nl_object *) addr, pp);
354 errout:
355  rtnl_addr_put(addr);
356 
357  return err;
358 
359 errout_nomem:
360  err = -NLE_NOMEM;
361  goto errout;
362 }
363 
364 static int addr_request_update(struct nl_cache *cache, struct nl_sock *sk)
365 {
366  return nl_rtgen_request(sk, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP);
367 }
368 
369 static void addr_dump_line(struct nl_object *obj, struct nl_dump_params *p)
370 {
371  struct rtnl_addr *addr = (struct rtnl_addr *) obj;
372  struct nl_cache *link_cache;
373  char buf[128];
374 
375  link_cache = nl_cache_mngt_require_safe("route/link");
376 
377  if (addr->ce_mask & ADDR_ATTR_LOCAL)
378  nl_dump_line(p, "%s",
379  nl_addr2str(addr->a_local, buf, sizeof(buf)));
380  else
381  nl_dump_line(p, "none");
382 
383  if (addr->ce_mask & ADDR_ATTR_PEER)
384  nl_dump(p, " peer %s",
385  nl_addr2str(addr->a_peer, buf, sizeof(buf)));
386 
387  nl_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf)));
388 
389  if (link_cache)
390  nl_dump(p, "dev %s ",
391  rtnl_link_i2name(link_cache, addr->a_ifindex,
392  buf, sizeof(buf)));
393  else
394  nl_dump(p, "dev %d ", addr->a_ifindex);
395 
396  nl_dump(p, "scope %s",
397  rtnl_scope2str(addr->a_scope, buf, sizeof(buf)));
398 
399  rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf));
400  if (buf[0])
401  nl_dump(p, " <%s>", buf);
402 
403  nl_dump(p, "\n");
404 
405  if (link_cache)
406  nl_cache_put(link_cache);
407 }
408 
409 static void addr_dump_details(struct nl_object *obj, struct nl_dump_params *p)
410 {
411  struct rtnl_addr *addr = (struct rtnl_addr *) obj;
412  char buf[128];
413 
414  addr_dump_line(obj, p);
415 
416  if (addr->ce_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST |
417  ADDR_ATTR_MULTICAST)) {
418  nl_dump_line(p, " ");
419 
420  if (addr->ce_mask & ADDR_ATTR_LABEL)
421  nl_dump(p, " label %s", addr->a_label);
422 
423  if (addr->ce_mask & ADDR_ATTR_BROADCAST)
424  nl_dump(p, " broadcast %s",
425  nl_addr2str(addr->a_bcast, buf, sizeof(buf)));
426 
427  if (addr->ce_mask & ADDR_ATTR_MULTICAST)
428  nl_dump(p, " multicast %s",
429  nl_addr2str(addr->a_multicast, buf,
430  sizeof(buf)));
431 
432  if (addr->ce_mask & ADDR_ATTR_ANYCAST)
433  nl_dump(p, " anycast %s",
434  nl_addr2str(addr->a_anycast, buf,
435  sizeof(buf)));
436 
437  nl_dump(p, "\n");
438  }
439 
440  if (addr->ce_mask & ADDR_ATTR_CACHEINFO) {
441  struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo;
442 
443  nl_dump_line(p, " valid-lifetime %s",
444  ci->aci_valid == 0xFFFFFFFFU ? "forever" :
445  nl_msec2str(ci->aci_valid * 1000,
446  buf, sizeof(buf)));
447 
448  nl_dump(p, " preferred-lifetime %s\n",
449  ci->aci_prefered == 0xFFFFFFFFU ? "forever" :
450  nl_msec2str(ci->aci_prefered * 1000,
451  buf, sizeof(buf)));
452 
453  nl_dump_line(p, " created boot-time+%s ",
454  nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10,
455  buf, sizeof(buf)));
456 
457  nl_dump(p, "last-updated boot-time+%s\n",
458  nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10,
459  buf, sizeof(buf)));
460  }
461 }
462 
463 static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
464 {
465  addr_dump_details(obj, p);
466 }
467 
468 static uint32_t addr_id_attrs_get(struct nl_object *obj)
469 {
470  struct rtnl_addr *addr = (struct rtnl_addr *)obj;
471  uint32_t rv;
472 
473  switch (addr->a_family) {
474  case AF_INET:
475  rv = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
476  ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN);
477  if (addr->a_peer)
478  rv |= ADDR_ATTR_PEER;
479  return rv;
480  case AF_INET6:
481  return (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
482  ADDR_ATTR_LOCAL);
483  default:
484  return (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
485  ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN);
486  }
487 }
488 
489 static uint64_t addr_compare(struct nl_object *_a, struct nl_object *_b,
490  uint64_t attrs, int flags)
491 {
492  struct rtnl_addr *a = (struct rtnl_addr *) _a;
493  struct rtnl_addr *b = (struct rtnl_addr *) _b;
494  uint64_t diff = 0;
495 
496 #define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR)
497 
498  diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex);
499  diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family);
500  diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope);
501  diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label));
502  if (attrs & ADDR_ATTR_PEER) {
503  if ( (flags & ID_COMPARISON)
504  && a->a_family == AF_INET
505  && b->a_family == AF_INET
506  && a->a_peer
507  && b->a_peer
508  && a->a_prefixlen == b->a_prefixlen) {
509  /* when comparing two IPv4 addresses for id-equality, the network part
510  * of the PEER address shall be compared.
511  */
512  diff |= ADDR_DIFF(PEER, nl_addr_cmp_prefix(a->a_peer, b->a_peer));
513  } else
514  diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer));
515  }
516  diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local));
517  diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast,
518  b->a_multicast));
519  diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
520  diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast, b->a_anycast));
521  diff |= ADDR_DIFF(CACHEINFO, memcmp(&a->a_cacheinfo, &b->a_cacheinfo,
522  sizeof (a->a_cacheinfo)));
523 
524  if (flags & LOOSE_COMPARISON)
525  diff |= ADDR_DIFF(FLAGS,
526  (a->a_flags ^ b->a_flags) & b->a_flag_mask);
527  else
528  diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags);
529 
530 #undef ADDR_DIFF
531 
532  return diff;
533 }
534 
535 static const struct trans_tbl addr_attrs[] = {
536  __ADD(ADDR_ATTR_FAMILY, family),
537  __ADD(ADDR_ATTR_PREFIXLEN, prefixlen),
538  __ADD(ADDR_ATTR_FLAGS, flags),
539  __ADD(ADDR_ATTR_SCOPE, scope),
540  __ADD(ADDR_ATTR_IFINDEX, ifindex),
541  __ADD(ADDR_ATTR_LABEL, label),
542  __ADD(ADDR_ATTR_CACHEINFO, cacheinfo),
543  __ADD(ADDR_ATTR_PEER, peer),
544  __ADD(ADDR_ATTR_LOCAL, local),
545  __ADD(ADDR_ATTR_BROADCAST, broadcast),
546  __ADD(ADDR_ATTR_MULTICAST, multicast),
547 };
548 
549 static char *addr_attrs2str(int attrs, char *buf, size_t len)
550 {
551  return __flags2str(attrs, buf, len, addr_attrs,
552  ARRAY_SIZE(addr_attrs));
553 }
554 
555 /**
556  * @name Allocation/Freeing
557  * @{
558  */
559 
560 struct rtnl_addr *rtnl_addr_alloc(void)
561 {
562  return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops);
563 }
564 
565 void rtnl_addr_put(struct rtnl_addr *addr)
566 {
567  nl_object_put((struct nl_object *) addr);
568 }
569 
570 /** @} */
571 
572 /**
573  * @name Cache Management
574  * @{
575  */
576 
577 int rtnl_addr_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
578 {
579  return nl_cache_alloc_and_fill(&rtnl_addr_ops, sk, result);
580 }
581 
582 /**
583  * Search address in cache
584  * @arg cache Address cache
585  * @arg ifindex Interface index of address
586  * @arg addr Local address part
587  *
588  * Searches address cache previously allocated with rtnl_addr_alloc_cache()
589  * for an address with a matching local address.
590  *
591  * The reference counter is incremented before returning the address, therefore
592  * the reference must be given back with rtnl_addr_put() after usage.
593  *
594  * @return Address object or NULL if no match was found.
595  */
596 struct rtnl_addr *rtnl_addr_get(struct nl_cache *cache, int ifindex,
597  struct nl_addr *addr)
598 {
599  struct rtnl_addr *a;
600 
601  if (cache->c_ops != &rtnl_addr_ops)
602  return NULL;
603 
604  nl_list_for_each_entry(a, &cache->c_items, ce_list) {
605  if (ifindex && a->a_ifindex != ifindex)
606  continue;
607 
608  if (a->ce_mask & ADDR_ATTR_LOCAL &&
609  !nl_addr_cmp(a->a_local, addr)) {
610  nl_object_get((struct nl_object *) a);
611  return a;
612  }
613  }
614 
615  return NULL;
616 }
617 
618 /** @} */
619 
620 static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags,
621  struct nl_msg **result)
622 {
623  struct nl_msg *msg;
624  struct ifaddrmsg am = {
625  .ifa_family = tmpl->a_family,
626  .ifa_index = tmpl->a_ifindex,
627  .ifa_prefixlen = tmpl->a_prefixlen,
628  .ifa_flags = tmpl->a_flags,
629  };
630 
631  if (tmpl->ce_mask & ADDR_ATTR_SCOPE)
632  am.ifa_scope = tmpl->a_scope;
633  else {
634  /* compatibility hack */
635  if (tmpl->a_family == AF_INET &&
636  tmpl->ce_mask & ADDR_ATTR_LOCAL &&
637  *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127)
638  am.ifa_scope = RT_SCOPE_HOST;
639  else
640  am.ifa_scope = RT_SCOPE_UNIVERSE;
641  }
642 
643  msg = nlmsg_alloc_simple(cmd, flags);
644  if (!msg)
645  return -NLE_NOMEM;
646 
647  if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0)
648  goto nla_put_failure;
649 
650  if (tmpl->ce_mask & ADDR_ATTR_LOCAL)
651  NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local);
652 
653  if (tmpl->ce_mask & ADDR_ATTR_PEER)
654  NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer);
655  else if (tmpl->ce_mask & ADDR_ATTR_LOCAL)
656  NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local);
657 
658  if (tmpl->ce_mask & ADDR_ATTR_LABEL)
659  NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label);
660 
661  if (tmpl->ce_mask & ADDR_ATTR_BROADCAST)
662  NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast);
663 
664  if (tmpl->ce_mask & ADDR_ATTR_CACHEINFO) {
665  struct ifa_cacheinfo ca = {
666  .ifa_valid = tmpl->a_cacheinfo.aci_valid,
667  .ifa_prefered = tmpl->a_cacheinfo.aci_prefered,
668  };
669 
670  NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca);
671  }
672 
673  if (tmpl->a_flags & ~0xFF) {
674  /* only set the IFA_FLAGS attribute, if they actually contain additional
675  * flags that are not already set to am.ifa_flags.
676  *
677  * Older kernels refuse RTM_NEWADDR and RTM_NEWROUTE messages with EINVAL
678  * if they contain unknown netlink attributes. See net/core/rtnetlink.c, which
679  * was fixed by kernel commit 661d2967b3f1b34eeaa7e212e7b9bbe8ee072b59.
680  *
681  * With this workaround, libnl will function correctly with older kernels,
682  * unless there is a new libnl user that wants to set these flags. In this
683  * case it's up to the user to workaround this issue. */
684  NLA_PUT_U32(msg, IFA_FLAGS, tmpl->a_flags);
685  }
686 
687  *result = msg;
688  return 0;
689 
690 nla_put_failure:
691  nlmsg_free(msg);
692  return -NLE_MSGSIZE;
693 }
694 
695 /**
696  * @name Addition
697  * @{
698  */
699 
700 /**
701  * Build netlink request message to request addition of new address
702  * @arg addr Address object representing the new address.
703  * @arg flags Additional netlink message flags.
704  * @arg result Pointer to store resulting message.
705  *
706  * Builds a new netlink message requesting the addition of a new
707  * address. The netlink message header isn't fully equipped with
708  * all relevant fields and must thus be sent out via nl_send_auto_complete()
709  * or supplemented as needed.
710  *
711  * Minimal required attributes:
712  * - interface index (rtnl_addr_set_ifindex())
713  * - local address (rtnl_addr_set_local())
714  *
715  * The scope will default to universe except for loopback addresses in
716  * which case a host scope is used if not specified otherwise.
717  *
718  * @note Free the memory after usage using nlmsg_free().
719  *
720  * @return 0 on success or a negative error code.
721  */
722 int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags,
723  struct nl_msg **result)
724 {
725  uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY |
726  ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL;
727 
728  if ((addr->ce_mask & required) != required)
729  return -NLE_MISSING_ATTR;
730 
731  return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags, result);
732 }
733 
734 /**
735  * Request addition of new address
736  * @arg sk Netlink socket.
737  * @arg addr Address object representing the new address.
738  * @arg flags Additional netlink message flags.
739  *
740  * Builds a netlink message by calling rtnl_addr_build_add_request(),
741  * sends the request to the kernel and waits for the next ACK to be
742  * received and thus blocks until the request has been fullfilled.
743  *
744  * @see rtnl_addr_build_add_request()
745  *
746  * @return 0 on sucess or a negative error if an error occured.
747  */
748 int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
749 {
750  struct nl_msg *msg;
751  int err;
752 
753  if ((err = rtnl_addr_build_add_request(addr, flags, &msg)) < 0)
754  return err;
755 
756  err = nl_send_auto_complete(sk, msg);
757  nlmsg_free(msg);
758  if (err < 0)
759  return err;
760 
761  return wait_for_ack(sk);
762 }
763 
764 /** @} */
765 
766 /**
767  * @name Deletion
768  * @{
769  */
770 
771 /**
772  * Build a netlink request message to request deletion of an address
773  * @arg addr Address object to be deleteted.
774  * @arg flags Additional netlink message flags.
775  * @arg result Pointer to store resulting message.
776  *
777  * Builds a new netlink message requesting a deletion of an address.
778  * The netlink message header isn't fully equipped with all relevant
779  * fields and must thus be sent out via nl_send_auto_complete()
780  * or supplemented as needed.
781  *
782  * Minimal required attributes:
783  * - interface index (rtnl_addr_set_ifindex())
784  * - address family (rtnl_addr_set_family())
785  *
786  * Optional attributes:
787  * - local address (rtnl_addr_set_local())
788  * - label (rtnl_addr_set_label(), IPv4/DECnet only)
789  * - peer address (rtnl_addr_set_peer(), IPv4 only)
790  *
791  * @note Free the memory after usage using nlmsg_free().
792  *
793  * @return 0 on success or a negative error code.
794  */
795 int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags,
796  struct nl_msg **result)
797 {
798  uint32_t required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY;
799 
800  if ((addr->ce_mask & required) != required)
801  return -NLE_MISSING_ATTR;
802 
803  return build_addr_msg(addr, RTM_DELADDR, flags, result);
804 }
805 
806 /**
807  * Request deletion of an address
808  * @arg sk Netlink socket.
809  * @arg addr Address object to be deleted.
810  * @arg flags Additional netlink message flags.
811  *
812  * Builds a netlink message by calling rtnl_addr_build_delete_request(),
813  * sends the request to the kernel and waits for the next ACK to be
814  * received and thus blocks until the request has been fullfilled.
815  *
816  * @see rtnl_addr_build_delete_request();
817  *
818  * @return 0 on sucess or a negative error if an error occured.
819  */
820 int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
821 {
822  struct nl_msg *msg;
823  int err;
824 
825  if ((err = rtnl_addr_build_delete_request(addr, flags, &msg)) < 0)
826  return err;
827 
828  err = nl_send_auto_complete(sk, msg);
829  nlmsg_free(msg);
830  if (err < 0)
831  return err;
832 
833  return wait_for_ack(sk);
834 }
835 
836 /** @} */
837 
838 /**
839  * @name Attributes
840  * @{
841  */
842 
843 int rtnl_addr_set_label(struct rtnl_addr *addr, const char *label)
844 {
845  if (strlen(label) > sizeof(addr->a_label) - 1)
846  return -NLE_RANGE;
847 
848  strcpy(addr->a_label, label);
849  addr->ce_mask |= ADDR_ATTR_LABEL;
850 
851  return 0;
852 }
853 
854 char *rtnl_addr_get_label(struct rtnl_addr *addr)
855 {
856  if (addr->ce_mask & ADDR_ATTR_LABEL)
857  return addr->a_label;
858  else
859  return NULL;
860 }
861 
862 void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex)
863 {
864  addr->a_ifindex = ifindex;
865  addr->ce_mask |= ADDR_ATTR_IFINDEX;
866 }
867 
868 int rtnl_addr_get_ifindex(struct rtnl_addr *addr)
869 {
870  return addr->a_ifindex;
871 }
872 
873 void rtnl_addr_set_link(struct rtnl_addr *addr, struct rtnl_link *link)
874 {
875  rtnl_link_put(addr->a_link);
876 
877  if (!link)
878  return;
879 
880  nl_object_get(OBJ_CAST(link));
881  addr->a_link = link;
882  addr->a_ifindex = link->l_index;
883  addr->ce_mask |= ADDR_ATTR_IFINDEX;
884 }
885 
886 struct rtnl_link *rtnl_addr_get_link(struct rtnl_addr *addr)
887 {
888  if (addr->a_link) {
889  nl_object_get(OBJ_CAST(addr->a_link));
890  return addr->a_link;
891  }
892 
893  return NULL;
894 }
895 
896 void rtnl_addr_set_family(struct rtnl_addr *addr, int family)
897 {
898  addr->a_family = family;
899  addr->ce_mask |= ADDR_ATTR_FAMILY;
900 }
901 
902 int rtnl_addr_get_family(struct rtnl_addr *addr)
903 {
904  return addr->a_family;
905 }
906 
907 /**
908  * Set the prefix length / netmask
909  * @arg addr Address
910  * @arg prefixlen Length of prefix (netmask)
911  *
912  * Modifies the length of the prefix. If the address object contains a peer
913  * address the prefix length will apply to it, otherwise the prefix length
914  * will apply to the local address of the address.
915  *
916  * If the address object contains a peer or local address the corresponding
917  * `struct nl_addr` will be updated with the new prefix length.
918  *
919  * @note Specifying a length of 0 will remove the prefix length alltogether.
920  *
921  * @see rtnl_addr_get_prefixlen()
922  */
923 void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefixlen)
924 {
925  addr->a_prefixlen = prefixlen;
926 
927  if (prefixlen)
928  addr->ce_mask |= ADDR_ATTR_PREFIXLEN;
929  else
930  addr->ce_mask &= ~ADDR_ATTR_PREFIXLEN;
931 
932  /*
933  * The prefix length always applies to the peer address if
934  * a peer address is present.
935  */
936  if (addr->a_peer)
937  nl_addr_set_prefixlen(addr->a_peer, prefixlen);
938  else if (addr->a_local)
939  nl_addr_set_prefixlen(addr->a_local, prefixlen);
940 }
941 
942 int rtnl_addr_get_prefixlen(struct rtnl_addr *addr)
943 {
944  return addr->a_prefixlen;
945 }
946 
947 void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope)
948 {
949  addr->a_scope = scope;
950  addr->ce_mask |= ADDR_ATTR_SCOPE;
951 }
952 
953 int rtnl_addr_get_scope(struct rtnl_addr *addr)
954 {
955  return addr->a_scope;
956 }
957 
958 void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags)
959 {
960  addr->a_flag_mask |= flags;
961  addr->a_flags |= flags;
962  addr->ce_mask |= ADDR_ATTR_FLAGS;
963 }
964 
965 void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags)
966 {
967  addr->a_flag_mask |= flags;
968  addr->a_flags &= ~flags;
969  addr->ce_mask |= ADDR_ATTR_FLAGS;
970 }
971 
972 unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr)
973 {
974  return addr->a_flags;
975 }
976 
977 static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos,
978  struct nl_addr *new, int flag)
979 {
980  if (new) {
981  if (addr->ce_mask & ADDR_ATTR_FAMILY) {
982  if (new->a_family != addr->a_family)
983  return -NLE_AF_MISMATCH;
984  } else
985  addr->a_family = new->a_family;
986 
987  if (*pos)
988  nl_addr_put(*pos);
989 
990  *pos = nl_addr_get(new);
991  addr->ce_mask |= (flag | ADDR_ATTR_FAMILY);
992  } else {
993  if (*pos)
994  nl_addr_put(*pos);
995 
996  *pos = NULL;
997  addr->ce_mask &= ~flag;
998  }
999 
1000  return 0;
1001 }
1002 
1003 int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local)
1004 {
1005  int err;
1006 
1007  /* Prohibit local address with prefix length if peer address is present */
1008  if ((addr->ce_mask & ADDR_ATTR_PEER) && local &&
1009  nl_addr_get_prefixlen(local))
1010  return -NLE_INVAL;
1011 
1012  err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL);
1013  if (err < 0)
1014  return err;
1015 
1016  /* Never overwrite the prefix length if a peer address is present */
1017  if (!(addr->ce_mask & ADDR_ATTR_PEER))
1018  rtnl_addr_set_prefixlen(addr, local ? nl_addr_get_prefixlen(local) : 0);
1019 
1020  return 0;
1021 }
1022 
1023 struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr)
1024 {
1025  return addr->a_local;
1026 }
1027 
1028 int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer)
1029 {
1030  int err;
1031 
1032  if (peer && peer->a_family != AF_INET)
1033  return -NLE_AF_NOSUPPORT;
1034 
1035  err = __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER);
1036  if (err < 0)
1037  return err;
1038 
1039  rtnl_addr_set_prefixlen(addr, peer ? nl_addr_get_prefixlen(peer) : 0);
1040 
1041  return 0;
1042 }
1043 
1044 struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr)
1045 {
1046  return addr->a_peer;
1047 }
1048 
1049 int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast)
1050 {
1051  if (bcast && bcast->a_family != AF_INET)
1052  return -NLE_AF_NOSUPPORT;
1053 
1054  return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST);
1055 }
1056 
1057 struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr)
1058 {
1059  return addr->a_bcast;
1060 }
1061 
1062 int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast)
1063 {
1064  if (multicast && multicast->a_family != AF_INET6)
1065  return -NLE_AF_NOSUPPORT;
1066 
1067  return __assign_addr(addr, &addr->a_multicast, multicast,
1068  ADDR_ATTR_MULTICAST);
1069 }
1070 
1071 struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr)
1072 {
1073  return addr->a_multicast;
1074 }
1075 
1076 int rtnl_addr_set_anycast(struct rtnl_addr *addr, struct nl_addr *anycast)
1077 {
1078  if (anycast && anycast->a_family != AF_INET6)
1079  return -NLE_AF_NOSUPPORT;
1080 
1081  return __assign_addr(addr, &addr->a_anycast, anycast,
1082  ADDR_ATTR_ANYCAST);
1083 }
1084 
1085 struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr)
1086 {
1087  return addr->a_anycast;
1088 }
1089 
1090 uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *addr)
1091 {
1092  if (addr->ce_mask & ADDR_ATTR_CACHEINFO)
1093  return addr->a_cacheinfo.aci_valid;
1094  else
1095  return 0xFFFFFFFFU;
1096 }
1097 
1098 void rtnl_addr_set_valid_lifetime(struct rtnl_addr *addr, uint32_t lifetime)
1099 {
1100  addr->a_cacheinfo.aci_valid = lifetime;
1101  addr->ce_mask |= ADDR_ATTR_CACHEINFO;
1102 }
1103 
1104 uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *addr)
1105 {
1106  if (addr->ce_mask & ADDR_ATTR_CACHEINFO)
1107  return addr->a_cacheinfo.aci_prefered;
1108  else
1109  return 0xFFFFFFFFU;
1110 }
1111 
1112 void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *addr, uint32_t lifetime)
1113 {
1114  addr->a_cacheinfo.aci_prefered = lifetime;
1115  addr->ce_mask |= ADDR_ATTR_CACHEINFO;
1116 }
1117 
1118 uint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr)
1119 {
1120  return addr->a_cacheinfo.aci_cstamp;
1121 }
1122 
1123 uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *addr)
1124 {
1125  return addr->a_cacheinfo.aci_tstamp;
1126 }
1127 
1128 /** @} */
1129 
1130 /**
1131  * @name Flags Translations
1132  * @{
1133  */
1134 
1135 static const struct trans_tbl addr_flags[] = {
1136  __ADD(IFA_F_SECONDARY, secondary),
1137  __ADD(IFA_F_NODAD, nodad),
1138  __ADD(IFA_F_OPTIMISTIC, optimistic),
1139  __ADD(IFA_F_HOMEADDRESS, homeaddress),
1140  __ADD(IFA_F_DEPRECATED, deprecated),
1141  __ADD(IFA_F_TENTATIVE, tentative),
1142  __ADD(IFA_F_PERMANENT, permanent),
1143  __ADD(IFA_F_MANAGETEMPADDR, mngtmpaddr),
1144  __ADD(IFA_F_NOPREFIXROUTE, noprefixroute),
1145 };
1146 
1147 char *rtnl_addr_flags2str(int flags, char *buf, size_t size)
1148 {
1149  return __flags2str(flags, buf, size, addr_flags,
1150  ARRAY_SIZE(addr_flags));
1151 }
1152 
1153 int rtnl_addr_str2flags(const char *name)
1154 {
1155  return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags));
1156 }
1157 
1158 /** @} */
1159 
1160 static struct nl_object_ops addr_obj_ops = {
1161  .oo_name = "route/addr",
1162  .oo_size = sizeof(struct rtnl_addr),
1163  .oo_constructor = addr_constructor,
1164  .oo_free_data = addr_free_data,
1165  .oo_clone = addr_clone,
1166  .oo_dump = {
1167  [NL_DUMP_LINE] = addr_dump_line,
1168  [NL_DUMP_DETAILS] = addr_dump_details,
1169  [NL_DUMP_STATS] = addr_dump_stats,
1170  },
1171  .oo_compare = addr_compare,
1172  .oo_attrs2str = addr_attrs2str,
1173  .oo_id_attrs_get = addr_id_attrs_get,
1174  .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
1175  ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN),
1176 };
1177 
1178 static struct nl_af_group addr_groups[] = {
1179  { AF_INET, RTNLGRP_IPV4_IFADDR },
1180  { AF_INET6, RTNLGRP_IPV6_IFADDR },
1181  { END_OF_GROUP_LIST },
1182 };
1183 
1184 static struct nl_cache_ops rtnl_addr_ops = {
1185  .co_name = "route/addr",
1186  .co_hdrsize = sizeof(struct ifaddrmsg),
1187  .co_msgtypes = {
1188  { RTM_NEWADDR, NL_ACT_NEW, "new" },
1189  { RTM_DELADDR, NL_ACT_DEL, "del" },
1190  { RTM_GETADDR, NL_ACT_GET, "get" },
1191  END_OF_MSGTYPES_LIST,
1192  },
1193  .co_protocol = NETLINK_ROUTE,
1194  .co_groups = addr_groups,
1195  .co_request_update = addr_request_update,
1196  .co_msg_parser = addr_msg_parser,
1197  .co_obj_ops = &addr_obj_ops,
1198 };
1199 
1200 static void __init addr_init(void)
1201 {
1202  nl_cache_mngt_register(&rtnl_addr_ops);
1203 }
1204 
1205 static void __exit addr_exit(void)
1206 {
1207  nl_cache_mngt_unregister(&rtnl_addr_ops);
1208 }
1209 
1210 /** @} */
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1248
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:494
Dump object briefly on one line.
Definition: types.h:22
void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
Set the prefix length of an abstract address.
Definition: addr.c:966
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:565
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
Definition: msg.c:215
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition: addr.c:586
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition: msg.c:107
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:289
unsigned int nl_addr_get_prefixlen(const struct nl_addr *addr)
Return prefix length of abstract address object.
Definition: addr.c:977
void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefixlen)
Set the prefix length / netmask.
Definition: addr.c:923
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition: object.c:55
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:288
Attribute validation policy.
Definition: attr.h:69
int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags, struct nl_msg **result)
Build netlink request message to request addition of new address.
Definition: addr.c:722
struct nl_cache * nl_cache_mngt_require_safe(const char *name)
Return cache previously provided via nl_cache_mngt_provide()
Definition: cache_mngt.c:431
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:205
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
Definition: addr.c:218
char * nl_msec2str(uint64_t msec, char *buf, size_t len)
Convert milliseconds to a character string.
Definition: utils.c:595
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:707
struct rtnl_addr * rtnl_addr_get(struct nl_cache *cache, int ifindex, struct nl_addr *addr)
Search address in cache.
Definition: addr.c:596
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition: addr.c:524
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition: addr.c:263
NUL terminated character string.
Definition: attr.h:45
Dump all attributes but no statistics.
Definition: types.h:23
int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
Request deletion of an address.
Definition: addr.c:820
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:253
int nl_rtgen_request(struct nl_sock *sk, int type, int family, int flags)
Send routing netlink request message.
Definition: rtnl.c:42
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:165
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:121
int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags, struct nl_msg **result)
Build a netlink request message to request deletion of an address.
Definition: addr.c:795
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:236
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition: msg.c:449
int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
Request addition of new address.
Definition: addr.c:748
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:216
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
Definition: attr.h:263
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:540
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:71
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:348
Dumping parameters.
Definition: types.h:33
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:962
int nl_addr_cmp_prefix(const struct nl_addr *a, const struct nl_addr *b)
Compare the prefix of two abstract addresses.
Definition: addr.c:625
Dump all attributes including statistics.
Definition: types.h:24
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition: addr.c:942
int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, struct nl_cache **result)
Allocate new cache and fill it.
Definition: cache.c:234
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
Definition: attr.c:379
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:1000