2 This file is part of systemd.
4 Copyright (C) 2017 Intel Corporation. All rights reserved.
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.
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.
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/>.
20 #include <netinet/icmp6.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
27 #include "alloc-util.h"
29 #include "icmp6-util.h"
30 #include "in-addr-util.h"
31 #include "radv-internal.h"
32 #include "socket-util.h"
33 #include "string-util.h"
36 _public_
int sd_radv_new(sd_radv
**ret
) {
37 _cleanup_(sd_radv_unrefp
) sd_radv
*ra
= NULL
;
39 assert_return(ret
, -EINVAL
);
41 ra
= new0(sd_radv
, 1);
47 LIST_HEAD_INIT(ra
->prefixes
);
55 _public_
int sd_radv_attach_event(sd_radv
*ra
, sd_event
*event
, int64_t priority
) {
58 assert_return(ra
, -EINVAL
);
59 assert_return(!ra
->event
, -EBUSY
);
62 ra
->event
= sd_event_ref(event
);
64 r
= sd_event_default(&ra
->event
);
69 ra
->event_priority
= priority
;
74 _public_
int sd_radv_detach_event(sd_radv
*ra
) {
76 assert_return(ra
, -EINVAL
);
78 ra
->event
= sd_event_unref(ra
->event
);
82 _public_ sd_event
*sd_radv_get_event(sd_radv
*ra
) {
83 assert_return(ra
, NULL
);
88 _public_ sd_radv
*sd_radv_ref(sd_radv
*ra
) {
92 assert(ra
->n_ref
> 0);
98 _public_ sd_radv
*sd_radv_unref(sd_radv
*ra
) {
102 assert(ra
->n_ref
> 0);
108 while (ra
->prefixes
) {
109 sd_radv_prefix
*p
= ra
->prefixes
;
111 LIST_REMOVE(prefix
, ra
->prefixes
, p
);
112 sd_radv_prefix_unref(p
);
115 sd_radv_detach_event(ra
);
119 _public_
int sd_radv_stop(sd_radv
*ra
) {
120 assert_return(ra
, -EINVAL
);
122 log_radv("Stopping IPv6 Router Advertisement daemon");
124 ra
->state
= SD_RADV_STATE_IDLE
;
129 _public_
int sd_radv_start(sd_radv
*ra
) {
130 assert_return(ra
, -EINVAL
);
131 assert_return(ra
->event
, -EINVAL
);
132 assert_return(ra
->ifindex
> 0, -EINVAL
);
134 if (ra
->state
!= SD_RADV_STATE_IDLE
)
137 ra
->state
= SD_RADV_STATE_ADVERTISING
;
139 log_radv("Started IPv6 Router Advertisement daemon");
144 _public_
int sd_radv_set_ifindex(sd_radv
*ra
, int ifindex
) {
145 assert_return(ra
, -EINVAL
);
146 assert_return(ifindex
>= -1, -EINVAL
);
148 if (ra
->state
!= SD_RADV_STATE_IDLE
)
151 ra
->ifindex
= ifindex
;
156 _public_
int sd_radv_set_mac(sd_radv
*ra
, const struct ether_addr
*mac_addr
) {
157 assert_return(ra
, -EINVAL
);
159 if (ra
->state
!= SD_RADV_STATE_IDLE
)
163 ra
->mac_addr
= *mac_addr
;
170 _public_
int sd_radv_set_mtu(sd_radv
*ra
, uint32_t mtu
) {
171 assert_return(ra
, -EINVAL
);
172 assert_return(mtu
>= 1280, -EINVAL
);
174 if (ra
->state
!= SD_RADV_STATE_IDLE
)
182 _public_
int sd_radv_set_hop_limit(sd_radv
*ra
, uint8_t hop_limit
) {
183 assert_return(ra
, -EINVAL
);
185 if (ra
->state
!= SD_RADV_STATE_IDLE
)
188 ra
->hop_limit
= hop_limit
;
193 _public_
int sd_radv_set_router_lifetime(sd_radv
*ra
, uint32_t router_lifetime
) {
194 assert_return(ra
, -EINVAL
);
196 if (ra
->state
!= SD_RADV_STATE_IDLE
)
199 /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the
200 preference value MUST be set to (00) by the sender..." */
201 if (router_lifetime
== 0 &&
202 (ra
->flags
& (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM
<< 3))
205 ra
->lifetime
= router_lifetime
;
210 _public_
int sd_radv_set_managed_information(sd_radv
*ra
, int managed
) {
211 assert_return(ra
, -EINVAL
);
213 if (ra
->state
!= SD_RADV_STATE_IDLE
)
216 SET_FLAG(ra
->flags
, ND_RA_FLAG_MANAGED
, managed
);
221 _public_
int sd_radv_set_other_information(sd_radv
*ra
, int other
) {
222 assert_return(ra
, -EINVAL
);
224 if (ra
->state
!= SD_RADV_STATE_IDLE
)
227 SET_FLAG(ra
->flags
, ND_RA_FLAG_OTHER
, other
);
232 _public_
int sd_radv_set_preference(sd_radv
*ra
, unsigned preference
) {
235 assert_return(ra
, -EINVAL
);
236 assert_return(IN_SET(preference
,
237 SD_NDISC_PREFERENCE_LOW
,
238 SD_NDISC_PREFERENCE_MEDIUM
,
239 SD_NDISC_PREFERENCE_HIGH
), -EINVAL
);
241 ra
->flags
= (ra
->flags
& ~(0x3 << 3)) | (preference
<< 3);
246 _public_
int sd_radv_add_prefix(sd_radv
*ra
, sd_radv_prefix
*p
) {
248 _cleanup_free_
char *addr_p
= NULL
;
250 assert_return(ra
, -EINVAL
);
255 LIST_FOREACH(prefix
, cur
, ra
->prefixes
) {
258 r
= in_addr_prefix_intersect(AF_INET6
,
259 (union in_addr_union
*) &cur
->opt
.in6_addr
,
261 (union in_addr_union
*) &p
->opt
.in6_addr
,
264 _cleanup_free_
char *addr_cur
= NULL
;
266 (void) in_addr_to_string(AF_INET6
,
267 (union in_addr_union
*) &cur
->opt
.in6_addr
,
269 (void) in_addr_to_string(AF_INET6
,
270 (union in_addr_union
*) &p
->opt
.in6_addr
,
273 log_radv("IPv6 prefix %s/%u already configured, ignoring %s/%u",
274 addr_cur
, cur
->opt
.prefixlen
,
275 addr_p
, p
->opt
.prefixlen
);
281 p
= sd_radv_prefix_ref(p
);
283 LIST_APPEND(prefix
, ra
->prefixes
, p
);
287 (void) in_addr_to_string(AF_INET6
, (union in_addr_union
*) &p
->opt
.in6_addr
, &addr_p
);
288 log_radv("Added prefix %s/%d", addr_p
, p
->opt
.prefixlen
);
293 _public_
int sd_radv_prefix_new(sd_radv_prefix
**ret
) {
294 _cleanup_(sd_radv_prefix_unrefp
) sd_radv_prefix
*p
= NULL
;
296 assert_return(ret
, -EINVAL
);
298 p
= new0(sd_radv_prefix
, 1);
304 p
->opt
.type
= ND_OPT_PREFIX_INFORMATION
;
305 p
->opt
.length
= (sizeof(p
->opt
) - 1) /8 + 1;
307 p
->opt
.prefixlen
= 64;
309 /* RFC 4861, Section 6.2.1 */
310 SET_FLAG(p
->opt
.flags
, ND_OPT_PI_FLAG_ONLINK
, true);
311 SET_FLAG(p
->opt
.flags
, ND_OPT_PI_FLAG_AUTO
, true);
312 p
->opt
.preferred_lifetime
= htobe32(604800);
313 p
->opt
.valid_lifetime
= htobe32(2592000);
315 LIST_INIT(prefix
, p
);
323 _public_ sd_radv_prefix
*sd_radv_prefix_ref(sd_radv_prefix
*p
) {
327 assert(p
->n_ref
> 0);
333 _public_ sd_radv_prefix
*sd_radv_prefix_unref(sd_radv_prefix
*p
) {
337 assert(p
->n_ref
> 0);
346 _public_
int sd_radv_prefix_set_prefix(sd_radv_prefix
*p
, struct in6_addr
*in6_addr
,
347 unsigned char prefixlen
) {
348 assert_return(p
, -EINVAL
);
349 assert_return(in6_addr
, -EINVAL
);
351 if (prefixlen
< 3 || prefixlen
> 128)
355 /* unusual but allowed, log it */
356 log_radv("Unusual prefix length %d greater than 64", prefixlen
);
358 p
->opt
.in6_addr
= *in6_addr
;
359 p
->opt
.prefixlen
= prefixlen
;
364 _public_
int sd_radv_prefix_set_onlink(sd_radv_prefix
*p
, int onlink
) {
365 assert_return(p
, -EINVAL
);
367 SET_FLAG(p
->opt
.flags
, ND_OPT_PI_FLAG_ONLINK
, onlink
);
372 _public_
int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix
*p
,
373 int address_autoconfiguration
) {
374 assert_return(p
, -EINVAL
);
376 SET_FLAG(p
->opt
.flags
, ND_OPT_PI_FLAG_AUTO
, address_autoconfiguration
);
381 _public_
int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix
*p
,
382 uint32_t valid_lifetime
) {
383 assert_return(p
, -EINVAL
);
385 p
->opt
.valid_lifetime
= htobe32(valid_lifetime
);
390 _public_
int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix
*p
,
391 uint32_t preferred_lifetime
) {
392 assert_return(p
, -EINVAL
);
394 p
->opt
.preferred_lifetime
= htobe32(preferred_lifetime
);