1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright (C) 2014 Tom Gundersen
4 Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
9 #include "alloc-util.h"
10 #include "dhcp6-lease-internal.h"
11 #include "dhcp6-protocol.h"
15 int dhcp6_lease_clear_timers(DHCP6IA
*ia
) {
16 assert_return(ia
, -EINVAL
);
18 ia
->timeout_t1
= sd_event_source_unref(ia
->timeout_t1
);
19 ia
->timeout_t2
= sd_event_source_unref(ia
->timeout_t2
);
24 int dhcp6_lease_ia_rebind_expire(const DHCP6IA
*ia
, uint32_t *expire
) {
26 uint32_t valid
= 0, t
;
28 assert_return(ia
, -EINVAL
);
29 assert_return(expire
, -EINVAL
);
31 LIST_FOREACH(addresses
, addr
, ia
->addresses
) {
32 t
= be32toh(addr
->iaaddr
.lifetime_valid
);
37 t
= be32toh(ia
->ia_na
.lifetime_t2
);
46 DHCP6IA
*dhcp6_lease_free_ia(DHCP6IA
*ia
) {
47 DHCP6Address
*address
;
52 dhcp6_lease_clear_timers(ia
);
54 while (ia
->addresses
) {
55 address
= ia
->addresses
;
57 LIST_REMOVE(addresses
, ia
->addresses
, address
);
65 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
,
67 assert_return(lease
, -EINVAL
);
68 assert_return(id
, -EINVAL
);
70 free(lease
->serverid
);
72 lease
->serverid
= memdup(id
, len
);
76 lease
->serverid_len
= len
;
81 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **id
, size_t *len
) {
82 assert_return(lease
, -EINVAL
);
88 *id
= lease
->serverid
;
90 *len
= lease
->serverid_len
;
95 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
96 assert_return(lease
, -EINVAL
);
98 lease
->preference
= preference
;
103 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *preference
) {
104 assert_return(preference
, -EINVAL
);
109 *preference
= lease
->preference
;
114 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
115 assert_return(lease
, -EINVAL
);
117 lease
->rapid_commit
= true;
122 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *rapid_commit
) {
123 assert_return(lease
, -EINVAL
);
124 assert_return(rapid_commit
, -EINVAL
);
126 *rapid_commit
= lease
->rapid_commit
;
131 int dhcp6_lease_get_iaid(sd_dhcp6_lease
*lease
, be32_t
*iaid
) {
132 assert_return(lease
, -EINVAL
);
133 assert_return(iaid
, -EINVAL
);
135 *iaid
= lease
->ia
.ia_na
.id
;
140 int sd_dhcp6_lease_get_address(sd_dhcp6_lease
*lease
, struct in6_addr
*addr
,
141 uint32_t *lifetime_preferred
,
142 uint32_t *lifetime_valid
) {
143 assert_return(lease
, -EINVAL
);
144 assert_return(addr
, -EINVAL
);
145 assert_return(lifetime_preferred
, -EINVAL
);
146 assert_return(lifetime_valid
, -EINVAL
);
148 if (!lease
->addr_iter
)
151 memcpy(addr
, &lease
->addr_iter
->iaaddr
.address
,
152 sizeof(struct in6_addr
));
153 *lifetime_preferred
=
154 be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
155 *lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
157 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
162 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
164 lease
->addr_iter
= lease
->ia
.addresses
;
167 int sd_dhcp6_lease_get_pd(sd_dhcp6_lease
*lease
, struct in6_addr
*prefix
,
169 uint32_t *lifetime_preferred
,
170 uint32_t *lifetime_valid
) {
171 assert_return(lease
, -EINVAL
);
172 assert_return(prefix
, -EINVAL
);
173 assert_return(prefix_len
, -EINVAL
);
174 assert_return(lifetime_preferred
, -EINVAL
);
175 assert_return(lifetime_valid
, -EINVAL
);
177 if (!lease
->prefix_iter
)
180 memcpy(prefix
, &lease
->prefix_iter
->iapdprefix
.address
,
181 sizeof(struct in6_addr
));
182 *prefix_len
= lease
->prefix_iter
->iapdprefix
.prefixlen
;
183 *lifetime_preferred
=
184 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_preferred
);
186 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_valid
);
188 lease
->prefix_iter
= lease
->prefix_iter
->addresses_next
;
193 void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease
*lease
) {
195 lease
->prefix_iter
= lease
->pd
.addresses
;
198 int dhcp6_lease_set_dns(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
201 assert_return(lease
, -EINVAL
);
202 assert_return(optval
, -EINVAL
);
207 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->dns
,
209 &lease
->dns_allocated
);
211 log_dhcp6_client(client
, "Invalid DNS server option: %s",
217 lease
->dns_count
= r
;
222 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, struct in6_addr
**addrs
) {
223 assert_return(lease
, -EINVAL
);
224 assert_return(addrs
, -EINVAL
);
226 if (lease
->dns_count
) {
228 return lease
->dns_count
;
234 int dhcp6_lease_set_domains(sd_dhcp6_lease
*lease
, uint8_t *optval
,
239 assert_return(lease
, -EINVAL
);
240 assert_return(optval
, -EINVAL
);
245 r
= dhcp6_option_parse_domainname(optval
, optlen
, &domains
);
249 strv_free_and_replace(lease
->domains
, domains
);
250 lease
->domains_count
= r
;
255 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***domains
) {
256 assert_return(lease
, -EINVAL
);
257 assert_return(domains
, -EINVAL
);
259 if (lease
->domains_count
) {
260 *domains
= lease
->domains
;
261 return lease
->domains_count
;
267 int dhcp6_lease_set_ntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
273 assert_return(lease
, -EINVAL
);
274 assert_return(optval
, -EINVAL
);
276 lease
->ntp
= mfree(lease
->ntp
);
277 lease
->ntp_count
= 0;
278 lease
->ntp_allocated
= 0;
280 while ((r
= dhcp6_option_parse(&optval
, &optlen
, &subopt
, &sublen
,
286 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
287 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
291 s
= dhcp6_option_parse_ip6addrs(subval
, sublen
,
294 &lease
->ntp_allocated
);
298 lease
->ntp_count
= s
;
302 case DHCP6_NTP_SUBOPTION_SRV_FQDN
:
303 r
= dhcp6_option_parse_domainname(subval
, sublen
,
308 strv_free_and_replace(lease
->ntp_fqdn
, servers
);
309 lease
->ntp_fqdn_count
= r
;
321 int dhcp6_lease_set_sntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
324 assert_return(lease
, -EINVAL
);
325 assert_return(optval
, -EINVAL
);
330 if (lease
->ntp
|| lease
->ntp_fqdn
) {
331 log_dhcp6_client(client
, "NTP information already provided");
336 log_dhcp6_client(client
, "Using deprecated SNTP information");
338 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->ntp
,
340 &lease
->ntp_allocated
);
342 log_dhcp6_client(client
, "Invalid SNTP server option: %s",
348 lease
->ntp_count
= r
;
353 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
,
354 struct in6_addr
**addrs
) {
355 assert_return(lease
, -EINVAL
);
356 assert_return(addrs
, -EINVAL
);
358 if (lease
->ntp_count
) {
360 return lease
->ntp_count
;
366 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ntp_fqdn
) {
367 assert_return(lease
, -EINVAL
);
368 assert_return(ntp_fqdn
, -EINVAL
);
370 if (lease
->ntp_fqdn_count
) {
371 *ntp_fqdn
= lease
->ntp_fqdn
;
372 return lease
->ntp_fqdn_count
;
378 sd_dhcp6_lease
*sd_dhcp6_lease_ref(sd_dhcp6_lease
*lease
) {
383 assert(lease
->n_ref
>= 1);
389 sd_dhcp6_lease
*sd_dhcp6_lease_unref(sd_dhcp6_lease
*lease
) {
394 assert(lease
->n_ref
>= 1);
397 if (lease
->n_ref
> 0)
400 free(lease
->serverid
);
401 dhcp6_lease_free_ia(&lease
->ia
);
402 dhcp6_lease_free_ia(&lease
->pd
);
406 lease
->domains
= strv_free(lease
->domains
);
410 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
414 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
415 sd_dhcp6_lease
*lease
;
417 lease
= new0(sd_dhcp6_lease
, 1);
423 LIST_HEAD_INIT(lease
->ia
.addresses
);