]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-radv.c
tree-wide: use TAKE_PTR() and TAKE_FD() macros
[thirdparty/systemd.git] / src / libsystemd-network / sd-radv.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright (C) 2017 Intel Corporation. All rights reserved.
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <netinet/icmp6.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24
25 #include "sd-radv.h"
26
27 #include "macro.h"
28 #include "alloc-util.h"
29 #include "dns-domain.h"
30 #include "fd-util.h"
31 #include "icmp6-util.h"
32 #include "in-addr-util.h"
33 #include "radv-internal.h"
34 #include "socket-util.h"
35 #include "string-util.h"
36 #include "strv.h"
37 #include "util.h"
38 #include "random-util.h"
39
40 _public_ int sd_radv_new(sd_radv **ret) {
41 _cleanup_(sd_radv_unrefp) sd_radv *ra = NULL;
42
43 assert_return(ret, -EINVAL);
44
45 ra = new0(sd_radv, 1);
46 if (!ra)
47 return -ENOMEM;
48
49 ra->n_ref = 1;
50 ra->fd = -1;
51
52 LIST_HEAD_INIT(ra->prefixes);
53
54 *ret = TAKE_PTR(ra);
55
56 return 0;
57 }
58
59 _public_ int sd_radv_attach_event(sd_radv *ra, sd_event *event, int64_t priority) {
60 int r;
61
62 assert_return(ra, -EINVAL);
63 assert_return(!ra->event, -EBUSY);
64
65 if (event)
66 ra->event = sd_event_ref(event);
67 else {
68 r = sd_event_default(&ra->event);
69 if (r < 0)
70 return 0;
71 }
72
73 ra->event_priority = priority;
74
75 return 0;
76 }
77
78 _public_ int sd_radv_detach_event(sd_radv *ra) {
79
80 assert_return(ra, -EINVAL);
81
82 ra->event = sd_event_unref(ra->event);
83 return 0;
84 }
85
86 _public_ sd_event *sd_radv_get_event(sd_radv *ra) {
87 assert_return(ra, NULL);
88
89 return ra->event;
90 }
91
92 static void radv_reset(sd_radv *ra) {
93
94 ra->timeout_event_source =
95 sd_event_source_unref(ra->timeout_event_source);
96
97 ra->recv_event_source =
98 sd_event_source_unref(ra->recv_event_source);
99
100 ra->ra_sent = 0;
101 }
102
103 _public_ sd_radv *sd_radv_ref(sd_radv *ra) {
104 if (!ra)
105 return NULL;
106
107 assert(ra->n_ref > 0);
108 ra->n_ref++;
109
110 return ra;
111 }
112
113 _public_ sd_radv *sd_radv_unref(sd_radv *ra) {
114 if (!ra)
115 return NULL;
116
117 assert(ra->n_ref > 0);
118 ra->n_ref--;
119
120 if (ra->n_ref > 0)
121 return NULL;
122
123 while (ra->prefixes) {
124 sd_radv_prefix *p = ra->prefixes;
125
126 LIST_REMOVE(prefix, ra->prefixes, p);
127 sd_radv_prefix_unref(p);
128 }
129
130 free(ra->rdnss);
131 free(ra->dnssl);
132
133 radv_reset(ra);
134
135 sd_radv_detach_event(ra);
136 return mfree(ra);
137 }
138
139 static int radv_send(sd_radv *ra, const struct in6_addr *dst,
140 const uint32_t router_lifetime) {
141 static const struct ether_addr mac_zero = {};
142 sd_radv_prefix *p;
143 struct sockaddr_in6 dst_addr = {
144 .sin6_family = AF_INET6,
145 .sin6_addr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
146 };
147 struct nd_router_advert adv = {};
148 struct {
149 struct nd_opt_hdr opthdr;
150 struct ether_addr slladdr;
151 } _packed_ opt_mac = {
152 .opthdr = {
153 .nd_opt_type = ND_OPT_SOURCE_LINKADDR,
154 .nd_opt_len = (sizeof(struct nd_opt_hdr) +
155 sizeof(struct ether_addr) - 1) /8 + 1,
156 },
157 };
158 struct nd_opt_mtu opt_mtu = {
159 .nd_opt_mtu_type = ND_OPT_MTU,
160 .nd_opt_mtu_len = 1,
161 };
162 /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, RDNSS
163 and DNSSL */
164 struct iovec iov[5 + ra->n_prefixes];
165 struct msghdr msg = {
166 .msg_name = &dst_addr,
167 .msg_namelen = sizeof(dst_addr),
168 .msg_iov = iov,
169 };
170 usec_t time_now;
171 int r;
172
173 r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
174 if (r < 0)
175 return r;
176
177 if (dst && !in_addr_is_null(AF_INET6, (union in_addr_union*) dst))
178 dst_addr.sin6_addr = *dst;
179
180 adv.nd_ra_type = ND_ROUTER_ADVERT;
181 adv.nd_ra_curhoplimit = ra->hop_limit;
182 adv.nd_ra_flags_reserved = ra->flags;
183 adv.nd_ra_router_lifetime = htobe16(router_lifetime);
184 iov[msg.msg_iovlen].iov_base = &adv;
185 iov[msg.msg_iovlen].iov_len = sizeof(adv);
186 msg.msg_iovlen++;
187
188 /* MAC address is optional, either because the link does not use L2
189 addresses or load sharing is desired. See RFC 4861, Section 4.2 */
190 if (memcmp(&mac_zero, &ra->mac_addr, sizeof(mac_zero))) {
191 opt_mac.slladdr = ra->mac_addr;
192 iov[msg.msg_iovlen].iov_base = &opt_mac;
193 iov[msg.msg_iovlen].iov_len = sizeof(opt_mac);
194 msg.msg_iovlen++;
195 }
196
197 if (ra->mtu) {
198 opt_mtu.nd_opt_mtu_mtu = htobe32(ra->mtu);
199 iov[msg.msg_iovlen].iov_base = &opt_mtu;
200 iov[msg.msg_iovlen].iov_len = sizeof(opt_mtu);
201 msg.msg_iovlen++;
202 }
203
204 LIST_FOREACH(prefix, p, ra->prefixes) {
205 if (p->valid_until) {
206
207 if (time_now > p->valid_until)
208 p->opt.valid_lifetime = 0;
209 else
210 p->opt.valid_lifetime = htobe32((p->valid_until - time_now) / USEC_PER_SEC);
211
212 if (time_now > p->preferred_until)
213 p->opt.preferred_lifetime = 0;
214 else
215 p->opt.preferred_lifetime = htobe32((p->preferred_until - time_now) / USEC_PER_SEC);
216 }
217 iov[msg.msg_iovlen].iov_base = &p->opt;
218 iov[msg.msg_iovlen].iov_len = sizeof(p->opt);
219 msg.msg_iovlen++;
220 }
221
222 if (ra->rdnss) {
223 iov[msg.msg_iovlen].iov_base = ra->rdnss;
224 iov[msg.msg_iovlen].iov_len = ra->rdnss->length * 8;
225 msg.msg_iovlen++;
226 }
227
228 if (ra->dnssl) {
229 iov[msg.msg_iovlen].iov_base = ra->dnssl;
230 iov[msg.msg_iovlen].iov_len = ra->dnssl->length * 8;
231 msg.msg_iovlen++;
232 }
233
234 if (sendmsg(ra->fd, &msg, 0) < 0)
235 return -errno;
236
237 return 0;
238 }
239
240 static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
241 sd_radv *ra = userdata;
242 _cleanup_free_ char *addr = NULL;
243 struct in6_addr src;
244 triple_timestamp timestamp;
245 int r;
246 ssize_t buflen;
247 _cleanup_free_ char *buf = NULL;
248
249 assert(s);
250 assert(ra);
251 assert(ra->event);
252
253 buflen = next_datagram_size_fd(fd);
254
255 if ((unsigned) buflen < sizeof(struct nd_router_solicit))
256 return log_radv("Too short packet received");
257
258 buf = new0(char, buflen);
259 if (!buf)
260 return 0;
261
262 r = icmp6_receive(fd, buf, buflen, &src, &timestamp);
263 if (r < 0) {
264 switch (r) {
265 case -EADDRNOTAVAIL:
266 (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &src, &addr);
267 log_radv("Received RS from non-link-local address %s. Ignoring", addr);
268 break;
269
270 case -EMULTIHOP:
271 log_radv("Received RS with invalid hop limit. Ignoring.");
272 break;
273
274 case -EPFNOSUPPORT:
275 log_radv("Received invalid source address from ICMPv6 socket. Ignoring.");
276 break;
277
278 default:
279 log_radv_warning_errno(r, "Error receiving from ICMPv6 socket: %m");
280 break;
281 }
282
283 return 0;
284 }
285
286 (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &src, &addr);
287
288 r = radv_send(ra, &src, ra->lifetime);
289 if (r < 0)
290 log_radv_warning_errno(r, "Unable to send solicited Router Advertisment to %s: %m", addr);
291 else
292 log_radv("Sent solicited Router Advertisement to %s", addr);
293
294 return 0;
295 }
296
297 static usec_t radv_compute_timeout(usec_t min, usec_t max) {
298 assert_return(min <= max, SD_RADV_DEFAULT_MIN_TIMEOUT_USEC);
299
300 return min + (random_u32() % (max - min));
301 }
302
303 static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
304 int r;
305 sd_radv *ra = userdata;
306 usec_t min_timeout = SD_RADV_DEFAULT_MIN_TIMEOUT_USEC;
307 usec_t max_timeout = SD_RADV_DEFAULT_MAX_TIMEOUT_USEC;
308 usec_t time_now, timeout;
309 char time_string[FORMAT_TIMESPAN_MAX];
310
311 assert(s);
312 assert(ra);
313 assert(ra->event);
314
315 ra->timeout_event_source = sd_event_source_unref(ra->timeout_event_source);
316
317 r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
318 if (r < 0)
319 goto fail;
320
321 r = radv_send(ra, NULL, ra->lifetime);
322 if (r < 0)
323 log_radv_warning_errno(r, "Unable to send Router Advertisement: %m");
324
325 /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
326 if (ra->ra_sent < SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS) {
327 max_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC;
328 min_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC / 3;
329 }
330
331 timeout = radv_compute_timeout(min_timeout, max_timeout);
332
333 log_radv("Next Router Advertisement in %s",
334 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
335 timeout, USEC_PER_SEC));
336
337 r = sd_event_add_time(ra->event, &ra->timeout_event_source,
338 clock_boottime_or_monotonic(),
339 time_now + timeout, MSEC_PER_SEC,
340 radv_timeout, ra);
341 if (r < 0)
342 goto fail;
343
344 r = sd_event_source_set_priority(ra->timeout_event_source,
345 ra->event_priority);
346 if (r < 0)
347 goto fail;
348
349 r = sd_event_source_set_description(ra->timeout_event_source,
350 "radv-timeout");
351 if (r < 0)
352 goto fail;
353
354 ra->ra_sent++;
355
356 fail:
357 if (r < 0)
358 sd_radv_stop(ra);
359
360 return 0;
361 }
362
363 _public_ int sd_radv_stop(sd_radv *ra) {
364 int r;
365
366 assert_return(ra, -EINVAL);
367
368 log_radv("Stopping IPv6 Router Advertisement daemon");
369
370 /* RFC 4861, Section 6.2.5, send at least one Router Advertisement
371 with zero lifetime */
372 r = radv_send(ra, NULL, 0);
373 if (r < 0)
374 log_radv_warning_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
375
376 radv_reset(ra);
377 ra->fd = safe_close(ra->fd);
378 ra->state = SD_RADV_STATE_IDLE;
379
380 return 0;
381 }
382
383 _public_ int sd_radv_start(sd_radv *ra) {
384 int r = 0;
385
386 assert_return(ra, -EINVAL);
387 assert_return(ra->event, -EINVAL);
388 assert_return(ra->ifindex > 0, -EINVAL);
389
390 if (ra->state != SD_RADV_STATE_IDLE)
391 return 0;
392
393 r = sd_event_add_time(ra->event, &ra->timeout_event_source,
394 clock_boottime_or_monotonic(), 0, 0,
395 radv_timeout, ra);
396 if (r < 0)
397 goto fail;
398
399 r = sd_event_source_set_priority(ra->timeout_event_source,
400 ra->event_priority);
401 if (r < 0)
402 goto fail;
403
404 (void) sd_event_source_set_description(ra->timeout_event_source,
405 "radv-timeout");
406
407 r = icmp6_bind_router_advertisement(ra->ifindex);
408 if (r < 0)
409 goto fail;
410
411 ra->fd = r;
412
413 r = sd_event_add_io(ra->event, &ra->recv_event_source, ra->fd, EPOLLIN, radv_recv, ra);
414 if (r < 0)
415 goto fail;
416
417 r = sd_event_source_set_priority(ra->recv_event_source, ra->event_priority);
418 if (r < 0)
419 goto fail;
420
421 (void) sd_event_source_set_description(ra->recv_event_source, "radv-receive-message");
422
423 ra->state = SD_RADV_STATE_ADVERTISING;
424
425 log_radv("Started IPv6 Router Advertisement daemon");
426
427 return 0;
428
429 fail:
430 radv_reset(ra);
431
432 return r;
433 }
434
435 _public_ int sd_radv_set_ifindex(sd_radv *ra, int ifindex) {
436 assert_return(ra, -EINVAL);
437 assert_return(ifindex >= -1, -EINVAL);
438
439 if (ra->state != SD_RADV_STATE_IDLE)
440 return -EBUSY;
441
442 ra->ifindex = ifindex;
443
444 return 0;
445 }
446
447 _public_ int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) {
448 assert_return(ra, -EINVAL);
449
450 if (ra->state != SD_RADV_STATE_IDLE)
451 return -EBUSY;
452
453 if (mac_addr)
454 ra->mac_addr = *mac_addr;
455 else
456 zero(ra->mac_addr);
457
458 return 0;
459 }
460
461 _public_ int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu) {
462 assert_return(ra, -EINVAL);
463 assert_return(mtu >= 1280, -EINVAL);
464
465 ra->mtu = mtu;
466
467 return 0;
468 }
469
470 _public_ int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) {
471 assert_return(ra, -EINVAL);
472
473 if (ra->state != SD_RADV_STATE_IDLE)
474 return -EBUSY;
475
476 ra->hop_limit = hop_limit;
477
478 return 0;
479 }
480
481 _public_ int sd_radv_set_router_lifetime(sd_radv *ra, uint32_t router_lifetime) {
482 assert_return(ra, -EINVAL);
483
484 if (ra->state != SD_RADV_STATE_IDLE)
485 return -EBUSY;
486
487 /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the
488 preference value MUST be set to (00) by the sender..." */
489 if (router_lifetime == 0 &&
490 (ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3))
491 return -ETIME;
492
493 ra->lifetime = router_lifetime;
494
495 return 0;
496 }
497
498 _public_ int sd_radv_set_managed_information(sd_radv *ra, int managed) {
499 assert_return(ra, -EINVAL);
500
501 if (ra->state != SD_RADV_STATE_IDLE)
502 return -EBUSY;
503
504 SET_FLAG(ra->flags, ND_RA_FLAG_MANAGED, managed);
505
506 return 0;
507 }
508
509 _public_ int sd_radv_set_other_information(sd_radv *ra, int other) {
510 assert_return(ra, -EINVAL);
511
512 if (ra->state != SD_RADV_STATE_IDLE)
513 return -EBUSY;
514
515 SET_FLAG(ra->flags, ND_RA_FLAG_OTHER, other);
516
517 return 0;
518 }
519
520 _public_ int sd_radv_set_preference(sd_radv *ra, unsigned preference) {
521 int r = 0;
522
523 assert_return(ra, -EINVAL);
524 assert_return(IN_SET(preference,
525 SD_NDISC_PREFERENCE_LOW,
526 SD_NDISC_PREFERENCE_MEDIUM,
527 SD_NDISC_PREFERENCE_HIGH), -EINVAL);
528
529 ra->flags = (ra->flags & ~(0x3 << 3)) | (preference << 3);
530
531 return r;
532 }
533
534 _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, bool dynamic) {
535 sd_radv_prefix *cur;
536 int r;
537 _cleanup_free_ char *addr_p = NULL;
538 char time_string_preferred[FORMAT_TIMESPAN_MAX];
539 char time_string_valid[FORMAT_TIMESPAN_MAX];
540 usec_t time_now, valid, preferred, valid_until, preferred_until;
541
542 assert_return(ra, -EINVAL);
543
544 if (!p)
545 return -EINVAL;
546
547 LIST_FOREACH(prefix, cur, ra->prefixes) {
548
549 r = in_addr_prefix_intersect(AF_INET6,
550 (union in_addr_union*) &cur->opt.in6_addr,
551 cur->opt.prefixlen,
552 (union in_addr_union*) &p->opt.in6_addr,
553 p->opt.prefixlen);
554 if (r > 0) {
555 _cleanup_free_ char *addr_cur = NULL;
556
557 (void) in_addr_to_string(AF_INET6,
558 (union in_addr_union*) &p->opt.in6_addr,
559 &addr_p);
560
561 if (dynamic && cur->opt.prefixlen == p->opt.prefixlen)
562 goto update;
563
564 (void) in_addr_to_string(AF_INET6,
565 (union in_addr_union*) &cur->opt.in6_addr,
566 &addr_cur);
567 log_radv("IPv6 prefix %s/%u already configured, ignoring %s/%u",
568 addr_cur, cur->opt.prefixlen,
569 addr_p, p->opt.prefixlen);
570
571 return -EEXIST;
572 }
573 }
574
575 p = sd_radv_prefix_ref(p);
576
577 LIST_APPEND(prefix, ra->prefixes, p);
578
579 ra->n_prefixes++;
580
581 (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &p->opt.in6_addr, &addr_p);
582
583 if (!dynamic) {
584 log_radv("Added prefix %s/%d", addr_p, p->opt.prefixlen);
585 return 0;
586 }
587
588 cur = p;
589
590 update:
591 r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
592 if (r < 0)
593 return r;
594
595 valid = be32toh(p->opt.valid_lifetime) * USEC_PER_SEC;
596 valid_until = usec_add(valid, time_now);
597 if (valid_until == USEC_INFINITY)
598 return -EOVERFLOW;
599
600 preferred = be32toh(p->opt.preferred_lifetime) * USEC_PER_SEC;
601 preferred_until = usec_add(preferred, time_now);
602 if (preferred_until == USEC_INFINITY)
603 return -EOVERFLOW;
604
605 cur->valid_until = valid_until;
606 cur->preferred_until = preferred_until;
607
608 log_radv("%s prefix %s/%u preferred %s valid %s",
609 cur? "Updated": "Added",
610 addr_p, p->opt.prefixlen,
611 format_timespan(time_string_preferred, FORMAT_TIMESPAN_MAX,
612 preferred, USEC_PER_SEC),
613 format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX,
614 valid, USEC_PER_SEC));
615
616 return 0;
617 }
618
619 _public_ sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra,
620 struct in6_addr *prefix,
621 uint8_t prefixlen) {
622 sd_radv_prefix *cur, *next;
623
624 assert_return(ra, NULL);
625 assert_return(prefix, NULL);
626
627 LIST_FOREACH_SAFE(prefix, cur, next, ra->prefixes) {
628 if (prefixlen != cur->opt.prefixlen)
629 continue;
630
631 if (!in_addr_equal(AF_INET6,
632 (union in_addr_union *)prefix,
633 (union in_addr_union *)&cur->opt.in6_addr))
634 continue;
635
636 LIST_REMOVE(prefix, ra->prefixes, cur);
637 ra->n_prefixes--;
638
639 break;
640 }
641
642 return cur;
643 }
644
645 _public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime,
646 const struct in6_addr *dns, size_t n_dns) {
647 _cleanup_free_ struct sd_radv_opt_dns *opt_rdnss = NULL;
648 size_t len;
649
650 assert_return(ra, -EINVAL);
651 assert_return(n_dns < 128, -EINVAL);
652
653 if (!dns || n_dns == 0) {
654 ra->rdnss = mfree(ra->rdnss);
655 ra->n_rdnss = 0;
656
657 return 0;
658 }
659
660 len = sizeof(struct sd_radv_opt_dns) + sizeof(struct in6_addr) * n_dns;
661
662 opt_rdnss = malloc0(len);
663 if (!opt_rdnss)
664 return -ENOMEM;
665
666 opt_rdnss->type = SD_RADV_OPT_RDNSS;
667 opt_rdnss->length = len / 8;
668 opt_rdnss->lifetime = htobe32(lifetime);
669
670 memcpy(opt_rdnss + 1, dns, n_dns * sizeof(struct in6_addr));
671
672 free_and_replace(ra->rdnss, opt_rdnss);
673
674 ra->n_rdnss = n_dns;
675
676 return 0;
677 }
678
679 _public_ int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime,
680 char **search_list) {
681 _cleanup_free_ struct sd_radv_opt_dns *opt_dnssl = NULL;
682 size_t len = 0;
683 char **s;
684 uint8_t *p;
685
686 assert_return(ra, -EINVAL);
687
688 if (!search_list || *search_list == NULL) {
689 ra->dnssl = mfree(ra->dnssl);
690
691 return 0;
692 }
693
694 STRV_FOREACH(s, search_list)
695 len += strlen(*s) + 2;
696
697 len = (sizeof(struct sd_radv_opt_dns) + len + 7) & ~0x7;
698
699 opt_dnssl = malloc0(len);
700 if (!opt_dnssl)
701 return -ENOMEM;
702
703 opt_dnssl->type = SD_RADV_OPT_DNSSL;
704 opt_dnssl->length = len / 8;
705 opt_dnssl->lifetime = htobe32(lifetime);
706
707 p = (uint8_t *)(opt_dnssl + 1);
708 len -= sizeof(struct sd_radv_opt_dns);
709
710 STRV_FOREACH(s, search_list) {
711 int r;
712
713 r = dns_name_to_wire_format(*s, p, len, false);
714 if (r < 0)
715 return r;
716
717 if (len < (size_t)r)
718 return -ENOBUFS;
719
720 p += r;
721 len -= r;
722 }
723
724 free_and_replace(ra->dnssl, opt_dnssl);
725
726 return 0;
727 }
728
729 _public_ int sd_radv_prefix_new(sd_radv_prefix **ret) {
730 _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
731
732 assert_return(ret, -EINVAL);
733
734 p = new0(sd_radv_prefix, 1);
735 if (!p)
736 return -ENOMEM;
737
738 p->n_ref = 1;
739
740 p->opt.type = ND_OPT_PREFIX_INFORMATION;
741 p->opt.length = (sizeof(p->opt) - 1) /8 + 1;
742
743 p->opt.prefixlen = 64;
744
745 /* RFC 4861, Section 6.2.1 */
746 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, true);
747 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, true);
748 p->opt.preferred_lifetime = htobe32(604800);
749 p->opt.valid_lifetime = htobe32(2592000);
750
751 LIST_INIT(prefix, p);
752
753 *ret = TAKE_PTR(p);
754
755 return 0;
756 }
757
758 _public_ sd_radv_prefix *sd_radv_prefix_ref(sd_radv_prefix *p) {
759 if (!p)
760 return NULL;
761
762 assert(p->n_ref > 0);
763 p->n_ref++;
764
765 return p;
766 }
767
768 _public_ sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *p) {
769 if (!p)
770 return NULL;
771
772 assert(p->n_ref > 0);
773 p->n_ref--;
774
775 if (p->n_ref > 0)
776 return NULL;
777
778 return mfree(p);
779 }
780
781 _public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, struct in6_addr *in6_addr,
782 unsigned char prefixlen) {
783 assert_return(p, -EINVAL);
784 assert_return(in6_addr, -EINVAL);
785
786 if (prefixlen < 3 || prefixlen > 128)
787 return -EINVAL;
788
789 if (prefixlen > 64)
790 /* unusual but allowed, log it */
791 log_radv("Unusual prefix length %d greater than 64", prefixlen);
792
793 p->opt.in6_addr = *in6_addr;
794 p->opt.prefixlen = prefixlen;
795
796 return 0;
797 }
798
799 _public_ int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink) {
800 assert_return(p, -EINVAL);
801
802 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, onlink);
803
804 return 0;
805 }
806
807 _public_ int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p,
808 int address_autoconfiguration) {
809 assert_return(p, -EINVAL);
810
811 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, address_autoconfiguration);
812
813 return 0;
814 }
815
816 _public_ int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p,
817 uint32_t valid_lifetime) {
818 assert_return(p, -EINVAL);
819
820 p->opt.valid_lifetime = htobe32(valid_lifetime);
821
822 return 0;
823 }
824
825 _public_ int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p,
826 uint32_t preferred_lifetime) {
827 assert_return(p, -EINVAL);
828
829 p->opt.preferred_lifetime = htobe32(preferred_lifetime);
830
831 return 0;
832 }