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 dhcp6_lease_ia_rebind_expire(const DHCP6IA
*ia
, uint32_t *expire
) {
16 uint32_t valid
= 0, t
;
18 assert_return(ia
, -EINVAL
);
19 assert_return(expire
, -EINVAL
);
21 LIST_FOREACH(addresses
, addr
, ia
->addresses
) {
22 t
= be32toh(addr
->iaaddr
.lifetime_valid
);
27 t
= be32toh(ia
->ia_na
.lifetime_t2
);
36 DHCP6IA
*dhcp6_lease_free_ia(DHCP6IA
*ia
) {
37 DHCP6Address
*address
;
42 while (ia
->addresses
) {
43 address
= ia
->addresses
;
45 LIST_REMOVE(addresses
, ia
->addresses
, address
);
53 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
,
57 assert_return(lease
, -EINVAL
);
58 assert_return(id
, -EINVAL
);
60 serverid
= memdup(id
, len
);
64 free_and_replace(lease
->serverid
, serverid
);
65 lease
->serverid_len
= len
;
70 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **id
, size_t *len
) {
71 assert_return(lease
, -EINVAL
);
77 *id
= lease
->serverid
;
79 *len
= lease
->serverid_len
;
84 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
85 assert_return(lease
, -EINVAL
);
87 lease
->preference
= preference
;
92 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *preference
) {
93 assert_return(preference
, -EINVAL
);
98 *preference
= lease
->preference
;
103 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
104 assert_return(lease
, -EINVAL
);
106 lease
->rapid_commit
= true;
111 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *rapid_commit
) {
112 assert_return(lease
, -EINVAL
);
113 assert_return(rapid_commit
, -EINVAL
);
115 *rapid_commit
= lease
->rapid_commit
;
120 int dhcp6_lease_get_iaid(sd_dhcp6_lease
*lease
, be32_t
*iaid
) {
121 assert_return(lease
, -EINVAL
);
122 assert_return(iaid
, -EINVAL
);
124 *iaid
= lease
->ia
.ia_na
.id
;
129 int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease
*lease
, be32_t
*iaid
) {
130 assert_return(lease
, -EINVAL
);
131 assert_return(iaid
, -EINVAL
);
133 *iaid
= lease
->pd
.ia_pd
.id
;
138 int sd_dhcp6_lease_get_address(sd_dhcp6_lease
*lease
, struct in6_addr
*addr
,
139 uint32_t *lifetime_preferred
,
140 uint32_t *lifetime_valid
) {
141 assert_return(lease
, -EINVAL
);
142 assert_return(addr
, -EINVAL
);
143 assert_return(lifetime_preferred
, -EINVAL
);
144 assert_return(lifetime_valid
, -EINVAL
);
146 if (!lease
->addr_iter
)
149 memcpy(addr
, &lease
->addr_iter
->iaaddr
.address
,
150 sizeof(struct in6_addr
));
151 *lifetime_preferred
=
152 be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
153 *lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
155 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
160 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
162 lease
->addr_iter
= lease
->ia
.addresses
;
165 int sd_dhcp6_lease_get_pd(sd_dhcp6_lease
*lease
, struct in6_addr
*prefix
,
167 uint32_t *lifetime_preferred
,
168 uint32_t *lifetime_valid
) {
169 assert_return(lease
, -EINVAL
);
170 assert_return(prefix
, -EINVAL
);
171 assert_return(prefix_len
, -EINVAL
);
172 assert_return(lifetime_preferred
, -EINVAL
);
173 assert_return(lifetime_valid
, -EINVAL
);
175 if (!lease
->prefix_iter
)
178 memcpy(prefix
, &lease
->prefix_iter
->iapdprefix
.address
,
179 sizeof(struct in6_addr
));
180 *prefix_len
= lease
->prefix_iter
->iapdprefix
.prefixlen
;
181 *lifetime_preferred
=
182 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_preferred
);
184 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_valid
);
186 lease
->prefix_iter
= lease
->prefix_iter
->addresses_next
;
191 void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease
*lease
) {
193 lease
->prefix_iter
= lease
->pd
.addresses
;
196 int dhcp6_lease_add_dns(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
197 assert_return(lease
, -EINVAL
);
198 assert_return(optval
, -EINVAL
);
203 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->dns
, &lease
->dns_count
);
206 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
207 assert_return(lease
, -EINVAL
);
208 assert_return(ret
, -EINVAL
);
214 return lease
->dns_count
;
217 int dhcp6_lease_add_domains(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
218 _cleanup_strv_free_
char **domains
= NULL
;
221 assert_return(lease
, -EINVAL
);
222 assert_return(optval
, -EINVAL
);
227 r
= dhcp6_option_parse_domainname_list(optval
, optlen
, &domains
);
231 return strv_extend_strv(&lease
->domains
, domains
, true);
234 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***ret
) {
235 assert_return(lease
, -EINVAL
);
236 assert_return(ret
, -EINVAL
);
241 *ret
= lease
->domains
;
242 return strv_length(lease
->domains
);
245 int dhcp6_lease_add_ntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
248 assert_return(lease
, -EINVAL
);
249 assert_return(optval
, -EINVAL
);
251 for (size_t offset
= 0; offset
< optlen
;) {
252 const uint8_t *subval
;
256 r
= dhcp6_option_parse(optval
, optlen
, &offset
, &subopt
, &sublen
, &subval
);
261 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
262 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
266 r
= dhcp6_option_parse_addresses(subval
, sublen
, &lease
->ntp
, &lease
->ntp_count
);
272 case DHCP6_NTP_SUBOPTION_SRV_FQDN
: {
273 _cleanup_free_
char *server
= NULL
;
275 r
= dhcp6_option_parse_domainname(subval
, sublen
, &server
);
279 if (strv_contains(lease
->ntp_fqdn
, server
))
282 r
= strv_consume(&lease
->ntp_fqdn
, TAKE_PTR(server
));
293 int dhcp6_lease_add_sntp(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
294 assert_return(lease
, -EINVAL
);
295 assert_return(optval
, -EINVAL
);
300 /* SNTP option is defined in RFC4075, and deprecated by RFC5908. */
301 return dhcp6_option_parse_addresses(optval
, optlen
, &lease
->sntp
, &lease
->sntp_count
);
304 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
, const struct in6_addr
**ret
) {
305 assert_return(lease
, -EINVAL
);
306 assert_return(ret
, -EINVAL
);
310 return lease
->ntp_count
;
313 if (lease
->sntp
&& !lease
->ntp_fqdn
) {
314 /* Fallback to the deprecated SNTP option. */
316 return lease
->sntp_count
;
322 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ret
) {
323 assert_return(lease
, -EINVAL
);
324 assert_return(ret
, -EINVAL
);
326 if (!lease
->ntp_fqdn
)
329 *ret
= lease
->ntp_fqdn
;
330 return strv_length(lease
->ntp_fqdn
);
333 int dhcp6_lease_set_fqdn(sd_dhcp6_lease
*lease
, const uint8_t *optval
, size_t optlen
) {
337 assert_return(lease
, -EINVAL
);
338 assert_return(optval
, -EINVAL
);
343 /* Ignore the flags field, it doesn't carry any useful
344 information for clients. */
345 r
= dhcp6_option_parse_domainname(optval
+ 1, optlen
- 1, &fqdn
);
349 return free_and_replace(lease
->fqdn
, fqdn
);
352 int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease
*lease
, const char **ret
) {
353 assert_return(lease
, -EINVAL
);
354 assert_return(ret
, -EINVAL
);
363 static sd_dhcp6_lease
*dhcp6_lease_free(sd_dhcp6_lease
*lease
) {
367 free(lease
->serverid
);
368 dhcp6_lease_free_ia(&lease
->ia
);
369 dhcp6_lease_free_ia(&lease
->pd
);
372 strv_free(lease
->domains
);
374 strv_free(lease
->ntp_fqdn
);
380 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease
, sd_dhcp6_lease
, dhcp6_lease_free
);
382 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
383 sd_dhcp6_lease
*lease
;
385 lease
= new0(sd_dhcp6_lease
, 1);
391 LIST_HEAD_INIT(lease
->ia
.addresses
);