1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014-2015 Intel Corporation. All rights reserved.
8 #include "alloc-util.h"
9 #include "dhcp6-lease-internal.h"
10 #include "dhcp6-protocol.h"
14 int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease
*lease
, clockid_t clock
, uint64_t *ret
) {
15 assert_return(lease
, -EINVAL
);
16 assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock
), -EOPNOTSUPP
);
17 assert_return(clock_supported(clock
), -EOPNOTSUPP
);
18 assert_return(ret
, -EINVAL
);
20 if (!triple_timestamp_is_set(&lease
->timestamp
))
23 *ret
= triple_timestamp_by_clock(&lease
->timestamp
, clock
);
27 int dhcp6_lease_ia_rebind_expire(const DHCP6IA
*ia
, uint32_t *expire
) {
29 uint32_t valid
= 0, t
;
31 assert_return(ia
, -EINVAL
);
32 assert_return(expire
, -EINVAL
);
34 LIST_FOREACH(addresses
, addr
, ia
->addresses
) {
35 t
= be32toh(addr
->iaaddr
.lifetime_valid
);
40 t
= be32toh(ia
->ia_na
.lifetime_t2
);
49 DHCP6IA
*dhcp6_lease_free_ia(DHCP6IA
*ia
) {
50 DHCP6Address
*address
;
55 while (ia
->addresses
) {
56 address
= ia
->addresses
;
58 LIST_REMOVE(addresses
, ia
->addresses
, address
);
66 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
,
70 assert_return(lease
, -EINVAL
);
71 assert_return(id
, -EINVAL
);
73 serverid
= memdup(id
, len
);
77 free_and_replace(lease
->serverid
, serverid
);
78 lease
->serverid_len
= len
;
83 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **id
, size_t *len
) {
84 assert_return(lease
, -EINVAL
);
90 *id
= lease
->serverid
;
92 *len
= lease
->serverid_len
;
97 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
98 assert_return(lease
, -EINVAL
);
100 lease
->preference
= preference
;
105 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *preference
) {
106 assert_return(preference
, -EINVAL
);
111 *preference
= lease
->preference
;
116 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
117 assert_return(lease
, -EINVAL
);
119 lease
->rapid_commit
= true;
124 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *rapid_commit
) {
125 assert_return(lease
, -EINVAL
);
126 assert_return(rapid_commit
, -EINVAL
);
128 *rapid_commit
= lease
->rapid_commit
;
133 int sd_dhcp6_lease_get_address(sd_dhcp6_lease
*lease
, struct in6_addr
*addr
,
134 uint32_t *lifetime_preferred
,
135 uint32_t *lifetime_valid
) {
136 assert_return(lease
, -EINVAL
);
137 assert_return(addr
, -EINVAL
);
138 assert_return(lifetime_preferred
, -EINVAL
);
139 assert_return(lifetime_valid
, -EINVAL
);
141 if (!lease
->addr_iter
)
144 memcpy(addr
, &lease
->addr_iter
->iaaddr
.address
,
145 sizeof(struct in6_addr
));
146 *lifetime_preferred
=
147 be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
148 *lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
150 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
155 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
157 lease
->addr_iter
= lease
->ia
.addresses
;
160 int sd_dhcp6_lease_get_pd(sd_dhcp6_lease
*lease
, struct in6_addr
*prefix
,
162 uint32_t *lifetime_preferred
,
163 uint32_t *lifetime_valid
) {
164 assert_return(lease
, -EINVAL
);
165 assert_return(prefix
, -EINVAL
);
166 assert_return(prefix_len
, -EINVAL
);
167 assert_return(lifetime_preferred
, -EINVAL
);
168 assert_return(lifetime_valid
, -EINVAL
);
170 if (!lease
->prefix_iter
)
173 memcpy(prefix
, &lease
->prefix_iter
->iapdprefix
.address
,
174 sizeof(struct in6_addr
));
175 *prefix_len
= lease
->prefix_iter
->iapdprefix
.prefixlen
;
176 *lifetime_preferred
=
177 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_preferred
);
179 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_valid
);
181 lease
->prefix_iter
= lease
->prefix_iter
->addresses_next
;
186 void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease
*lease
) {
188 lease
->prefix_iter
= lease
->pd
.addresses
;
191 int dhcp6_lease_add_dns(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
192 assert_return(lease
, -EINVAL
);
193 assert_return(optval
, -EINVAL
);
198 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->dns
, &lease
->dns_count
);
201 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
202 assert_return(lease
, -EINVAL
);
203 assert_return(ret
, -EINVAL
);
209 return lease
->dns_count
;
212 int dhcp6_lease_add_domains(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
213 _cleanup_strv_free_
char **domains
= NULL
;
216 assert_return(lease
, -EINVAL
);
217 assert_return(optval
, -EINVAL
);
222 r
= dhcp6_option_parse_domainname_list(optval
, optlen
, &domains
);
226 return strv_extend_strv(&lease
->domains
, domains
, true);
229 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***ret
) {
230 assert_return(lease
, -EINVAL
);
231 assert_return(ret
, -EINVAL
);
236 *ret
= lease
->domains
;
237 return strv_length(lease
->domains
);
240 int dhcp6_lease_add_ntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
243 assert_return(lease
, -EINVAL
);
244 assert_return(optval
, -EINVAL
);
246 for (size_t offset
= 0; offset
< optlen
;) {
247 const uint8_t *subval
;
251 r
= dhcp6_option_parse(optval
, optlen
, &offset
, &subopt
, &sublen
, &subval
);
256 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
257 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
261 r
= dhcp6_option_parse_addresses(subval
, sublen
, &lease
->ntp
, &lease
->ntp_count
);
267 case DHCP6_NTP_SUBOPTION_SRV_FQDN
: {
268 _cleanup_free_
char *server
= NULL
;
270 r
= dhcp6_option_parse_domainname(subval
, sublen
, &server
);
274 if (strv_contains(lease
->ntp_fqdn
, server
))
277 r
= strv_consume(&lease
->ntp_fqdn
, TAKE_PTR(server
));
288 int dhcp6_lease_add_sntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
289 assert_return(lease
, -EINVAL
);
290 assert_return(optval
, -EINVAL
);
295 /* SNTP option is defined in RFC4075, and deprecated by RFC5908. */
296 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->sntp
, &lease
->sntp_count
);
299 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
300 assert_return(lease
, -EINVAL
);
301 assert_return(ret
, -EINVAL
);
305 return lease
->ntp_count
;
308 if (lease
->sntp
&& !lease
->ntp_fqdn
) {
309 /* Fallback to the deprecated SNTP option. */
311 return lease
->sntp_count
;
317 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ret
) {
318 assert_return(lease
, -EINVAL
);
319 assert_return(ret
, -EINVAL
);
321 if (!lease
->ntp_fqdn
)
324 *ret
= lease
->ntp_fqdn
;
325 return strv_length(lease
->ntp_fqdn
);
328 int dhcp6_lease_set_fqdn(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
332 assert_return(lease
, -EINVAL
);
333 assert_return(optval
, -EINVAL
);
338 /* Ignore the flags field, it doesn't carry any useful
339 information for clients. */
340 r
= dhcp6_option_parse_domainname(optval
+ 1, optlen
- 1, &fqdn
);
344 return free_and_replace(lease
->fqdn
, fqdn
);
347 int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease
*lease
, const char **ret
) {
348 assert_return(lease
, -EINVAL
);
349 assert_return(ret
, -EINVAL
);
358 static sd_dhcp6_lease
*dhcp6_lease_free(sd_dhcp6_lease
*lease
) {
362 free(lease
->serverid
);
363 dhcp6_lease_free_ia(&lease
->ia
);
364 dhcp6_lease_free_ia(&lease
->pd
);
367 strv_free(lease
->domains
);
369 strv_free(lease
->ntp_fqdn
);
375 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease
, sd_dhcp6_lease
, dhcp6_lease_free
);
377 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
378 sd_dhcp6_lease
*lease
;
380 lease
= new0(sd_dhcp6_lease
, 1);
386 LIST_HEAD_INIT(lease
->ia
.addresses
);