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