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