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 sd_dhcp6_lease_get_server_address(sd_dhcp6_lease
*lease
, struct in6_addr
*ret
) {
28 assert_return(lease
, -EINVAL
);
29 assert_return(ret
, -EINVAL
);
31 *ret
= lease
->server_address
;
35 int dhcp6_lease_ia_rebind_expire(const DHCP6IA
*ia
, uint32_t *expire
) {
37 uint32_t valid
= 0, t
;
42 LIST_FOREACH(addresses
, addr
, ia
->addresses
) {
43 t
= be32toh(addr
->iaaddr
.lifetime_valid
);
48 t
= be32toh(ia
->header
.lifetime_t2
);
57 void dhcp6_ia_clear_addresses(DHCP6IA
*ia
) {
62 LIST_FOREACH_SAFE(addresses
, a
, n
, ia
->addresses
)
68 DHCP6IA
*dhcp6_ia_free(DHCP6IA
*ia
) {
72 dhcp6_ia_clear_addresses(ia
);
77 int dhcp6_lease_set_clientid(sd_dhcp6_lease
*lease
, const uint8_t *id
, size_t len
) {
78 uint8_t *clientid
= NULL
;
81 assert(id
|| len
== 0);
84 clientid
= memdup(id
, len
);
89 free_and_replace(lease
->clientid
, clientid
);
90 lease
->clientid_len
= len
;
95 int dhcp6_lease_get_clientid(sd_dhcp6_lease
*lease
, uint8_t **ret_id
, size_t *ret_len
) {
102 *ret_id
= lease
->clientid
;
104 *ret_len
= lease
->clientid_len
;
109 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
, size_t len
) {
110 uint8_t *serverid
= NULL
;
113 assert(id
|| len
== 0);
116 serverid
= memdup(id
, len
);
121 free_and_replace(lease
->serverid
, serverid
);
122 lease
->serverid_len
= len
;
127 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **ret_id
, size_t *ret_len
) {
130 if (!lease
->serverid
)
134 *ret_id
= lease
->serverid
;
136 *ret_len
= lease
->serverid_len
;
140 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
143 lease
->preference
= preference
;
147 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *ret
) {
151 *ret
= lease
->preference
;
155 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
158 lease
->rapid_commit
= true;
162 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *ret
) {
166 *ret
= lease
->rapid_commit
;
170 int sd_dhcp6_lease_get_address(
171 sd_dhcp6_lease
*lease
,
172 struct in6_addr
*ret_addr
,
173 uint32_t *ret_lifetime_preferred
,
174 uint32_t *ret_lifetime_valid
) {
176 assert_return(lease
, -EINVAL
);
178 if (!lease
->addr_iter
)
182 *ret_addr
= lease
->addr_iter
->iaaddr
.address
;
183 if (ret_lifetime_preferred
)
184 *ret_lifetime_preferred
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
185 if (ret_lifetime_valid
)
186 *ret_lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
188 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
192 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
194 lease
->addr_iter
= lease
->ia_na
? lease
->ia_na
->addresses
: NULL
;
197 int sd_dhcp6_lease_get_pd(
198 sd_dhcp6_lease
*lease
,
199 struct in6_addr
*ret_prefix
,
200 uint8_t *ret_prefix_len
,
201 uint32_t *ret_lifetime_preferred
,
202 uint32_t *ret_lifetime_valid
) {
204 assert_return(lease
, -EINVAL
);
206 if (!lease
->prefix_iter
)
210 *ret_prefix
= lease
->prefix_iter
->iapdprefix
.address
;
212 *ret_prefix_len
= lease
->prefix_iter
->iapdprefix
.prefixlen
;
213 if (ret_lifetime_preferred
)
214 *ret_lifetime_preferred
= be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_preferred
);
215 if (ret_lifetime_valid
)
216 *ret_lifetime_valid
= be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_valid
);
218 lease
->prefix_iter
= lease
->prefix_iter
->addresses_next
;
222 void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease
*lease
) {
224 lease
->prefix_iter
= lease
->ia_pd
? lease
->ia_pd
->addresses
: NULL
;
227 int dhcp6_lease_add_dns(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
229 assert(optval
|| optlen
== 0);
234 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->dns
, &lease
->dns_count
);
237 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
238 assert_return(lease
, -EINVAL
);
246 return lease
->dns_count
;
249 int dhcp6_lease_add_domains(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
250 _cleanup_strv_free_
char **domains
= NULL
;
254 assert(optval
|| optlen
== 0);
259 r
= dhcp6_option_parse_domainname_list(optval
, optlen
, &domains
);
263 return strv_extend_strv(&lease
->domains
, domains
, true);
266 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***ret
) {
267 assert_return(lease
, -EINVAL
);
268 assert_return(ret
, -EINVAL
);
273 *ret
= lease
->domains
;
274 return strv_length(lease
->domains
);
277 int dhcp6_lease_add_ntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
281 assert(optval
|| optlen
== 0);
283 for (size_t offset
= 0; offset
< optlen
;) {
284 const uint8_t *subval
;
288 r
= dhcp6_option_parse(optval
, optlen
, &offset
, &subopt
, &sublen
, &subval
);
293 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
294 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
298 r
= dhcp6_option_parse_addresses(subval
, sublen
, &lease
->ntp
, &lease
->ntp_count
);
304 case DHCP6_NTP_SUBOPTION_SRV_FQDN
: {
305 _cleanup_free_
char *server
= NULL
;
307 r
= dhcp6_option_parse_domainname(subval
, sublen
, &server
);
311 if (strv_contains(lease
->ntp_fqdn
, server
))
314 r
= strv_consume(&lease
->ntp_fqdn
, TAKE_PTR(server
));
325 int dhcp6_lease_add_sntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
327 assert(optval
|| optlen
== 0);
332 /* SNTP option is defined in RFC4075, and deprecated by RFC5908. */
333 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->sntp
, &lease
->sntp_count
);
336 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
337 assert_return(lease
, -EINVAL
);
342 return lease
->ntp_count
;
345 if (lease
->sntp
&& !lease
->ntp_fqdn
) {
346 /* Fallback to the deprecated SNTP option. */
349 return lease
->sntp_count
;
355 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ret
) {
356 assert_return(lease
, -EINVAL
);
358 if (!lease
->ntp_fqdn
)
362 *ret
= lease
->ntp_fqdn
;
363 return strv_length(lease
->ntp_fqdn
);
366 int dhcp6_lease_set_fqdn(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
371 assert(optval
|| optlen
== 0);
379 /* Ignore the flags field, it doesn't carry any useful
380 information for clients. */
381 r
= dhcp6_option_parse_domainname(optval
+ 1, optlen
- 1, &fqdn
);
385 return free_and_replace(lease
->fqdn
, fqdn
);
388 int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease
*lease
, const char **ret
) {
389 assert_return(lease
, -EINVAL
);
390 assert_return(ret
, -EINVAL
);
399 static sd_dhcp6_lease
*dhcp6_lease_free(sd_dhcp6_lease
*lease
) {
403 free(lease
->clientid
);
404 free(lease
->serverid
);
405 dhcp6_ia_free(lease
->ia_na
);
406 dhcp6_ia_free(lease
->ia_pd
);
409 strv_free(lease
->domains
);
411 strv_free(lease
->ntp_fqdn
);
417 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease
, sd_dhcp6_lease
, dhcp6_lease_free
);
419 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
420 sd_dhcp6_lease
*lease
;
424 lease
= new0(sd_dhcp6_lease
, 1);