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 DHCP6IA
*dhcp6_lease_free_ia(DHCP6IA
*ia
) {
58 DHCP6Address
*address
;
63 while (ia
->addresses
) {
64 address
= ia
->addresses
;
66 LIST_REMOVE(addresses
, ia
->addresses
, address
);
74 int dhcp6_lease_set_clientid(sd_dhcp6_lease
*lease
, const uint8_t *id
, size_t len
) {
75 uint8_t *clientid
= NULL
;
78 assert(id
|| len
== 0);
81 clientid
= memdup(id
, len
);
86 free_and_replace(lease
->clientid
, clientid
);
87 lease
->clientid_len
= len
;
92 int dhcp6_lease_get_clientid(sd_dhcp6_lease
*lease
, uint8_t **ret_id
, size_t *ret_len
) {
99 *ret_id
= lease
->clientid
;
101 *ret_len
= lease
->clientid_len
;
106 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
, size_t len
) {
107 uint8_t *serverid
= NULL
;
110 assert(id
|| len
== 0);
113 serverid
= memdup(id
, len
);
118 free_and_replace(lease
->serverid
, serverid
);
119 lease
->serverid_len
= len
;
124 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **ret_id
, size_t *ret_len
) {
127 if (!lease
->serverid
)
131 *ret_id
= lease
->serverid
;
133 *ret_len
= lease
->serverid_len
;
137 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
140 lease
->preference
= preference
;
144 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *ret
) {
148 *ret
= lease
->preference
;
152 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
155 lease
->rapid_commit
= true;
159 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *ret
) {
163 *ret
= lease
->rapid_commit
;
167 int sd_dhcp6_lease_get_address(
168 sd_dhcp6_lease
*lease
,
169 struct in6_addr
*ret_addr
,
170 uint32_t *ret_lifetime_preferred
,
171 uint32_t *ret_lifetime_valid
) {
173 assert_return(lease
, -EINVAL
);
175 if (!lease
->addr_iter
)
179 *ret_addr
= lease
->addr_iter
->iaaddr
.address
;
180 if (ret_lifetime_preferred
)
181 *ret_lifetime_preferred
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
182 if (ret_lifetime_valid
)
183 *ret_lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
185 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
189 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
191 lease
->addr_iter
= lease
->ia_na
.addresses
;
194 int sd_dhcp6_lease_get_pd(
195 sd_dhcp6_lease
*lease
,
196 struct in6_addr
*ret_prefix
,
197 uint8_t *ret_prefix_len
,
198 uint32_t *ret_lifetime_preferred
,
199 uint32_t *ret_lifetime_valid
) {
201 assert_return(lease
, -EINVAL
);
203 if (!lease
->prefix_iter
)
207 *ret_prefix
= lease
->prefix_iter
->iapdprefix
.address
;
209 *ret_prefix_len
= lease
->prefix_iter
->iapdprefix
.prefixlen
;
210 if (ret_lifetime_preferred
)
211 *ret_lifetime_preferred
= be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_preferred
);
212 if (ret_lifetime_valid
)
213 *ret_lifetime_valid
= be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_valid
);
215 lease
->prefix_iter
= lease
->prefix_iter
->addresses_next
;
219 void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease
*lease
) {
221 lease
->prefix_iter
= lease
->ia_pd
.addresses
;
224 int dhcp6_lease_add_dns(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
226 assert(optval
|| optlen
== 0);
231 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->dns
, &lease
->dns_count
);
234 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
235 assert_return(lease
, -EINVAL
);
243 return lease
->dns_count
;
246 int dhcp6_lease_add_domains(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
247 _cleanup_strv_free_
char **domains
= NULL
;
251 assert(optval
|| optlen
== 0);
256 r
= dhcp6_option_parse_domainname_list(optval
, optlen
, &domains
);
260 return strv_extend_strv(&lease
->domains
, domains
, true);
263 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***ret
) {
264 assert_return(lease
, -EINVAL
);
265 assert_return(ret
, -EINVAL
);
270 *ret
= lease
->domains
;
271 return strv_length(lease
->domains
);
274 int dhcp6_lease_add_ntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
278 assert(optval
|| optlen
== 0);
280 for (size_t offset
= 0; offset
< optlen
;) {
281 const uint8_t *subval
;
285 r
= dhcp6_option_parse(optval
, optlen
, &offset
, &subopt
, &sublen
, &subval
);
290 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
291 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
295 r
= dhcp6_option_parse_addresses(subval
, sublen
, &lease
->ntp
, &lease
->ntp_count
);
301 case DHCP6_NTP_SUBOPTION_SRV_FQDN
: {
302 _cleanup_free_
char *server
= NULL
;
304 r
= dhcp6_option_parse_domainname(subval
, sublen
, &server
);
308 if (strv_contains(lease
->ntp_fqdn
, server
))
311 r
= strv_consume(&lease
->ntp_fqdn
, TAKE_PTR(server
));
322 int dhcp6_lease_add_sntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
324 assert(optval
|| optlen
== 0);
329 /* SNTP option is defined in RFC4075, and deprecated by RFC5908. */
330 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->sntp
, &lease
->sntp_count
);
333 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
334 assert_return(lease
, -EINVAL
);
339 return lease
->ntp_count
;
342 if (lease
->sntp
&& !lease
->ntp_fqdn
) {
343 /* Fallback to the deprecated SNTP option. */
346 return lease
->sntp_count
;
352 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ret
) {
353 assert_return(lease
, -EINVAL
);
355 if (!lease
->ntp_fqdn
)
359 *ret
= lease
->ntp_fqdn
;
360 return strv_length(lease
->ntp_fqdn
);
363 int dhcp6_lease_set_fqdn(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
368 assert(optval
|| optlen
== 0);
376 /* Ignore the flags field, it doesn't carry any useful
377 information for clients. */
378 r
= dhcp6_option_parse_domainname(optval
+ 1, optlen
- 1, &fqdn
);
382 return free_and_replace(lease
->fqdn
, fqdn
);
385 int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease
*lease
, const char **ret
) {
386 assert_return(lease
, -EINVAL
);
387 assert_return(ret
, -EINVAL
);
396 static sd_dhcp6_lease
*dhcp6_lease_free(sd_dhcp6_lease
*lease
) {
400 free(lease
->clientid
);
401 free(lease
->serverid
);
402 dhcp6_lease_free_ia(&lease
->ia_na
);
403 dhcp6_lease_free_ia(&lease
->ia_pd
);
406 strv_free(lease
->domains
);
408 strv_free(lease
->ntp_fqdn
);
414 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease
, sd_dhcp6_lease
, dhcp6_lease_free
);
416 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
417 sd_dhcp6_lease
*lease
;
421 lease
= new0(sd_dhcp6_lease
, 1);
427 LIST_HEAD_INIT(lease
->ia_na
.addresses
);