]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-radv.c
97d306c49b2b067039bf77996acf6e8edca57261
[thirdparty/systemd.git] / src / libsystemd-network / sd-radv.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2017 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <netinet/icmp6.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9
10 #include "sd-radv.h"
11
12 #include "alloc-util.h"
13 #include "dns-domain.h"
14 #include "ether-addr-util.h"
15 #include "event-util.h"
16 #include "fd-util.h"
17 #include "icmp6-util.h"
18 #include "in-addr-util.h"
19 #include "iovec-util.h"
20 #include "macro.h"
21 #include "memory-util.h"
22 #include "network-common.h"
23 #include "radv-internal.h"
24 #include "random-util.h"
25 #include "socket-util.h"
26 #include "string-util.h"
27 #include "strv.h"
28 #include "unaligned.h"
29
30 int sd_radv_new(sd_radv **ret) {
31 _cleanup_(sd_radv_unrefp) sd_radv *ra = NULL;
32
33 assert_return(ret, -EINVAL);
34
35 ra = new(sd_radv, 1);
36 if (!ra)
37 return -ENOMEM;
38
39 *ra = (sd_radv) {
40 .n_ref = 1,
41 .fd = -EBADF,
42 .lifetime_usec = RADV_DEFAULT_ROUTER_LIFETIME_USEC,
43 };
44
45 *ret = TAKE_PTR(ra);
46
47 return 0;
48 }
49
50 int sd_radv_attach_event(sd_radv *ra, sd_event *event, int64_t priority) {
51 int r;
52
53 assert_return(ra, -EINVAL);
54 assert_return(!ra->event, -EBUSY);
55
56 if (event)
57 ra->event = sd_event_ref(event);
58 else {
59 r = sd_event_default(&ra->event);
60 if (r < 0)
61 return 0;
62 }
63
64 ra->event_priority = priority;
65
66 return 0;
67 }
68
69 int sd_radv_detach_event(sd_radv *ra) {
70
71 assert_return(ra, -EINVAL);
72
73 ra->event = sd_event_unref(ra->event);
74 return 0;
75 }
76
77 sd_event *sd_radv_get_event(sd_radv *ra) {
78 assert_return(ra, NULL);
79
80 return ra->event;
81 }
82
83 int sd_radv_is_running(sd_radv *ra) {
84 assert_return(ra, false);
85
86 return ra->state != RADV_STATE_IDLE;
87 }
88
89 static void radv_reset(sd_radv *ra) {
90 assert(ra);
91
92 (void) event_source_disable(ra->timeout_event_source);
93
94 ra->recv_event_source = sd_event_source_disable_unref(ra->recv_event_source);
95
96 ra->ra_sent = 0;
97 }
98
99 static sd_radv *radv_free(sd_radv *ra) {
100 if (!ra)
101 return NULL;
102
103 LIST_CLEAR(prefix, ra->prefixes, sd_radv_prefix_unref);
104 LIST_CLEAR(prefix, ra->route_prefixes, sd_radv_route_prefix_unref);
105 LIST_CLEAR(prefix, ra->pref64_prefixes, sd_radv_pref64_prefix_unref);
106
107 free(ra->rdnss);
108 free(ra->dnssl);
109
110 radv_reset(ra);
111
112 sd_event_source_unref(ra->timeout_event_source);
113 sd_radv_detach_event(ra);
114
115 ra->fd = safe_close(ra->fd);
116 free(ra->ifname);
117
118 return mfree(ra);
119 }
120
121 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free);
122
123 static bool router_lifetime_is_valid(usec_t lifetime_usec) {
124 return lifetime_usec == 0 ||
125 (lifetime_usec >= RADV_MIN_ROUTER_LIFETIME_USEC &&
126 lifetime_usec <= RADV_MAX_ROUTER_LIFETIME_USEC);
127 }
128
129 static int radv_send(sd_radv *ra, const struct in6_addr *dst, usec_t lifetime_usec) {
130 struct sockaddr_in6 dst_addr = {
131 .sin6_family = AF_INET6,
132 .sin6_addr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
133 };
134 struct nd_router_advert adv = {};
135 struct {
136 struct nd_opt_hdr opthdr;
137 struct ether_addr slladdr;
138 } _packed_ opt_mac = {
139 .opthdr = {
140 .nd_opt_type = ND_OPT_SOURCE_LINKADDR,
141 .nd_opt_len = (sizeof(struct nd_opt_hdr) +
142 sizeof(struct ether_addr) - 1) /8 + 1,
143 },
144 };
145 struct nd_opt_mtu opt_mtu = {
146 .nd_opt_mtu_type = ND_OPT_MTU,
147 .nd_opt_mtu_len = 1,
148 };
149 /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, N routes, N pref64 prefixes, RDNSS,
150 * DNSSL, and home agent. */
151 struct iovec iov[6 + ra->n_prefixes + ra->n_route_prefixes + ra->n_pref64_prefixes];
152 struct msghdr msg = {
153 .msg_name = &dst_addr,
154 .msg_namelen = sizeof(dst_addr),
155 .msg_iov = iov,
156 };
157 usec_t time_now;
158 int r;
159
160 assert(ra);
161 assert(router_lifetime_is_valid(lifetime_usec));
162
163 r = sd_event_now(ra->event, CLOCK_BOOTTIME, &time_now);
164 if (r < 0)
165 return r;
166
167 if (dst && in6_addr_is_set(dst))
168 dst_addr.sin6_addr = *dst;
169
170 adv.nd_ra_type = ND_ROUTER_ADVERT;
171 adv.nd_ra_curhoplimit = ra->hop_limit;
172 adv.nd_ra_retransmit = usec_to_be32_msec(ra->retransmit_usec);
173 adv.nd_ra_flags_reserved = ra->flags;
174 assert_cc(RADV_MAX_ROUTER_LIFETIME_USEC <= UINT16_MAX * USEC_PER_SEC);
175 adv.nd_ra_router_lifetime = usec_to_be16_sec(lifetime_usec);
176 iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv));
177
178 /* MAC address is optional, either because the link does not use L2
179 addresses or load sharing is desired. See RFC 4861, Section 4.2 */
180 if (!ether_addr_is_null(&ra->mac_addr)) {
181 opt_mac.slladdr = ra->mac_addr;
182 iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mac, sizeof(opt_mac));
183 }
184
185 if (ra->mtu > 0) {
186 opt_mtu.nd_opt_mtu_mtu = htobe32(ra->mtu);
187 iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mtu, sizeof(opt_mtu));
188 }
189
190 LIST_FOREACH(prefix, p, ra->prefixes) {
191 usec_t lifetime_valid_usec, lifetime_preferred_usec;
192
193 lifetime_valid_usec = MIN(usec_sub_unsigned(p->valid_until, time_now),
194 p->lifetime_valid_usec);
195
196 lifetime_preferred_usec = MIN3(usec_sub_unsigned(p->preferred_until, time_now),
197 p->lifetime_preferred_usec,
198 lifetime_valid_usec);
199
200 p->opt.lifetime_valid = usec_to_be32_sec(lifetime_valid_usec);
201 p->opt.lifetime_preferred = usec_to_be32_sec(lifetime_preferred_usec);
202
203 iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt));
204 }
205
206 LIST_FOREACH(prefix, rt, ra->route_prefixes) {
207 rt->opt.lifetime = usec_to_be32_sec(MIN(usec_sub_unsigned(rt->valid_until, time_now),
208 rt->lifetime_usec));
209
210 iov[msg.msg_iovlen++] = IOVEC_MAKE(&rt->opt, sizeof(rt->opt));
211 }
212
213 LIST_FOREACH(prefix, p, ra->pref64_prefixes)
214 iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt));
215
216 if (ra->rdnss)
217 iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->rdnss, ra->rdnss->length * 8);
218
219 if (ra->dnssl)
220 iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->dnssl, ra->dnssl->length * 8);
221
222 if (FLAGS_SET(ra->flags, ND_RA_FLAG_HOME_AGENT)) {
223 ra->home_agent.nd_opt_home_agent_info_type = ND_OPT_HOME_AGENT_INFO;
224 ra->home_agent.nd_opt_home_agent_info_len = 1;
225
226 /* 0 means to place the current Router Lifetime value */
227 if (ra->home_agent.nd_opt_home_agent_info_lifetime == 0)
228 ra->home_agent.nd_opt_home_agent_info_lifetime = adv.nd_ra_router_lifetime;
229
230 iov[msg.msg_iovlen++] = IOVEC_MAKE(&ra->home_agent, sizeof(ra->home_agent));
231 }
232
233 if (sendmsg(ra->fd, &msg, 0) < 0)
234 return -errno;
235
236 return 0;
237 }
238
239 static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
240 sd_radv *ra = ASSERT_PTR(userdata);
241 struct in6_addr src;
242 triple_timestamp timestamp;
243 int r;
244
245 assert(s);
246 assert(ra->event);
247
248 ssize_t buflen = next_datagram_size_fd(fd);
249 if (ERRNO_IS_NEG_TRANSIENT(buflen) || ERRNO_IS_NEG_DISCONNECT(buflen))
250 return 0;
251 if (buflen < 0) {
252 log_radv_errno(ra, buflen, "Failed to determine datagram size to read, ignoring: %m");
253 return 0;
254 }
255
256 _cleanup_free_ char *buf = new0(char, buflen);
257 if (!buf)
258 return -ENOMEM;
259
260 r = icmp6_receive(fd, buf, buflen, &src, &timestamp);
261 if (ERRNO_IS_NEG_TRANSIENT(r) || ERRNO_IS_NEG_DISCONNECT(r))
262 return 0;
263 if (r < 0)
264 switch (r) {
265 case -EADDRNOTAVAIL:
266 log_radv(ra, "Received RS from neither link-local nor null address. Ignoring");
267 return 0;
268
269 case -EMULTIHOP:
270 log_radv(ra, "Received RS with invalid hop limit. Ignoring.");
271 return 0;
272
273 case -EPFNOSUPPORT:
274 log_radv(ra, "Received invalid source address from ICMPv6 socket. Ignoring.");
275 return 0;
276
277 default:
278 log_radv_errno(ra, r, "Unexpected error receiving from ICMPv6 socket, ignoring: %m");
279 return 0;
280 }
281
282 if ((size_t) buflen < sizeof(struct nd_router_solicit)) {
283 log_radv(ra, "Too short packet received, ignoring");
284 return 0;
285 }
286
287 /* TODO: if the sender address is null, check that the message does not have the source link-layer
288 * address option. See RFC 4861 Section 6.1.1. */
289
290 const char *addr = IN6_ADDR_TO_STRING(&src);
291
292 r = radv_send(ra, &src, ra->lifetime_usec);
293 if (r < 0)
294 log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", addr);
295 else
296 log_radv(ra, "Sent solicited Router Advertisement to %s", addr);
297
298 return 0;
299 }
300
301 static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
302 usec_t min_timeout, max_timeout, time_now, timeout;
303 sd_radv *ra = ASSERT_PTR(userdata);
304 int r;
305
306 assert(s);
307 assert(ra->event);
308 assert(router_lifetime_is_valid(ra->lifetime_usec));
309
310 r = sd_event_now(ra->event, CLOCK_BOOTTIME, &time_now);
311 if (r < 0)
312 goto fail;
313
314 r = radv_send(ra, NULL, ra->lifetime_usec);
315 if (r < 0)
316 log_radv_errno(ra, r, "Unable to send Router Advertisement, ignoring: %m");
317
318 /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
319 if (ra->ra_sent < RADV_MAX_INITIAL_RTR_ADVERTISEMENTS)
320 max_timeout = RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC;
321 else
322 max_timeout = RADV_DEFAULT_MAX_TIMEOUT_USEC;
323
324 /* RFC 4861, Section 6.2.1, lifetime must be at least MaxRtrAdvInterval,
325 * so lower the interval here */
326 if (ra->lifetime_usec > 0)
327 max_timeout = MIN(max_timeout, ra->lifetime_usec);
328
329 if (max_timeout >= 9 * USEC_PER_SEC)
330 min_timeout = max_timeout / 3;
331 else
332 min_timeout = max_timeout * 3 / 4;
333
334 /* RFC 4861, Section 6.2.1.
335 * MaxRtrAdvInterval MUST be no less than 4 seconds and no greater than 1800 seconds.
336 * MinRtrAdvInterval MUST be no less than 3 seconds and no greater than .75 * MaxRtrAdvInterval. */
337 assert(max_timeout >= RADV_MIN_MAX_TIMEOUT_USEC);
338 assert(max_timeout <= RADV_MAX_MAX_TIMEOUT_USEC);
339 assert(min_timeout >= RADV_MIN_MIN_TIMEOUT_USEC);
340 assert(min_timeout <= max_timeout * 3 / 4);
341
342 timeout = min_timeout + random_u64_range(max_timeout - min_timeout);
343 log_radv(ra, "Next Router Advertisement in %s", FORMAT_TIMESPAN(timeout, USEC_PER_SEC));
344
345 r = event_reset_time(ra->event, &ra->timeout_event_source,
346 CLOCK_BOOTTIME,
347 usec_add(time_now, timeout), MSEC_PER_SEC,
348 radv_timeout, ra,
349 ra->event_priority, "radv-timeout", true);
350 if (r < 0)
351 goto fail;
352
353 ra->ra_sent++;
354
355 return 0;
356
357 fail:
358 sd_radv_stop(ra);
359
360 return 0;
361 }
362
363 int sd_radv_stop(sd_radv *ra) {
364 int r;
365
366 if (!ra)
367 return 0;
368
369 if (ra->state == RADV_STATE_IDLE)
370 return 0;
371
372 log_radv(ra, "Stopping IPv6 Router Advertisement daemon");
373
374 /* RFC 4861, Section 6.2.5, send at least one Router Advertisement
375 with zero lifetime */
376 r = radv_send(ra, NULL, 0);
377 if (r < 0)
378 log_radv_errno(ra, r, "Unable to send last Router Advertisement with router lifetime set to zero, ignoring: %m");
379
380 radv_reset(ra);
381 ra->fd = safe_close(ra->fd);
382 ra->state = RADV_STATE_IDLE;
383
384 return 0;
385 }
386
387 int sd_radv_start(sd_radv *ra) {
388 int r;
389
390 assert_return(ra, -EINVAL);
391 assert_return(ra->event, -EINVAL);
392 assert_return(ra->ifindex > 0, -EINVAL);
393
394 if (ra->state != RADV_STATE_IDLE)
395 return 0;
396
397 r = event_reset_time(ra->event, &ra->timeout_event_source,
398 CLOCK_BOOTTIME,
399 0, 0,
400 radv_timeout, ra,
401 ra->event_priority, "radv-timeout", true);
402 if (r < 0)
403 goto fail;
404
405 r = icmp6_bind_router_advertisement(ra->ifindex);
406 if (r < 0)
407 goto fail;
408
409 ra->fd = r;
410
411 r = sd_event_add_io(ra->event, &ra->recv_event_source, ra->fd, EPOLLIN, radv_recv, ra);
412 if (r < 0)
413 goto fail;
414
415 r = sd_event_source_set_priority(ra->recv_event_source, ra->event_priority);
416 if (r < 0)
417 goto fail;
418
419 (void) sd_event_source_set_description(ra->recv_event_source, "radv-receive-message");
420
421 ra->state = RADV_STATE_ADVERTISING;
422
423 log_radv(ra, "Started IPv6 Router Advertisement daemon");
424
425 return 0;
426
427 fail:
428 radv_reset(ra);
429
430 return r;
431 }
432
433 int sd_radv_set_ifindex(sd_radv *ra, int ifindex) {
434 assert_return(ra, -EINVAL);
435 assert_return(ifindex > 0, -EINVAL);
436
437 if (ra->state != RADV_STATE_IDLE)
438 return -EBUSY;
439
440 ra->ifindex = ifindex;
441
442 return 0;
443 }
444
445 int sd_radv_set_ifname(sd_radv *ra, const char *ifname) {
446 assert_return(ra, -EINVAL);
447 assert_return(ifname, -EINVAL);
448
449 if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
450 return -EINVAL;
451
452 return free_and_strdup(&ra->ifname, ifname);
453 }
454
455 int sd_radv_get_ifname(sd_radv *ra, const char **ret) {
456 int r;
457
458 assert_return(ra, -EINVAL);
459
460 r = get_ifname(ra->ifindex, &ra->ifname);
461 if (r < 0)
462 return r;
463
464 if (ret)
465 *ret = ra->ifname;
466
467 return 0;
468 }
469
470 int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) {
471 assert_return(ra, -EINVAL);
472
473 if (ra->state != RADV_STATE_IDLE)
474 return -EBUSY;
475
476 if (mac_addr)
477 ra->mac_addr = *mac_addr;
478 else
479 zero(ra->mac_addr);
480
481 return 0;
482 }
483
484 int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu) {
485 assert_return(ra, -EINVAL);
486 assert_return(mtu >= 1280, -EINVAL);
487
488 ra->mtu = mtu;
489
490 return 0;
491 }
492
493 int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) {
494 assert_return(ra, -EINVAL);
495
496 if (ra->state != RADV_STATE_IDLE)
497 return -EBUSY;
498
499 ra->hop_limit = hop_limit;
500
501 return 0;
502 }
503
504 int sd_radv_set_retransmit(sd_radv *ra, uint64_t usec) {
505 assert_return(ra, -EINVAL);
506
507 if (ra->state != RADV_STATE_IDLE)
508 return -EBUSY;
509
510 if (usec > RADV_MAX_RETRANSMIT_USEC)
511 return -EINVAL;
512
513 ra->retransmit_usec = usec;
514 return 0;
515 }
516
517 int sd_radv_set_router_lifetime(sd_radv *ra, uint64_t usec) {
518 assert_return(ra, -EINVAL);
519
520 if (ra->state != RADV_STATE_IDLE)
521 return -EBUSY;
522
523 if (!router_lifetime_is_valid(usec))
524 return -EINVAL;
525
526 /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set
527 * to (00) by the sender..." */
528 if (usec == 0 &&
529 (ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3))
530 return -EINVAL;
531
532 ra->lifetime_usec = usec;
533 return 0;
534 }
535
536 int sd_radv_set_managed_information(sd_radv *ra, int managed) {
537 assert_return(ra, -EINVAL);
538
539 if (ra->state != RADV_STATE_IDLE)
540 return -EBUSY;
541
542 SET_FLAG(ra->flags, ND_RA_FLAG_MANAGED, managed);
543
544 return 0;
545 }
546
547 int sd_radv_set_other_information(sd_radv *ra, int other) {
548 assert_return(ra, -EINVAL);
549
550 if (ra->state != RADV_STATE_IDLE)
551 return -EBUSY;
552
553 SET_FLAG(ra->flags, ND_RA_FLAG_OTHER, other);
554
555 return 0;
556 }
557
558 int sd_radv_set_preference(sd_radv *ra, unsigned preference) {
559 assert_return(ra, -EINVAL);
560 assert_return(IN_SET(preference,
561 SD_NDISC_PREFERENCE_LOW,
562 SD_NDISC_PREFERENCE_MEDIUM,
563 SD_NDISC_PREFERENCE_HIGH), -EINVAL);
564
565 /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the preference value MUST be set
566 * to (00) by the sender..." */
567 if (ra->lifetime_usec == 0 && preference != SD_NDISC_PREFERENCE_MEDIUM)
568 return -EINVAL;
569
570 ra->flags = (ra->flags & ~(0x3 << 3)) | (preference << 3);
571
572 return 0;
573 }
574
575 int sd_radv_set_home_agent_information(sd_radv *ra, int home_agent) {
576 assert_return(ra, -EINVAL);
577
578 if (ra->state != RADV_STATE_IDLE)
579 return -EBUSY;
580
581 SET_FLAG(ra->flags, ND_RA_FLAG_HOME_AGENT, home_agent);
582
583 return 0;
584 }
585
586 int sd_radv_set_home_agent_preference(sd_radv *ra, uint16_t preference) {
587 assert_return(ra, -EINVAL);
588
589 if (ra->state != RADV_STATE_IDLE)
590 return -EBUSY;
591
592 ra->home_agent.nd_opt_home_agent_info_preference = htobe16(preference);
593
594 return 0;
595 }
596
597 int sd_radv_set_home_agent_lifetime(sd_radv *ra, uint64_t lifetime_usec) {
598 assert_return(ra, -EINVAL);
599
600 if (ra->state != RADV_STATE_IDLE)
601 return -EBUSY;
602
603 if (lifetime_usec > RADV_HOME_AGENT_MAX_LIFETIME_USEC)
604 return -EINVAL;
605
606 ra->home_agent.nd_opt_home_agent_info_lifetime = usec_to_be16_sec(lifetime_usec);
607 return 0;
608 }
609
610 int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p) {
611 sd_radv_prefix *found = NULL;
612 int r;
613
614 assert_return(ra, -EINVAL);
615 assert_return(p, -EINVAL);
616
617 /* Refuse prefixes that don't have a prefix set */
618 if (in6_addr_is_null(&p->opt.in6_addr))
619 return -ENOEXEC;
620
621 const char *addr_p = IN6_ADDR_PREFIX_TO_STRING(&p->opt.in6_addr, p->opt.prefixlen);
622
623 LIST_FOREACH(prefix, cur, ra->prefixes) {
624 r = in_addr_prefix_intersect(AF_INET6,
625 (const union in_addr_union*) &cur->opt.in6_addr,
626 cur->opt.prefixlen,
627 (const union in_addr_union*) &p->opt.in6_addr,
628 p->opt.prefixlen);
629 if (r < 0)
630 return r;
631 if (r == 0)
632 continue;
633
634 if (cur->opt.prefixlen == p->opt.prefixlen) {
635 found = cur;
636 break;
637 }
638
639 return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
640 "IPv6 prefix %s conflicts with %s, ignoring.",
641 addr_p,
642 IN6_ADDR_PREFIX_TO_STRING(&cur->opt.in6_addr, cur->opt.prefixlen));
643 }
644
645 if (found) {
646 /* p and cur may be equivalent. First increment the reference counter. */
647 sd_radv_prefix_ref(p);
648
649 /* Then, remove the old entry. */
650 LIST_REMOVE(prefix, ra->prefixes, found);
651 sd_radv_prefix_unref(found);
652
653 /* Finally, add the new entry. */
654 LIST_APPEND(prefix, ra->prefixes, p);
655
656 log_radv(ra, "Updated/replaced IPv6 prefix %s (preferred: %s, valid: %s)",
657 addr_p,
658 FORMAT_TIMESPAN(p->lifetime_preferred_usec, USEC_PER_SEC),
659 FORMAT_TIMESPAN(p->lifetime_valid_usec, USEC_PER_SEC));
660 } else {
661 /* The prefix is new. Let's simply add it. */
662
663 sd_radv_prefix_ref(p);
664 LIST_APPEND(prefix, ra->prefixes, p);
665 ra->n_prefixes++;
666
667 log_radv(ra, "Added prefix %s", addr_p);
668 }
669
670 if (ra->state == RADV_STATE_IDLE)
671 return 0;
672
673 if (ra->ra_sent == 0)
674 return 0;
675
676 /* If RAs have already been sent, send an RA immediately to announce the newly-added prefix */
677 r = radv_send(ra, NULL, ra->lifetime_usec);
678 if (r < 0)
679 log_radv_errno(ra, r, "Unable to send Router Advertisement for added prefix %s, ignoring: %m", addr_p);
680 else
681 log_radv(ra, "Sent Router Advertisement for added/updated prefix %s.", addr_p);
682
683 return 0;
684 }
685
686 void sd_radv_remove_prefix(
687 sd_radv *ra,
688 const struct in6_addr *prefix,
689 unsigned char prefixlen) {
690
691 if (!ra)
692 return;
693
694 if (!prefix)
695 return;
696
697 LIST_FOREACH(prefix, cur, ra->prefixes) {
698 if (prefixlen != cur->opt.prefixlen)
699 continue;
700
701 if (!in6_addr_equal(prefix, &cur->opt.in6_addr))
702 continue;
703
704 LIST_REMOVE(prefix, ra->prefixes, cur);
705 ra->n_prefixes--;
706 sd_radv_prefix_unref(cur);
707 return;
708 }
709 }
710
711 int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p) {
712 sd_radv_route_prefix *found = NULL;
713 int r;
714
715 assert_return(ra, -EINVAL);
716 assert_return(p, -EINVAL);
717
718 const char *addr_p = IN6_ADDR_PREFIX_TO_STRING(&p->opt.in6_addr, p->opt.prefixlen);
719
720 LIST_FOREACH(prefix, cur, ra->route_prefixes) {
721 r = in_addr_prefix_intersect(AF_INET6,
722 (const union in_addr_union*) &cur->opt.in6_addr,
723 cur->opt.prefixlen,
724 (const union in_addr_union*) &p->opt.in6_addr,
725 p->opt.prefixlen);
726 if (r < 0)
727 return r;
728 if (r == 0)
729 continue;
730
731 if (cur->opt.prefixlen == p->opt.prefixlen) {
732 found = cur;
733 break;
734 }
735
736 return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
737 "IPv6 route prefix %s conflicts with %s, ignoring.",
738 addr_p,
739 IN6_ADDR_PREFIX_TO_STRING(&cur->opt.in6_addr, cur->opt.prefixlen));
740 }
741
742 if (found) {
743 /* p and cur may be equivalent. First increment the reference counter. */
744 sd_radv_route_prefix_ref(p);
745
746 /* Then, remove the old entry. */
747 LIST_REMOVE(prefix, ra->route_prefixes, found);
748 sd_radv_route_prefix_unref(found);
749
750 /* Finally, add the new entry. */
751 LIST_APPEND(prefix, ra->route_prefixes, p);
752
753 log_radv(ra, "Updated/replaced IPv6 route prefix %s (lifetime: %s)",
754 strna(addr_p),
755 FORMAT_TIMESPAN(p->lifetime_usec, USEC_PER_SEC));
756 } else {
757 /* The route prefix is new. Let's simply add it. */
758
759 sd_radv_route_prefix_ref(p);
760 LIST_APPEND(prefix, ra->route_prefixes, p);
761 ra->n_route_prefixes++;
762
763 log_radv(ra, "Added route prefix %s", strna(addr_p));
764 }
765
766 if (ra->state == RADV_STATE_IDLE)
767 return 0;
768
769 if (ra->ra_sent == 0)
770 return 0;
771
772 /* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */
773 r = radv_send(ra, NULL, ra->lifetime_usec);
774 if (r < 0)
775 log_radv_errno(ra, r, "Unable to send Router Advertisement for added route prefix %s, ignoring: %m",
776 strna(addr_p));
777 else
778 log_radv(ra, "Sent Router Advertisement for added route prefix %s.", strna(addr_p));
779
780 return 0;
781 }
782
783 int sd_radv_add_pref64_prefix(sd_radv *ra, sd_radv_pref64_prefix *p) {
784 sd_radv_pref64_prefix *found = NULL;
785 int r;
786
787 assert_return(ra, -EINVAL);
788 assert_return(p, -EINVAL);
789
790 const char *addr_p = IN6_ADDR_PREFIX_TO_STRING(&p->in6_addr, p->prefixlen);
791
792 LIST_FOREACH(prefix, cur, ra->pref64_prefixes) {
793 r = in_addr_prefix_intersect(AF_INET6,
794 (const union in_addr_union*) &cur->in6_addr,
795 cur->prefixlen,
796 (const union in_addr_union*) &p->in6_addr,
797 p->prefixlen);
798 if (r < 0)
799 return r;
800 if (r == 0)
801 continue;
802
803 if (cur->prefixlen == p->prefixlen) {
804 found = cur;
805 break;
806 }
807
808 return log_radv_errno(ra, SYNTHETIC_ERRNO(EEXIST),
809 "IPv6 PREF64 prefix %s conflicts with %s, ignoring.",
810 addr_p,
811 IN6_ADDR_PREFIX_TO_STRING(&cur->in6_addr, cur->prefixlen));
812 }
813
814 if (found) {
815 /* p and cur may be equivalent. First increment the reference counter. */
816 sd_radv_pref64_prefix_ref(p);
817
818 /* Then, remove the old entry. */
819 LIST_REMOVE(prefix, ra->pref64_prefixes, found);
820 sd_radv_pref64_prefix_unref(found);
821
822 /* Finally, add the new entry. */
823 LIST_APPEND(prefix, ra->pref64_prefixes, p);
824
825 log_radv(ra, "Updated/replaced IPv6 PREF64 prefix %s (lifetime: %s)",
826 strna(addr_p),
827 FORMAT_TIMESPAN(p->lifetime_usec, USEC_PER_SEC));
828 } else {
829 /* The route prefix is new. Let's simply add it. */
830
831 sd_radv_pref64_prefix_ref(p);
832 LIST_APPEND(prefix, ra->pref64_prefixes, p);
833 ra->n_pref64_prefixes++;
834
835 log_radv(ra, "Added PREF64 prefix %s", strna(addr_p));
836 }
837
838 if (ra->state == RADV_STATE_IDLE)
839 return 0;
840
841 if (ra->ra_sent == 0)
842 return 0;
843
844 /* If RAs have already been sent, send an RA immediately to announce the newly-added route prefix */
845 r = radv_send(ra, NULL, ra->lifetime_usec);
846 if (r < 0)
847 log_radv_errno(ra, r, "Unable to send Router Advertisement for added PREF64 prefix %s, ignoring: %m",
848 strna(addr_p));
849 else
850 log_radv(ra, "Sent Router Advertisement for added PREF64 prefix %s.", strna(addr_p));
851
852 return 0;
853 }
854
855 int sd_radv_set_rdnss(
856 sd_radv *ra,
857 uint64_t lifetime_usec,
858 const struct in6_addr *dns,
859 size_t n_dns) {
860
861 _cleanup_free_ struct sd_radv_opt_dns *opt_rdnss = NULL;
862 size_t len;
863
864 assert_return(ra, -EINVAL);
865 assert_return(n_dns < 128, -EINVAL);
866
867 if (lifetime_usec > RADV_RDNSS_MAX_LIFETIME_USEC)
868 return -EINVAL;
869
870 if (!dns || n_dns == 0) {
871 ra->rdnss = mfree(ra->rdnss);
872 ra->n_rdnss = 0;
873
874 return 0;
875 }
876
877 len = sizeof(struct sd_radv_opt_dns) + sizeof(struct in6_addr) * n_dns;
878
879 opt_rdnss = malloc0(len);
880 if (!opt_rdnss)
881 return -ENOMEM;
882
883 opt_rdnss->type = RADV_OPT_RDNSS;
884 opt_rdnss->length = len / 8;
885 opt_rdnss->lifetime = usec_to_be32_sec(lifetime_usec);
886
887 memcpy(opt_rdnss + 1, dns, n_dns * sizeof(struct in6_addr));
888
889 free_and_replace(ra->rdnss, opt_rdnss);
890
891 ra->n_rdnss = n_dns;
892
893 return 0;
894 }
895
896 int sd_radv_set_dnssl(
897 sd_radv *ra,
898 uint64_t lifetime_usec,
899 char **search_list) {
900
901 _cleanup_free_ struct sd_radv_opt_dns *opt_dnssl = NULL;
902 size_t len = 0;
903 uint8_t *p;
904
905 assert_return(ra, -EINVAL);
906
907 if (lifetime_usec > RADV_DNSSL_MAX_LIFETIME_USEC)
908 return -EINVAL;
909
910 if (strv_isempty(search_list)) {
911 ra->dnssl = mfree(ra->dnssl);
912 return 0;
913 }
914
915 STRV_FOREACH(s, search_list)
916 len += strlen(*s) + 2;
917
918 len = (sizeof(struct sd_radv_opt_dns) + len + 7) & ~0x7;
919
920 opt_dnssl = malloc0(len);
921 if (!opt_dnssl)
922 return -ENOMEM;
923
924 opt_dnssl->type = RADV_OPT_DNSSL;
925 opt_dnssl->length = len / 8;
926 opt_dnssl->lifetime = usec_to_be32_sec(lifetime_usec);
927
928 p = (uint8_t *)(opt_dnssl + 1);
929 len -= sizeof(struct sd_radv_opt_dns);
930
931 STRV_FOREACH(s, search_list) {
932 int r;
933
934 r = dns_name_to_wire_format(*s, p, len, false);
935 if (r < 0)
936 return r;
937
938 if (len < (size_t)r)
939 return -ENOBUFS;
940
941 p += r;
942 len -= r;
943 }
944
945 free_and_replace(ra->dnssl, opt_dnssl);
946
947 return 0;
948 }
949
950 int sd_radv_prefix_new(sd_radv_prefix **ret) {
951 sd_radv_prefix *p;
952
953 assert_return(ret, -EINVAL);
954
955 p = new(sd_radv_prefix, 1);
956 if (!p)
957 return -ENOMEM;
958
959 *p = (sd_radv_prefix) {
960 .n_ref = 1,
961
962 .opt.type = ND_OPT_PREFIX_INFORMATION,
963 .opt.length = (sizeof(p->opt) - 1)/8 + 1,
964 .opt.prefixlen = 64,
965
966 /* RFC 4861, Section 6.2.1 */
967 .opt.flags = ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO,
968
969 .lifetime_valid_usec = RADV_DEFAULT_VALID_LIFETIME_USEC,
970 .lifetime_preferred_usec = RADV_DEFAULT_PREFERRED_LIFETIME_USEC,
971 .valid_until = USEC_INFINITY,
972 .preferred_until = USEC_INFINITY,
973 };
974
975 *ret = p;
976 return 0;
977 }
978
979 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_prefix, sd_radv_prefix, mfree);
980
981 int sd_radv_prefix_set_prefix(
982 sd_radv_prefix *p,
983 const struct in6_addr *in6_addr,
984 unsigned char prefixlen) {
985
986 assert_return(p, -EINVAL);
987 assert_return(in6_addr, -EINVAL);
988
989 if (prefixlen < 3 || prefixlen > 128)
990 return -EINVAL;
991
992 if (prefixlen > 64)
993 /* unusual but allowed, log it */
994 log_radv(NULL, "Unusual prefix length %d greater than 64", prefixlen);
995
996 p->opt.in6_addr = *in6_addr;
997 p->opt.prefixlen = prefixlen;
998
999 return 0;
1000 }
1001
1002 int sd_radv_prefix_get_prefix(
1003 sd_radv_prefix *p,
1004 struct in6_addr *ret_in6_addr,
1005 unsigned char *ret_prefixlen) {
1006
1007 assert_return(p, -EINVAL);
1008 assert_return(ret_in6_addr, -EINVAL);
1009 assert_return(ret_prefixlen, -EINVAL);
1010
1011 *ret_in6_addr = p->opt.in6_addr;
1012 *ret_prefixlen = p->opt.prefixlen;
1013
1014 return 0;
1015 }
1016
1017 int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink) {
1018 assert_return(p, -EINVAL);
1019
1020 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, onlink);
1021
1022 return 0;
1023 }
1024
1025 int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p, int address_autoconfiguration) {
1026 assert_return(p, -EINVAL);
1027
1028 SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, address_autoconfiguration);
1029
1030 return 0;
1031 }
1032
1033 int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p, uint64_t lifetime_usec, uint64_t valid_until) {
1034 assert_return(p, -EINVAL);
1035
1036 p->lifetime_valid_usec = lifetime_usec;
1037 p->valid_until = valid_until;
1038
1039 return 0;
1040 }
1041
1042 int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, uint64_t lifetime_usec, uint64_t valid_until) {
1043 assert_return(p, -EINVAL);
1044
1045 p->lifetime_preferred_usec = lifetime_usec;
1046 p->preferred_until = valid_until;
1047
1048 return 0;
1049 }
1050
1051 int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) {
1052 sd_radv_route_prefix *p;
1053
1054 assert_return(ret, -EINVAL);
1055
1056 p = new(sd_radv_route_prefix, 1);
1057 if (!p)
1058 return -ENOMEM;
1059
1060 *p = (sd_radv_route_prefix) {
1061 .n_ref = 1,
1062
1063 .opt.type = RADV_OPT_ROUTE_INFORMATION,
1064 .opt.length = DIV_ROUND_UP(sizeof(p->opt), 8),
1065 .opt.prefixlen = 64,
1066
1067 .lifetime_usec = RADV_DEFAULT_VALID_LIFETIME_USEC,
1068 .valid_until = USEC_INFINITY,
1069 };
1070
1071 *ret = p;
1072 return 0;
1073 }
1074
1075 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix, sd_radv_route_prefix, mfree);
1076
1077 int sd_radv_route_prefix_set_prefix(
1078 sd_radv_route_prefix *p,
1079 const struct in6_addr *in6_addr,
1080 unsigned char prefixlen) {
1081
1082 assert_return(p, -EINVAL);
1083 assert_return(in6_addr, -EINVAL);
1084
1085 if (prefixlen > 128)
1086 return -EINVAL;
1087
1088 if (prefixlen > 64)
1089 /* unusual but allowed, log it */
1090 log_radv(NULL, "Unusual prefix length %u greater than 64", prefixlen);
1091
1092 p->opt.in6_addr = *in6_addr;
1093 p->opt.prefixlen = prefixlen;
1094
1095 return 0;
1096 }
1097
1098 int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint64_t lifetime_usec, uint64_t valid_until) {
1099 assert_return(p, -EINVAL);
1100
1101 p->lifetime_usec = lifetime_usec;
1102 p->valid_until = valid_until;
1103
1104 return 0;
1105 }
1106
1107 int sd_radv_pref64_prefix_new(sd_radv_pref64_prefix **ret) {
1108 sd_radv_pref64_prefix *p;
1109
1110 assert_return(ret, -EINVAL);
1111
1112 p = new(sd_radv_pref64_prefix, 1);
1113 if (!p)
1114 return -ENOMEM;
1115
1116 *p = (sd_radv_pref64_prefix) {
1117 .n_ref = 1,
1118
1119 .opt.type = RADV_OPT_PREF64,
1120 .opt.length = 2,
1121 };
1122
1123 *ret = p;
1124 return 0;
1125 }
1126
1127 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_pref64_prefix, sd_radv_pref64_prefix, mfree);
1128
1129 int sd_radv_pref64_prefix_set_prefix(
1130 sd_radv_pref64_prefix *p,
1131 const struct in6_addr *prefix,
1132 uint8_t prefixlen,
1133 uint64_t lifetime_usec) {
1134
1135 uint16_t pref64_lifetime;
1136 uint8_t prefixlen_code;
1137 int r;
1138
1139 assert_return(p, -EINVAL);
1140 assert_return(prefix, -EINVAL);
1141
1142 r = pref64_prefix_length_to_plc(prefixlen, &prefixlen_code);
1143 if (r < 0)
1144 return log_radv_errno(NULL, r,
1145 "Unsupported PREF64 prefix length %u. Valid lengths are 32, 40, 48, 56, 64 and 96", prefixlen);
1146
1147 if (lifetime_usec > PREF64_MAX_LIFETIME_USEC)
1148 return -EINVAL;
1149
1150 /* RFC 8781 - 4.1 rounding up lifetime to multiply of 8 */
1151 pref64_lifetime = DIV_ROUND_UP(lifetime_usec, 8 * USEC_PER_SEC) << 3;
1152 pref64_lifetime |= prefixlen_code;
1153
1154 unaligned_write_be16(&p->opt.lifetime_and_plc, pref64_lifetime);
1155 memcpy(&p->opt.prefix, prefix, sizeof(p->opt.prefix));
1156
1157 p->in6_addr = *prefix;
1158 p->prefixlen = prefixlen;
1159
1160 return 0;
1161 }