1 /* SPDX-License-Identifier: LGPL-2.1+ */
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_set_dns(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
199 assert_return(lease
, -EINVAL
);
200 assert_return(optval
, -EINVAL
);
205 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->dns
,
207 &lease
->dns_allocated
);
209 return log_dhcp6_client_errno(client
, r
, "Invalid DNS server option: %m");
211 lease
->dns_count
= r
;
216 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, const struct in6_addr
**addrs
) {
217 assert_return(lease
, -EINVAL
);
218 assert_return(addrs
, -EINVAL
);
220 if (lease
->dns_count
) {
222 return lease
->dns_count
;
228 int dhcp6_lease_set_domains(sd_dhcp6_lease
*lease
, uint8_t *optval
,
233 assert_return(lease
, -EINVAL
);
234 assert_return(optval
, -EINVAL
);
239 r
= dhcp6_option_parse_domainname_list(optval
, optlen
, &domains
);
243 strv_free_and_replace(lease
->domains
, domains
);
244 lease
->domains_count
= r
;
249 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***domains
) {
250 assert_return(lease
, -EINVAL
);
251 assert_return(domains
, -EINVAL
);
253 if (lease
->domains_count
) {
254 *domains
= lease
->domains
;
255 return lease
->domains_count
;
261 int dhcp6_lease_set_ntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
267 assert_return(lease
, -EINVAL
);
268 assert_return(optval
, -EINVAL
);
270 lease
->ntp
= mfree(lease
->ntp
);
271 lease
->ntp_count
= 0;
272 lease
->ntp_allocated
= 0;
274 while ((r
= dhcp6_option_parse(&optval
, &optlen
, &subopt
, &sublen
,
280 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
281 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
285 s
= dhcp6_option_parse_ip6addrs(subval
, sublen
,
288 &lease
->ntp_allocated
);
292 lease
->ntp_count
= s
;
296 case DHCP6_NTP_SUBOPTION_SRV_FQDN
:
297 r
= dhcp6_option_parse_domainname_list(subval
, sublen
,
302 strv_free_and_replace(lease
->ntp_fqdn
, servers
);
303 lease
->ntp_fqdn_count
= r
;
315 int dhcp6_lease_set_sntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
318 assert_return(lease
, -EINVAL
);
319 assert_return(optval
, -EINVAL
);
324 if (lease
->ntp
|| lease
->ntp_fqdn
) {
325 log_dhcp6_client(client
, "NTP information already provided");
330 log_dhcp6_client(client
, "Using deprecated SNTP information");
332 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->ntp
,
334 &lease
->ntp_allocated
);
336 return log_dhcp6_client_errno(client
, r
, "Invalid SNTP server option: %m");
338 lease
->ntp_count
= r
;
343 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
,
344 const struct in6_addr
**addrs
) {
345 assert_return(lease
, -EINVAL
);
346 assert_return(addrs
, -EINVAL
);
348 if (lease
->ntp_count
) {
350 return lease
->ntp_count
;
356 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ntp_fqdn
) {
357 assert_return(lease
, -EINVAL
);
358 assert_return(ntp_fqdn
, -EINVAL
);
360 if (lease
->ntp_fqdn_count
) {
361 *ntp_fqdn
= lease
->ntp_fqdn
;
362 return lease
->ntp_fqdn_count
;
368 int dhcp6_lease_set_fqdn(sd_dhcp6_lease
*lease
, const uint8_t *optval
,
373 assert_return(lease
, -EINVAL
);
374 assert_return(optval
, -EINVAL
);
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 **fqdn
) {
389 assert_return(lease
, -EINVAL
);
390 assert_return(fqdn
, -EINVAL
);
400 static sd_dhcp6_lease
*dhcp6_lease_free(sd_dhcp6_lease
*lease
) {
403 free(lease
->serverid
);
404 dhcp6_lease_free_ia(&lease
->ia
);
405 dhcp6_lease_free_ia(&lease
->pd
);
410 lease
->domains
= strv_free(lease
->domains
);
414 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
418 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease
, sd_dhcp6_lease
, dhcp6_lease_free
);
420 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
421 sd_dhcp6_lease
*lease
;
423 lease
= new0(sd_dhcp6_lease
, 1);
429 LIST_HEAD_INIT(lease
->ia
.addresses
);