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
125 static struct nl_cache_ops rtnl_addr_ops;
126 static struct nl_object_ops addr_obj_ops;
127 /** @endcond */
128
addr_constructor(struct nl_object * obj)129 static 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
addr_free_data(struct nl_object * obj)136 static 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
addr_clone(struct nl_object * _dst,struct nl_object * _src)151 static 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
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_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
rtnl_addr_flags2str(int flags,char * buf,size_t size)1148 char *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
rtnl_addr_str2flags(const char * name)1154 int rtnl_addr_str2flags(const char *name)
1155 {
1156 return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags));
1157 }
1158
1159 /** @} */
1160
1161 static 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
1179 static 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
1185 static 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
addr_init(void)1201 static void __init addr_init(void)
1202 {
1203 nl_cache_mngt_register(&rtnl_addr_ops);
1204 }
1205
addr_exit(void)1206 static void __exit addr_exit(void)
1207 {
1208 nl_cache_mngt_unregister(&rtnl_addr_ops);
1209 }
1210
1211 /** @} */
1212