• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
addr_constructor(struct nl_object * obj)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 
addr_free_data(struct nl_object * obj)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 
addr_clone(struct nl_object * _dst,struct nl_object * _src)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 
addr_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)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 
addr_request_update(struct nl_cache * cache,struct nl_sock * sk)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 
addr_dump_line(struct nl_object * obj,struct nl_dump_params * p)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 
addr_dump_details(struct nl_object * obj,struct nl_dump_params * p)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 
addr_dump_stats(struct nl_object * obj,struct nl_dump_params * p)463 static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
464 {
465 	addr_dump_details(obj, p);
466 }
467 
addr_id_attrs_get(struct nl_object * obj)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 
addr_compare(struct nl_object * _a,struct nl_object * _b,uint64_t attrs,int flags)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 
addr_attrs2str(int attrs,char * buf,size_t len)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 
rtnl_addr_alloc(void)560 struct rtnl_addr *rtnl_addr_alloc(void)
561 {
562 	return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops);
563 }
564 
rtnl_addr_put(struct rtnl_addr * addr)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 
rtnl_addr_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)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  */
rtnl_addr_get(struct nl_cache * cache,int ifindex,struct nl_addr * addr)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 
build_addr_msg(struct rtnl_addr * tmpl,int cmd,int flags,struct nl_msg ** result)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  */
rtnl_addr_build_add_request(struct rtnl_addr * addr,int flags,struct nl_msg ** result)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  */
rtnl_addr_add(struct nl_sock * sk,struct rtnl_addr * addr,int flags)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  */
rtnl_addr_build_delete_request(struct rtnl_addr * addr,int flags,struct nl_msg ** result)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  */
rtnl_addr_delete(struct nl_sock * sk,struct rtnl_addr * addr,int flags)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 
rtnl_addr_set_label(struct rtnl_addr * addr,const char * label)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 
rtnl_addr_get_label(struct rtnl_addr * addr)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 
rtnl_addr_set_ifindex(struct rtnl_addr * addr,int ifindex)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 
rtnl_addr_get_ifindex(struct rtnl_addr * addr)868 int rtnl_addr_get_ifindex(struct rtnl_addr *addr)
869 {
870 	return addr->a_ifindex;
871 }
872 
rtnl_addr_set_link(struct rtnl_addr * addr,struct rtnl_link * link)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 
rtnl_addr_get_link(struct rtnl_addr * addr)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 
rtnl_addr_set_family(struct rtnl_addr * addr,int family)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 
rtnl_addr_get_family(struct rtnl_addr * addr)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  */
rtnl_addr_set_prefixlen(struct rtnl_addr * addr,int prefixlen)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 
rtnl_addr_get_prefixlen(struct rtnl_addr * addr)942 int rtnl_addr_get_prefixlen(struct rtnl_addr *addr)
943 {
944 	return addr->a_prefixlen;
945 }
946 
rtnl_addr_set_scope(struct rtnl_addr * addr,int scope)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 
rtnl_addr_get_scope(struct rtnl_addr * addr)953 int rtnl_addr_get_scope(struct rtnl_addr *addr)
954 {
955 	return addr->a_scope;
956 }
957 
rtnl_addr_set_flags(struct rtnl_addr * addr,unsigned int flags)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 
rtnl_addr_unset_flags(struct rtnl_addr * addr,unsigned int flags)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 
rtnl_addr_get_flags(struct rtnl_addr * addr)972 unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr)
973 {
974 	return addr->a_flags;
975 }
976 
__assign_addr(struct rtnl_addr * addr,struct nl_addr ** pos,struct nl_addr * new,int flag)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 
rtnl_addr_set_local(struct rtnl_addr * addr,struct nl_addr * local)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 
rtnl_addr_get_local(struct rtnl_addr * addr)1023 struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr)
1024 {
1025 	return addr->a_local;
1026 }
1027 
rtnl_addr_set_peer(struct rtnl_addr * addr,struct nl_addr * peer)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 
rtnl_addr_get_peer(struct rtnl_addr * addr)1044 struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr)
1045 {
1046 	return addr->a_peer;
1047 }
1048 
rtnl_addr_set_broadcast(struct rtnl_addr * addr,struct nl_addr * bcast)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 
rtnl_addr_get_broadcast(struct rtnl_addr * addr)1057 struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr)
1058 {
1059 	return addr->a_bcast;
1060 }
1061 
rtnl_addr_set_multicast(struct rtnl_addr * addr,struct nl_addr * multicast)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 
rtnl_addr_get_multicast(struct rtnl_addr * addr)1071 struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr)
1072 {
1073 	return addr->a_multicast;
1074 }
1075 
rtnl_addr_set_anycast(struct rtnl_addr * addr,struct nl_addr * anycast)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 
rtnl_addr_get_anycast(struct rtnl_addr * addr)1085 struct nl_addr *rtnl_addr_get_anycast(struct rtnl_addr *addr)
1086 {
1087 	return addr->a_anycast;
1088 }
1089 
rtnl_addr_get_valid_lifetime(struct rtnl_addr * addr)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 
rtnl_addr_set_valid_lifetime(struct rtnl_addr * addr,uint32_t lifetime)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 
rtnl_addr_get_preferred_lifetime(struct rtnl_addr * addr)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 
rtnl_addr_set_preferred_lifetime(struct rtnl_addr * addr,uint32_t lifetime)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 
rtnl_addr_get_create_time(struct rtnl_addr * addr)1118 uint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr)
1119 {
1120 	return addr->a_cacheinfo.aci_cstamp;
1121 }
1122 
rtnl_addr_get_last_update_time(struct rtnl_addr * addr)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 
rtnl_addr_flags2str(int flags,char * buf,size_t size)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 
rtnl_addr_str2flags(const char * name)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 
addr_init(void)1200 static void __init addr_init(void)
1201 {
1202 	nl_cache_mngt_register(&rtnl_addr_ops);
1203 }
1204 
addr_exit(void)1205 static void __exit addr_exit(void)
1206 {
1207 	nl_cache_mngt_unregister(&rtnl_addr_ops);
1208 }
1209 
1210 /** @} */
1211