]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-ndisc.c
network: ignore requested ipv6 addresses when ipv6 is disabled by sysctl
[thirdparty/systemd.git] / src / network / networkd-ndisc.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright © 2014 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <netinet/icmp6.h>
7 #include <arpa/inet.h>
8
9 #include "sd-ndisc.h"
10
11 #include "missing_network.h"
12 #include "networkd-ndisc.h"
13 #include "networkd-route.h"
14 #include "strv.h"
15
16 #define NDISC_DNSSL_MAX 64U
17 #define NDISC_RDNSS_MAX 64U
18 #define NDISC_PREFIX_LFT_MIN 7200U
19
20 static int ndisc_netlink_message_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
21 int r;
22
23 assert(link);
24 assert(link->ndisc_messages > 0);
25
26 link->ndisc_messages--;
27
28 r = sd_netlink_message_get_errno(m);
29 if (r < 0 && r != -EEXIST)
30 log_link_error_errno(link, r, "Could not set NDisc route or address: %m");
31
32 if (link->ndisc_messages == 0) {
33 link->ndisc_configured = true;
34 link_check_ready(link);
35 }
36
37 return 1;
38 }
39
40 static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
41 _cleanup_(route_freep) Route *route = NULL;
42 union in_addr_union gateway;
43 uint16_t lifetime;
44 unsigned preference;
45 uint32_t mtu;
46 usec_t time_now;
47 int r;
48 Address *address;
49 Iterator i;
50
51 assert(link);
52 assert(rt);
53
54 r = sd_ndisc_router_get_lifetime(rt, &lifetime);
55 if (r < 0)
56 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
57
58 if (lifetime == 0) /* not a default router */
59 return 0;
60
61 r = sd_ndisc_router_get_address(rt, &gateway.in6);
62 if (r < 0)
63 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
64
65 SET_FOREACH(address, link->addresses, i) {
66 if (address->family != AF_INET6)
67 continue;
68 if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
69 _cleanup_free_ char *buffer = NULL;
70
71 (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
72 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
73 strnull(buffer));
74 return 0;
75 }
76 }
77
78 SET_FOREACH(address, link->addresses_foreign, i) {
79 if (address->family != AF_INET6)
80 continue;
81 if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
82 _cleanup_free_ char *buffer = NULL;
83
84 (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
85 log_link_debug(link, "No NDisc route added, gateway %s matches local address",
86 strnull(buffer));
87 return 0;
88 }
89 }
90
91 r = sd_ndisc_router_get_preference(rt, &preference);
92 if (r < 0)
93 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
94
95 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
96 if (r < 0)
97 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
98
99 r = sd_ndisc_router_get_mtu(rt, &mtu);
100 if (r == -ENODATA)
101 mtu = 0;
102 else if (r < 0)
103 return log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m");
104
105 r = route_new(&route);
106 if (r < 0)
107 return log_link_error_errno(link, r, "Could not allocate route: %m");
108
109 route->family = AF_INET6;
110 route->table = link_get_ipv6_accept_ra_route_table(link);
111 route->priority = link->network->dhcp_route_metric;
112 route->protocol = RTPROT_RA;
113 route->pref = preference;
114 route->gw = gateway;
115 route->lifetime = time_now + lifetime * USEC_PER_SEC;
116 route->mtu = mtu;
117
118 r = route_configure(route, link, ndisc_netlink_message_handler);
119 if (r < 0) {
120 log_link_warning_errno(link, r, "Could not set default route: %m");
121 link_enter_failed(link);
122 return r;
123 }
124
125 link->ndisc_messages++;
126
127 return 0;
128 }
129
130 static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
131 _cleanup_(address_freep) Address *address = NULL;
132 Address *existing_address;
133 uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
134 usec_t time_now;
135 unsigned prefixlen;
136 int r;
137
138 assert(link);
139 assert(rt);
140
141 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
142 if (r < 0)
143 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
144
145 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
146 if (r < 0)
147 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
148
149 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid);
150 if (r < 0)
151 return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
152
153 r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
154 if (r < 0)
155 return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
156
157 /* The preferred lifetime is never greater than the valid lifetime */
158 if (lifetime_preferred > lifetime_valid)
159 return 0;
160
161 r = address_new(&address);
162 if (r < 0)
163 return log_link_error_errno(link, r, "Could not allocate address: %m");
164
165 address->family = AF_INET6;
166 r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6);
167 if (r < 0)
168 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
169
170 if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0)
171 memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8);
172 else {
173 /* see RFC4291 section 2.5.1 */
174 address->in_addr.in6.s6_addr[8] = link->mac.ether_addr_octet[0];
175 address->in_addr.in6.s6_addr[8] ^= 1 << 1;
176 address->in_addr.in6.s6_addr[9] = link->mac.ether_addr_octet[1];
177 address->in_addr.in6.s6_addr[10] = link->mac.ether_addr_octet[2];
178 address->in_addr.in6.s6_addr[11] = 0xff;
179 address->in_addr.in6.s6_addr[12] = 0xfe;
180 address->in_addr.in6.s6_addr[13] = link->mac.ether_addr_octet[3];
181 address->in_addr.in6.s6_addr[14] = link->mac.ether_addr_octet[4];
182 address->in_addr.in6.s6_addr[15] = link->mac.ether_addr_octet[5];
183 }
184 address->prefixlen = prefixlen;
185 address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
186 address->cinfo.ifa_prefered = lifetime_preferred;
187
188 /* see RFC4862 section 5.5.3.e */
189 r = address_get(link, address->family, &address->in_addr, address->prefixlen, &existing_address);
190 if (r > 0) {
191 lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
192 if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
193 address->cinfo.ifa_valid = lifetime_valid;
194 else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN)
195 address->cinfo.ifa_valid = lifetime_remaining;
196 else
197 address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
198 } else if (lifetime_valid > 0)
199 address->cinfo.ifa_valid = lifetime_valid;
200 else
201 return 0; /* see RFC4862 section 5.5.3.d */
202
203 if (address->cinfo.ifa_valid == 0)
204 return 0;
205
206 r = address_configure(address, link, ndisc_netlink_message_handler, true);
207 if (r < 0) {
208 log_link_warning_errno(link, r, "Could not set SLAAC address: %m");
209 link_enter_failed(link);
210 return r;
211 }
212 if (r > 0)
213 link->ndisc_messages++;
214
215 return 0;
216 }
217
218 static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
219 _cleanup_(route_freep) Route *route = NULL;
220 usec_t time_now;
221 uint32_t lifetime;
222 unsigned prefixlen;
223 int r;
224
225 assert(link);
226 assert(rt);
227
228 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
229 if (r < 0)
230 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
231
232 r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
233 if (r < 0)
234 return log_link_error_errno(link, r, "Failed to get prefix length: %m");
235
236 r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime);
237 if (r < 0)
238 return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
239
240 r = route_new(&route);
241 if (r < 0)
242 return log_link_error_errno(link, r, "Could not allocate route: %m");
243
244 route->family = AF_INET6;
245 route->table = link_get_ipv6_accept_ra_route_table(link);
246 route->priority = link->network->dhcp_route_metric;
247 route->protocol = RTPROT_RA;
248 route->flags = RTM_F_PREFIX;
249 route->dst_prefixlen = prefixlen;
250 route->lifetime = time_now + lifetime * USEC_PER_SEC;
251
252 r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
253 if (r < 0)
254 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
255
256 r = route_configure(route, link, ndisc_netlink_message_handler);
257 if (r < 0) {
258 log_link_warning_errno(link, r, "Could not set prefix route: %m");
259 link_enter_failed(link);
260 return r;
261 }
262
263 link->ndisc_messages++;
264
265 return 0;
266 }
267
268 static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
269 _cleanup_(route_freep) Route *route = NULL;
270 struct in6_addr gateway;
271 uint32_t lifetime;
272 unsigned preference, prefixlen;
273 usec_t time_now;
274 int r;
275
276 assert(link);
277
278 r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
279 if (r < 0)
280 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
281
282 if (lifetime == 0)
283 return 0;
284
285 r = sd_ndisc_router_get_address(rt, &gateway);
286 if (r < 0)
287 return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
288
289 r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
290 if (r < 0)
291 return log_link_warning_errno(link, r, "Failed to get route prefix length: %m");
292
293 r = sd_ndisc_router_route_get_preference(rt, &preference);
294 if (r < 0)
295 return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
296
297 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
298 if (r < 0)
299 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
300
301 r = route_new(&route);
302 if (r < 0)
303 return log_link_error_errno(link, r, "Could not allocate route: %m");
304
305 route->family = AF_INET6;
306 route->table = link_get_ipv6_accept_ra_route_table(link);
307 route->protocol = RTPROT_RA;
308 route->pref = preference;
309 route->gw.in6 = gateway;
310 route->dst_prefixlen = prefixlen;
311 route->lifetime = time_now + lifetime * USEC_PER_SEC;
312
313 r = sd_ndisc_router_route_get_address(rt, &route->dst.in6);
314 if (r < 0)
315 return log_link_error_errno(link, r, "Failed to get route address: %m");
316
317 r = route_configure(route, link, ndisc_netlink_message_handler);
318 if (r < 0) {
319 log_link_warning_errno(link, r, "Could not set additional route: %m");
320 link_enter_failed(link);
321 return r;
322 }
323
324 link->ndisc_messages++;
325
326 return 0;
327 }
328
329 static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) {
330 siphash24_compress(&x->address, sizeof(x->address), state);
331 }
332
333 static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) {
334 return memcmp(&a->address, &b->address, sizeof(a->address));
335 }
336
337 DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops, NDiscRDNSS, ndisc_rdnss_hash_func, ndisc_rdnss_compare_func);
338
339 static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
340 uint32_t lifetime;
341 const struct in6_addr *a;
342 usec_t time_now;
343 int i, n, r;
344
345 assert(link);
346 assert(rt);
347
348 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
349 if (r < 0)
350 return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
351
352 r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
353 if (r < 0)
354 return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
355
356 n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
357 if (n < 0)
358 return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m");
359
360 for (i = 0; i < n; i++) {
361 _cleanup_free_ NDiscRDNSS *x = NULL;
362 NDiscRDNSS d = {
363 .address = a[i],
364 }, *y;
365
366 if (lifetime == 0) {
367 (void) set_remove(link->ndisc_rdnss, &d);
368 link_dirty(link);
369 continue;
370 }
371
372 y = set_get(link->ndisc_rdnss, &d);
373 if (y) {
374 y->valid_until = time_now + lifetime * USEC_PER_SEC;
375 continue;
376 }
377
378 ndisc_vacuum(link);
379
380 if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) {
381 log_link_warning(link, "Too many RDNSS records per link, ignoring.");
382 continue;
383 }
384
385 r = set_ensure_allocated(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops);
386 if (r < 0)
387 return log_oom();
388
389 x = new(NDiscRDNSS, 1);
390 if (!x)
391 return log_oom();
392
393 *x = (NDiscRDNSS) {
394 .address = a[i],
395 .valid_until = time_now + lifetime * USEC_PER_SEC,
396 };
397
398 r = set_put(link->ndisc_rdnss, x);
399 if (r < 0)
400 return log_oom();
401
402 TAKE_PTR(x);
403
404 assert(r > 0);
405 link_dirty(link);
406 }
407
408 return 0;
409 }
410
411 static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) {
412 siphash24_compress(NDISC_DNSSL_DOMAIN(x), strlen(NDISC_DNSSL_DOMAIN(x)), state);
413 }
414
415 static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) {
416 return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
417 }
418
419 DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops, NDiscDNSSL, ndisc_dnssl_hash_func, ndisc_dnssl_compare_func);
420
421 static void ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
422 _cleanup_strv_free_ char **l = NULL;
423 uint32_t lifetime;
424 usec_t time_now;
425 char **i;
426 int r;
427
428 assert(link);
429 assert(rt);
430
431 r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
432 if (r < 0) {
433 log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
434 return;
435 }
436
437 r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
438 if (r < 0) {
439 log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
440 return;
441 }
442
443 r = sd_ndisc_router_dnssl_get_domains(rt, &l);
444 if (r < 0) {
445 log_link_warning_errno(link, r, "Failed to get RDNSS addresses: %m");
446 return;
447 }
448
449 STRV_FOREACH(i, l) {
450 _cleanup_free_ NDiscDNSSL *s;
451 NDiscDNSSL *x;
452
453 s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1);
454 if (!s) {
455 log_oom();
456 return;
457 }
458
459 strcpy(NDISC_DNSSL_DOMAIN(s), *i);
460
461 if (lifetime == 0) {
462 (void) set_remove(link->ndisc_dnssl, s);
463 link_dirty(link);
464 continue;
465 }
466
467 x = set_get(link->ndisc_dnssl, s);
468 if (x) {
469 x->valid_until = time_now + lifetime * USEC_PER_SEC;
470 continue;
471 }
472
473 ndisc_vacuum(link);
474
475 if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) {
476 log_link_warning(link, "Too many DNSSL records per link, ignoring.");
477 continue;
478 }
479
480 r = set_ensure_allocated(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops);
481 if (r < 0) {
482 log_oom();
483 return;
484 }
485
486 s->valid_until = time_now + lifetime * USEC_PER_SEC;
487
488 r = set_put(link->ndisc_dnssl, s);
489 if (r < 0) {
490 log_oom();
491 return;
492 }
493
494 s = NULL;
495 assert(r > 0);
496 link_dirty(link);
497 }
498 }
499
500 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
501 int r;
502
503 assert(link);
504 assert(rt);
505
506 r = sd_ndisc_router_option_rewind(rt);
507 for (;;) {
508 uint8_t type;
509
510 if (r < 0)
511 return log_link_warning_errno(link, r, "Failed to iterate through options: %m");
512 if (r == 0) /* EOF */
513 break;
514
515 r = sd_ndisc_router_option_get_type(rt, &type);
516 if (r < 0)
517 return log_link_warning_errno(link, r, "Failed to get RA option type: %m");
518
519 switch (type) {
520
521 case SD_NDISC_OPTION_PREFIX_INFORMATION: {
522 uint8_t flags;
523
524 r = sd_ndisc_router_prefix_get_flags(rt, &flags);
525 if (r < 0)
526 return log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m");
527
528 if (link->network->ipv6_accept_ra_use_onlink_prefix &&
529 FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK))
530 (void) ndisc_router_process_onlink_prefix(link, rt);
531
532 if (link->network->ipv6_accept_ra_use_autonomous_prefix &&
533 FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO))
534 (void) ndisc_router_process_autonomous_prefix(link, rt);
535
536 break;
537 }
538
539 case SD_NDISC_OPTION_ROUTE_INFORMATION:
540 (void) ndisc_router_process_route(link, rt);
541 break;
542
543 case SD_NDISC_OPTION_RDNSS:
544 if (link->network->ipv6_accept_ra_use_dns)
545 (void) ndisc_router_process_rdnss(link, rt);
546 break;
547
548 case SD_NDISC_OPTION_DNSSL:
549 if (link->network->ipv6_accept_ra_use_dns)
550 (void) ndisc_router_process_dnssl(link, rt);
551 break;
552 }
553
554 r = sd_ndisc_router_option_next(rt);
555 }
556
557 return 0;
558 }
559
560 static int ndisc_prefix_is_black_listed(Link *link, sd_ndisc_router *rt) {
561 int r;
562
563 assert(link);
564 assert(link->network);
565 assert(rt);
566
567 for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
568 union in_addr_union a;
569 uint8_t type;
570
571 if (r < 0)
572 return log_link_warning_errno(link, r, "Failed to iterate through options: %m");
573 if (r == 0) /* EOF */
574 return false;
575
576 r = sd_ndisc_router_option_get_type(rt, &type);
577 if (r < 0)
578 return log_link_warning_errno(link, r, "Failed to get RA option type: %m");
579
580 if (type != SD_NDISC_OPTION_PREFIX_INFORMATION)
581 continue;
582
583 r = sd_ndisc_router_prefix_get_address(rt, &a.in6);
584 if (r < 0)
585 return log_link_error_errno(link, r, "Failed to get prefix address: %m");
586
587 if (set_contains(link->network->ndisc_black_listed_prefix, &a.in6)) {
588 if (DEBUG_LOGGING) {
589 _cleanup_free_ char *b = NULL;
590
591 (void) in_addr_to_string(AF_INET6, &a, &b);
592 log_link_debug(link, "Prefix '%s' is black listed, ignoring", strna(b));
593 }
594
595 return true;
596 }
597 }
598 }
599
600 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
601 uint64_t flags;
602 int r;
603
604 assert(link);
605 assert(link->network);
606 assert(link->manager);
607 assert(rt);
608
609 r = sd_ndisc_router_get_flags(rt, &flags);
610 if (r < 0)
611 return log_link_warning_errno(link, r, "Failed to get RA flags: %m");
612
613 if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) {
614 /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
615 r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED));
616 if (r < 0 && r != -EBUSY)
617 log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
618 else {
619 log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
620 r = 0;
621 }
622 }
623
624 if (ndisc_prefix_is_black_listed(link, rt) == 0) {
625 (void) ndisc_router_process_default(link, rt);
626 (void) ndisc_router_process_options(link, rt);
627 }
628
629 return r;
630 }
631
632 static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
633 Link *link = userdata;
634
635 assert(link);
636
637 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
638 return;
639
640 switch (event) {
641
642 case SD_NDISC_EVENT_ROUTER:
643 (void) ndisc_router_handler(link, rt);
644 break;
645
646 case SD_NDISC_EVENT_TIMEOUT:
647 link->ndisc_configured = true;
648 link_check_ready(link);
649
650 break;
651 default:
652 log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
653 }
654 }
655
656 int ndisc_configure(Link *link) {
657 int r;
658
659 assert(link);
660
661 r = sd_ndisc_new(&link->ndisc);
662 if (r < 0)
663 return r;
664
665 r = sd_ndisc_attach_event(link->ndisc, NULL, 0);
666 if (r < 0)
667 return r;
668
669 r = sd_ndisc_set_mac(link->ndisc, &link->mac);
670 if (r < 0)
671 return r;
672
673 r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
674 if (r < 0)
675 return r;
676
677 r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
678 if (r < 0)
679 return r;
680
681 return 0;
682 }
683
684 void ndisc_vacuum(Link *link) {
685 NDiscRDNSS *r;
686 NDiscDNSSL *d;
687 Iterator i;
688 usec_t time_now;
689
690 assert(link);
691
692 /* Removes all RDNSS and DNSSL entries whose validity time has passed */
693
694 time_now = now(clock_boottime_or_monotonic());
695
696 SET_FOREACH(r, link->ndisc_rdnss, i)
697 if (r->valid_until < time_now) {
698 free(set_remove(link->ndisc_rdnss, r));
699 link_dirty(link);
700 }
701
702 SET_FOREACH(d, link->ndisc_dnssl, i)
703 if (d->valid_until < time_now) {
704 free(set_remove(link->ndisc_dnssl, d));
705 link_dirty(link);
706 }
707 }
708
709 void ndisc_flush(Link *link) {
710 assert(link);
711
712 /* Removes all RDNSS and DNSSL entries, without exception */
713
714 link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
715 link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
716 }
717
718 int config_parse_ndisc_black_listed_prefix(
719 const char *unit,
720 const char *filename,
721 unsigned line,
722 const char *section,
723 unsigned section_line,
724 const char *lvalue,
725 int ltype,
726 const char *rvalue,
727 void *data,
728 void *userdata) {
729
730 Network *network = data;
731 const char *p;
732 int r;
733
734 assert(filename);
735 assert(lvalue);
736 assert(rvalue);
737 assert(data);
738
739 if (isempty(rvalue)) {
740 network->ndisc_black_listed_prefix = set_free_free(network->ndisc_black_listed_prefix);
741 return 0;
742 }
743
744 for (p = rvalue;;) {
745 _cleanup_free_ char *n = NULL;
746 _cleanup_free_ struct in6_addr *a = NULL;
747 union in_addr_union ip;
748
749 r = extract_first_word(&p, &n, NULL, 0);
750 if (r < 0) {
751 log_syntax(unit, LOG_ERR, filename, line, r,
752 "Failed to parse NDISC black listed prefix, ignoring assignment: %s",
753 rvalue);
754 return 0;
755 }
756 if (r == 0)
757 return 0;
758
759 r = in_addr_from_string(AF_INET6, n, &ip);
760 if (r < 0) {
761 log_syntax(unit, LOG_ERR, filename, line, r,
762 "NDISC black listed prefix is invalid, ignoring assignment: %s", n);
763 continue;
764 }
765
766 r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops);
767 if (r < 0)
768 return log_oom();
769
770 a = newdup(struct in6_addr, &ip.in6, 1);
771 if (!a)
772 return log_oom();
773
774 r = set_put(network->ndisc_black_listed_prefix, a);
775 if (r < 0) {
776 if (r == -EEXIST)
777 log_syntax(unit, LOG_WARNING, filename, line, r,
778 "NDISC black listed prefixs is duplicated, ignoring assignment: %s", n);
779 else
780 log_syntax(unit, LOG_ERR, filename, line, r,
781 "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
782 continue;
783 }
784
785 TAKE_PTR(a);
786 }
787
788 return 0;
789 }