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
->ia_na
.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
) {
81 clientid
= memdup(id
, len
);
85 free_and_replace(lease
->clientid
, clientid
);
86 lease
->clientid_len
= len
;
91 int dhcp6_lease_get_clientid(sd_dhcp6_lease
*lease
, uint8_t **ret_id
, size_t *ret_len
) {
98 *ret_id
= lease
->clientid
;
100 *ret_len
= lease
->clientid_len
;
105 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
, size_t len
) {
112 serverid
= memdup(id
, len
);
116 free_and_replace(lease
->serverid
, serverid
);
117 lease
->serverid_len
= len
;
122 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **ret_id
, size_t *ret_len
) {
125 if (!lease
->serverid
)
129 *ret_id
= lease
->serverid
;
131 *ret_len
= lease
->serverid_len
;
135 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
138 lease
->preference
= preference
;
142 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *ret
) {
146 *ret
= lease
->preference
;
150 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
153 lease
->rapid_commit
= true;
157 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *ret
) {
161 *ret
= lease
->rapid_commit
;
165 int sd_dhcp6_lease_get_address(
166 sd_dhcp6_lease
*lease
,
167 struct in6_addr
*ret_addr
,
168 uint32_t *ret_lifetime_preferred
,
169 uint32_t *ret_lifetime_valid
) {
171 assert_return(lease
, -EINVAL
);
173 if (!lease
->addr_iter
)
177 *ret_addr
= lease
->addr_iter
->iaaddr
.address
;
178 if (ret_lifetime_preferred
)
179 *ret_lifetime_preferred
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
180 if (ret_lifetime_valid
)
181 *ret_lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
183 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
187 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
189 lease
->addr_iter
= lease
->ia_na
.addresses
;
192 int sd_dhcp6_lease_get_pd(
193 sd_dhcp6_lease
*lease
,
194 struct in6_addr
*ret_prefix
,
195 uint8_t *ret_prefix_len
,
196 uint32_t *ret_lifetime_preferred
,
197 uint32_t *ret_lifetime_valid
) {
199 assert_return(lease
, -EINVAL
);
201 if (!lease
->prefix_iter
)
205 *ret_prefix
= lease
->prefix_iter
->iapdprefix
.address
;
207 *ret_prefix_len
= lease
->prefix_iter
->iapdprefix
.prefixlen
;
208 if (ret_lifetime_preferred
)
209 *ret_lifetime_preferred
= be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_preferred
);
210 if (ret_lifetime_valid
)
211 *ret_lifetime_valid
= be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_valid
);
213 lease
->prefix_iter
= lease
->prefix_iter
->addresses_next
;
217 void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease
*lease
) {
219 lease
->prefix_iter
= lease
->ia_pd
.addresses
;
222 int dhcp6_lease_add_dns(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
224 assert(optval
|| optlen
== 0);
229 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->dns
, &lease
->dns_count
);
232 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
233 assert_return(lease
, -EINVAL
);
241 return lease
->dns_count
;
244 int dhcp6_lease_add_domains(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
245 _cleanup_strv_free_
char **domains
= NULL
;
249 assert(optval
|| optlen
== 0);
254 r
= dhcp6_option_parse_domainname_list(optval
, optlen
, &domains
);
258 return strv_extend_strv(&lease
->domains
, domains
, true);
261 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***ret
) {
262 assert_return(lease
, -EINVAL
);
263 assert_return(ret
, -EINVAL
);
268 *ret
= lease
->domains
;
269 return strv_length(lease
->domains
);
272 int dhcp6_lease_add_ntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
276 assert(optval
|| optlen
== 0);
278 for (size_t offset
= 0; offset
< optlen
;) {
279 const uint8_t *subval
;
283 r
= dhcp6_option_parse(optval
, optlen
, &offset
, &subopt
, &sublen
, &subval
);
288 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
289 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
293 r
= dhcp6_option_parse_addresses(subval
, sublen
, &lease
->ntp
, &lease
->ntp_count
);
299 case DHCP6_NTP_SUBOPTION_SRV_FQDN
: {
300 _cleanup_free_
char *server
= NULL
;
302 r
= dhcp6_option_parse_domainname(subval
, sublen
, &server
);
306 if (strv_contains(lease
->ntp_fqdn
, server
))
309 r
= strv_consume(&lease
->ntp_fqdn
, TAKE_PTR(server
));
320 int dhcp6_lease_add_sntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
322 assert(optval
|| optlen
== 0);
327 /* SNTP option is defined in RFC4075, and deprecated by RFC5908. */
328 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->sntp
, &lease
->sntp_count
);
331 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
332 assert_return(lease
, -EINVAL
);
337 return lease
->ntp_count
;
340 if (lease
->sntp
&& !lease
->ntp_fqdn
) {
341 /* Fallback to the deprecated SNTP option. */
344 return lease
->sntp_count
;
350 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ret
) {
351 assert_return(lease
, -EINVAL
);
353 if (!lease
->ntp_fqdn
)
357 *ret
= lease
->ntp_fqdn
;
358 return strv_length(lease
->ntp_fqdn
);
361 int dhcp6_lease_set_fqdn(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
366 assert(optval
|| optlen
== 0);
374 /* Ignore the flags field, it doesn't carry any useful
375 information for clients. */
376 r
= dhcp6_option_parse_domainname(optval
+ 1, optlen
- 1, &fqdn
);
380 return free_and_replace(lease
->fqdn
, fqdn
);
383 int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease
*lease
, const char **ret
) {
384 assert_return(lease
, -EINVAL
);
385 assert_return(ret
, -EINVAL
);
394 static sd_dhcp6_lease
*dhcp6_lease_free(sd_dhcp6_lease
*lease
) {
398 free(lease
->clientid
);
399 free(lease
->serverid
);
400 dhcp6_lease_free_ia(&lease
->ia_na
);
401 dhcp6_lease_free_ia(&lease
->ia_pd
);
404 strv_free(lease
->domains
);
406 strv_free(lease
->ntp_fqdn
);
412 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease
, sd_dhcp6_lease
, dhcp6_lease_free
);
414 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
415 sd_dhcp6_lease
*lease
;
419 lease
= new0(sd_dhcp6_lease
, 1);
425 LIST_HEAD_INIT(lease
->ia_na
.addresses
);