libnl 3.7.0
addr.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
4 * Copyright (c) 2003-2006 Baruch Even <baruch@ev-en.org>
5 * Copyright (c) 2003-2006 Mediatrix Telecom, inc. <ericb@mediatrix.com>
6 */
7
8/**
9 * @ingroup rtnl
10 * @defgroup rtaddr Addresses
11 * @brief
12 *
13 * @note The maximum size of an address label is IFNAMSIZ.
14 *
15 * @note The address may not contain a prefix length if the peer address
16 * has been specified already.
17 *
18 * @par 1) Address Addition
19 * @code
20 * // Allocate an empty address object to be filled out with the attributes
21 * // of the new address.
22 * struct rtnl_addr *addr = rtnl_addr_alloc();
23 *
24 * // Fill out the mandatory attributes of the new address. Setting the
25 * // local address will automatically set the address family and the
26 * // prefix length to the correct values.
27 * rtnl_addr_set_ifindex(addr, ifindex);
28 * rtnl_addr_set_local(addr, local_addr);
29 *
30 * // The label of the address can be specified, currently only supported
31 * // by IPv4 and DECnet.
32 * rtnl_addr_set_label(addr, "mylabel");
33 *
34 * // The peer address can be specified if necessary, in either case a peer
35 * // address will be sent to the kernel in order to fullfil the interface
36 * // requirements. If none is set, it will equal the local address.
37 * // Note: Real peer addresses are only supported by IPv4 for now.
38 * rtnl_addr_set_peer(addr, peer_addr);
39 *
40 * // In case you want to have the address have a scope other than global
41 * // it may be overwritten using rtnl_addr_set_scope(). The scope currently
42 * // cannot be set for IPv6 addresses.
43 * rtnl_addr_set_scope(addr, rtnl_str2scope("site"));
44 *
45 * // Broadcast address may be specified using the relevant
46 * // functions, the address family will be verified if one of the other
47 * // addresses has been set already. Currently only works for IPv4.
48 * rtnl_addr_set_broadcast(addr, broadcast_addr);
49 *
50 * // Build the netlink message and send it to the kernel, the operation will
51 * // block until the operation has been completed. Alternatively the required
52 * // netlink message can be built using rtnl_addr_build_add_request() to be
53 * // sent out using nl_send_auto_complete().
54 * rtnl_addr_add(sk, addr, 0);
55 *
56 * // Free the memory
57 * rtnl_addr_put(addr);
58 * @endcode
59 *
60 * @par 2) Address Deletion
61 * @code
62 * // Allocate an empty address object to be filled out with the attributes
63 * // matching the address to be deleted. Alternatively a fully equipped
64 * // address object out of a cache can be used instead.
65 * struct rtnl_addr *addr = rtnl_addr_alloc();
66 *
67 * // The only mandatory parameter besides the address family is the interface
68 * // index the address is on, i.e. leaving out all other parameters will
69 * // result in all addresses of the specified address family interface tuple
70 * // to be deleted.
71 * rtnl_addr_set_ifindex(addr, ifindex);
72 *
73 * // Specyfing the address family manually is only required if neither the
74 * // local nor peer address have been specified.
75 * rtnl_addr_set_family(addr, AF_INET);
76 *
77 * // Specyfing the local address is optional but the best choice to delete
78 * // specific addresses.
79 * rtnl_addr_set_local(addr, local_addr);
80 *
81 * // The label of the address can be specified, currently only supported
82 * // by IPv4 and DECnet.
83 * rtnl_addr_set_label(addr, "mylabel");
84 *
85 * // The peer address can be specified if necessary, in either case a peer
86 * // address will be sent to the kernel in order to fullfil the interface
87 * // requirements. If none is set, it will equal the local address.
88 * // Note: Real peer addresses are only supported by IPv4 for now.
89 * rtnl_addr_set_peer(addr, peer_addr);
90 *
91 * // Build the netlink message and send it to the kernel, the operation will
92 * // block until the operation has been completed. Alternatively the required
93 * // netlink message can be built using rtnl_addr_build_delete_request()
94 * // to be sent out using nl_send_auto_complete().
95 * rtnl_addr_delete(sk, addr, 0);
96 *
97 * // Free the memory
98 * rtnl_addr_put(addr);
99 * @endcode
100 * @{
101 */
102
103#include <netlink-private/netlink.h>
104#include <netlink/netlink.h>
105#include <netlink/route/rtnl.h>
106#include <netlink/route/addr.h>
107#include <netlink/route/route.h>
108#include <netlink/route/link.h>
109#include <netlink/utils.h>
110
111/** @cond SKIP */
112#define ADDR_ATTR_FAMILY 0x0001
113#define ADDR_ATTR_PREFIXLEN 0x0002
114#define ADDR_ATTR_FLAGS 0x0004
115#define ADDR_ATTR_SCOPE 0x0008
116#define ADDR_ATTR_IFINDEX 0x0010
117#define ADDR_ATTR_LABEL 0x0020
118#define ADDR_ATTR_CACHEINFO 0x0040
119#define ADDR_ATTR_PEER 0x0080
120#define ADDR_ATTR_LOCAL 0x0100
121#define ADDR_ATTR_BROADCAST 0x0200
122#define ADDR_ATTR_MULTICAST 0x0400
123#define ADDR_ATTR_ANYCAST 0x0800
124
125static struct nl_cache_ops rtnl_addr_ops;
126static struct nl_object_ops addr_obj_ops;
127/** @endcond */
128
129static void addr_constructor(struct nl_object *obj)
130{
131 struct rtnl_addr *addr = nl_object_priv(obj);
132
133 addr->a_scope = RT_SCOPE_NOWHERE;
134}
135
136static void addr_free_data(struct nl_object *obj)
137{
138 struct rtnl_addr *addr = nl_object_priv(obj);
139
140 if (!addr)
141 return;
142
143 nl_addr_put(addr->a_peer);
144 nl_addr_put(addr->a_local);
145 nl_addr_put(addr->a_bcast);
146 nl_addr_put(addr->a_multicast);
147 nl_addr_put(addr->a_anycast);
148 rtnl_link_put(addr->a_link);
149}
150
151static int addr_clone(struct nl_object *_dst, struct nl_object *_src)
152{
153 struct rtnl_addr *dst = nl_object_priv(_dst);
154 struct rtnl_addr *src = nl_object_priv(_src);
155
156 dst->a_peer = NULL;
157 dst->a_local = NULL;
158 dst->a_bcast = NULL;
159 dst->a_anycast = NULL;
160 dst->a_multicast = NULL;
161 dst->a_link = NULL;
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
191static 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
197static 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);
354errout:
355 rtnl_addr_put(addr);
356
357 return err;
358
359errout_nomem:
360 err = -NLE_NOMEM;
361 goto errout;
362}
363
364static 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
369static 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
409static 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
463static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
464{
465 addr_dump_details(obj, p);
466}
467
468static 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
489static 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
535static 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
549static 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
560struct rtnl_addr *rtnl_addr_alloc(void)
561{
562 return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops);
563}
564
565void 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
577int 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 */
596struct 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
620static 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
690nla_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 */
722int 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 success or a negative error if an error occured.
747 */
748int 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 */
795int 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 success or a negative error if an error occured.
819 */
820int 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
843int 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
854char *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
862void 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
868int rtnl_addr_get_ifindex(struct rtnl_addr *addr)
869{
870 return addr->a_ifindex;
871}
872
873void 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
886struct 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
896void 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
902int 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 */
923void 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
942int rtnl_addr_get_prefixlen(struct rtnl_addr *addr)
943{
944 return addr->a_prefixlen;
945}
946
947void 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
953int rtnl_addr_get_scope(struct rtnl_addr *addr)
954{
955 return addr->a_scope;
956}
957
958void 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
965void 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
972unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr)
973{
974 return addr->a_flags;
975}
976
977static 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
1003int 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
1023struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr)
1024{
1025 return addr->a_local;
1026}
1027
1028int 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
1044struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr)
1045{
1046 return addr->a_peer;
1047}
1048
1049int 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
1057struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr)
1058{
1059 return addr->a_bcast;
1060}
1061
1062int 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
1071struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr)
1072{
1073 return addr->a_multicast;
1074}
1075
1076int 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
1085struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr)
1086{
1087 return addr->a_anycast;
1088}
1089
1090uint32_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
1098void 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
1104uint32_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
1112void 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
1118uint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr)
1119{
1120 return addr->a_cacheinfo.aci_cstamp;
1121}
1122
1123uint32_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
1135static 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_DADFAILED, dadfailed),
1140 __ADD(IFA_F_HOMEADDRESS, homeaddress),
1141 __ADD(IFA_F_DEPRECATED, deprecated),
1142 __ADD(IFA_F_TENTATIVE, tentative),
1143 __ADD(IFA_F_PERMANENT, permanent),
1144 __ADD(IFA_F_MANAGETEMPADDR, mngtmpaddr),
1145 __ADD(IFA_F_NOPREFIXROUTE, noprefixroute),
1146};
1147
1148char *rtnl_addr_flags2str(int flags, char *buf, size_t size)
1149{
1150 return __flags2str(flags, buf, size, addr_flags,
1151 ARRAY_SIZE(addr_flags));
1152}
1153
1154int rtnl_addr_str2flags(const char *name)
1155{
1156 return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags));
1157}
1158
1159/** @} */
1160
1161static struct nl_object_ops addr_obj_ops = {
1162 .oo_name = "route/addr",
1163 .oo_size = sizeof(struct rtnl_addr),
1164 .oo_constructor = addr_constructor,
1165 .oo_free_data = addr_free_data,
1166 .oo_clone = addr_clone,
1167 .oo_dump = {
1168 [NL_DUMP_LINE] = addr_dump_line,
1169 [NL_DUMP_DETAILS] = addr_dump_details,
1170 [NL_DUMP_STATS] = addr_dump_stats,
1171 },
1172 .oo_compare = addr_compare,
1173 .oo_attrs2str = addr_attrs2str,
1174 .oo_id_attrs_get = addr_id_attrs_get,
1175 .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX |
1176 ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN),
1177};
1178
1179static struct nl_af_group addr_groups[] = {
1180 { AF_INET, RTNLGRP_IPV4_IFADDR },
1181 { AF_INET6, RTNLGRP_IPV6_IFADDR },
1182 { END_OF_GROUP_LIST },
1183};
1184
1185static struct nl_cache_ops rtnl_addr_ops = {
1186 .co_name = "route/addr",
1187 .co_hdrsize = sizeof(struct ifaddrmsg),
1188 .co_msgtypes = {
1189 { RTM_NEWADDR, NL_ACT_NEW, "new" },
1190 { RTM_DELADDR, NL_ACT_DEL, "del" },
1191 { RTM_GETADDR, NL_ACT_GET, "get" },
1192 END_OF_MSGTYPES_LIST,
1193 },
1194 .co_protocol = NETLINK_ROUTE,
1195 .co_groups = addr_groups,
1196 .co_request_update = addr_request_update,
1197 .co_msg_parser = addr_msg_parser,
1198 .co_obj_ops = &addr_obj_ops,
1199};
1200
1201static void __init addr_init(void)
1202{
1203 nl_cache_mngt_register(&rtnl_addr_ops);
1204}
1205
1206static void __exit addr_exit(void)
1207{
1208 nl_cache_mngt_unregister(&rtnl_addr_ops);
1209}
1210
1211/** @} */
void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
Set the prefix length of an abstract address.
Definition: addr.c:964
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition: addr.c:522
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:211
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition: addr.c:256
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition: addr.c:940
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition: addr.c:584
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:492
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:623
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:998
unsigned int nl_addr_get_prefixlen(const struct nl_addr *addr)
Return prefix length of abstract address object.
Definition: addr.c:975
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:538
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:702
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:283
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:114
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:159
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:230
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
Definition: attr.c:371
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
Definition: attr.h:257
@ NLA_STRING
NUL terminated character string.
Definition: attr.h:39
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:281
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:246
struct nl_cache * nl_cache_mngt_require_safe(const char *name)
Return cache previously provided via nl_cache_mngt_provide()
Definition: cache_mngt.c:424
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:228
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:341
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition: msg.c:100
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:558
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:208
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:442
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:214
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:203
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:48
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
int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
Request deletion of an address.
Definition: addr.c:820
struct rtnl_addr * rtnl_addr_get(struct nl_cache *cache, int ifindex, struct nl_addr *addr)
Search address in cache.
Definition: addr.c:596
int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
Request addition of new address.
Definition: addr.c:748
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
void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefixlen)
Set the prefix length / netmask.
Definition: addr.c:923
int nl_rtgen_request(struct nl_sock *sk, int type, int family, int flags)
Send routing netlink request message.
Definition: rtnl.c:35
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1241
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
char * nl_msec2str(uint64_t msec, char *buf, size_t len)
Convert milliseconds to a character string.
Definition: utils.c:588
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition: types.h:18
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65