1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright (C) 2014 Tom Gundersen
6 Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
11 #include "alloc-util.h"
12 #include "dhcp6-lease-internal.h"
13 #include "dhcp6-protocol.h"
17 int dhcp6_lease_clear_timers(DHCP6IA
*ia
) {
18 assert_return(ia
, -EINVAL
);
20 ia
->timeout_t1
= sd_event_source_unref(ia
->timeout_t1
);
21 ia
->timeout_t2
= sd_event_source_unref(ia
->timeout_t2
);
26 int dhcp6_lease_ia_rebind_expire(const DHCP6IA
*ia
, uint32_t *expire
) {
28 uint32_t valid
= 0, t
;
30 assert_return(ia
, -EINVAL
);
31 assert_return(expire
, -EINVAL
);
33 LIST_FOREACH(addresses
, addr
, ia
->addresses
) {
34 t
= be32toh(addr
->iaaddr
.lifetime_valid
);
39 t
= be32toh(ia
->ia_na
.lifetime_t2
);
48 DHCP6IA
*dhcp6_lease_free_ia(DHCP6IA
*ia
) {
49 DHCP6Address
*address
;
54 dhcp6_lease_clear_timers(ia
);
56 while (ia
->addresses
) {
57 address
= ia
->addresses
;
59 LIST_REMOVE(addresses
, ia
->addresses
, address
);
67 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
,
69 assert_return(lease
, -EINVAL
);
70 assert_return(id
, -EINVAL
);
72 free(lease
->serverid
);
74 lease
->serverid
= memdup(id
, len
);
78 lease
->serverid_len
= len
;
83 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **id
, size_t *len
) {
84 assert_return(lease
, -EINVAL
);
90 *id
= lease
->serverid
;
92 *len
= lease
->serverid_len
;
97 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
98 assert_return(lease
, -EINVAL
);
100 lease
->preference
= preference
;
105 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *preference
) {
106 assert_return(preference
, -EINVAL
);
111 *preference
= lease
->preference
;
116 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
117 assert_return(lease
, -EINVAL
);
119 lease
->rapid_commit
= true;
124 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *rapid_commit
) {
125 assert_return(lease
, -EINVAL
);
126 assert_return(rapid_commit
, -EINVAL
);
128 *rapid_commit
= lease
->rapid_commit
;
133 int dhcp6_lease_get_iaid(sd_dhcp6_lease
*lease
, be32_t
*iaid
) {
134 assert_return(lease
, -EINVAL
);
135 assert_return(iaid
, -EINVAL
);
137 *iaid
= lease
->ia
.ia_na
.id
;
142 int sd_dhcp6_lease_get_address(sd_dhcp6_lease
*lease
, struct in6_addr
*addr
,
143 uint32_t *lifetime_preferred
,
144 uint32_t *lifetime_valid
) {
145 assert_return(lease
, -EINVAL
);
146 assert_return(addr
, -EINVAL
);
147 assert_return(lifetime_preferred
, -EINVAL
);
148 assert_return(lifetime_valid
, -EINVAL
);
150 if (!lease
->addr_iter
)
153 memcpy(addr
, &lease
->addr_iter
->iaaddr
.address
,
154 sizeof(struct in6_addr
));
155 *lifetime_preferred
=
156 be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
157 *lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
159 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
164 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
166 lease
->addr_iter
= lease
->ia
.addresses
;
169 int sd_dhcp6_lease_get_pd(sd_dhcp6_lease
*lease
, struct in6_addr
*prefix
,
171 uint32_t *lifetime_preferred
,
172 uint32_t *lifetime_valid
) {
173 assert_return(lease
, -EINVAL
);
174 assert_return(prefix
, -EINVAL
);
175 assert_return(prefix_len
, -EINVAL
);
176 assert_return(lifetime_preferred
, -EINVAL
);
177 assert_return(lifetime_valid
, -EINVAL
);
179 if (!lease
->prefix_iter
)
182 memcpy(prefix
, &lease
->prefix_iter
->iapdprefix
.address
,
183 sizeof(struct in6_addr
));
184 *prefix_len
= lease
->prefix_iter
->iapdprefix
.prefixlen
;
185 *lifetime_preferred
=
186 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_preferred
);
188 be32toh(lease
->prefix_iter
->iapdprefix
.lifetime_valid
);
190 lease
->prefix_iter
= lease
->prefix_iter
->addresses_next
;
195 void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease
*lease
) {
197 lease
->prefix_iter
= lease
->pd
.addresses
;
200 int dhcp6_lease_set_dns(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
203 assert_return(lease
, -EINVAL
);
204 assert_return(optval
, -EINVAL
);
209 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->dns
,
211 &lease
->dns_allocated
);
213 log_dhcp6_client(client
, "Invalid DNS server option: %s",
219 lease
->dns_count
= r
;
224 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, struct in6_addr
**addrs
) {
225 assert_return(lease
, -EINVAL
);
226 assert_return(addrs
, -EINVAL
);
228 if (lease
->dns_count
) {
230 return lease
->dns_count
;
236 int dhcp6_lease_set_domains(sd_dhcp6_lease
*lease
, uint8_t *optval
,
241 assert_return(lease
, -EINVAL
);
242 assert_return(optval
, -EINVAL
);
247 r
= dhcp6_option_parse_domainname(optval
, optlen
, &domains
);
251 strv_free(lease
->domains
);
252 lease
->domains
= domains
;
253 lease
->domains_count
= r
;
258 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***domains
) {
259 assert_return(lease
, -EINVAL
);
260 assert_return(domains
, -EINVAL
);
262 if (lease
->domains_count
) {
263 *domains
= lease
->domains
;
264 return lease
->domains_count
;
270 int dhcp6_lease_set_ntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
276 assert_return(lease
, -EINVAL
);
277 assert_return(optval
, -EINVAL
);
279 lease
->ntp
= mfree(lease
->ntp
);
280 lease
->ntp_count
= 0;
281 lease
->ntp_allocated
= 0;
283 while ((r
= dhcp6_option_parse(&optval
, &optlen
, &subopt
, &sublen
,
289 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
290 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
294 s
= dhcp6_option_parse_ip6addrs(subval
, sublen
,
297 &lease
->ntp_allocated
);
301 lease
->ntp_count
= s
;
305 case DHCP6_NTP_SUBOPTION_SRV_FQDN
:
306 r
= dhcp6_option_parse_domainname(subval
, sublen
,
311 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
312 lease
->ntp_fqdn
= servers
;
313 lease
->ntp_fqdn_count
= r
;
325 int dhcp6_lease_set_sntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
328 assert_return(lease
, -EINVAL
);
329 assert_return(optval
, -EINVAL
);
334 if (lease
->ntp
|| lease
->ntp_fqdn
) {
335 log_dhcp6_client(client
, "NTP information already provided");
340 log_dhcp6_client(client
, "Using deprecated SNTP information");
342 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->ntp
,
344 &lease
->ntp_allocated
);
346 log_dhcp6_client(client
, "Invalid SNTP server option: %s",
352 lease
->ntp_count
= r
;
357 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
,
358 struct in6_addr
**addrs
) {
359 assert_return(lease
, -EINVAL
);
360 assert_return(addrs
, -EINVAL
);
362 if (lease
->ntp_count
) {
364 return lease
->ntp_count
;
370 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ntp_fqdn
) {
371 assert_return(lease
, -EINVAL
);
372 assert_return(ntp_fqdn
, -EINVAL
);
374 if (lease
->ntp_fqdn_count
) {
375 *ntp_fqdn
= lease
->ntp_fqdn
;
376 return lease
->ntp_fqdn_count
;
382 sd_dhcp6_lease
*sd_dhcp6_lease_ref(sd_dhcp6_lease
*lease
) {
387 assert(lease
->n_ref
>= 1);
393 sd_dhcp6_lease
*sd_dhcp6_lease_unref(sd_dhcp6_lease
*lease
) {
398 assert(lease
->n_ref
>= 1);
401 if (lease
->n_ref
> 0)
404 free(lease
->serverid
);
405 dhcp6_lease_free_ia(&lease
->ia
);
406 dhcp6_lease_free_ia(&lease
->pd
);
410 lease
->domains
= strv_free(lease
->domains
);
414 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
418 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
419 sd_dhcp6_lease
*lease
;
421 lease
= new0(sd_dhcp6_lease
, 1);
427 LIST_HEAD_INIT(lease
->ia
.addresses
);