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.
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "alloc-util.h"
25 #include "dhcp6-lease-internal.h"
26 #include "dhcp6-protocol.h"
30 int dhcp6_lease_clear_timers(DHCP6IA
*ia
) {
31 assert_return(ia
, -EINVAL
);
33 ia
->timeout_t1
= sd_event_source_unref(ia
->timeout_t1
);
34 ia
->timeout_t2
= sd_event_source_unref(ia
->timeout_t2
);
39 int dhcp6_lease_ia_rebind_expire(const DHCP6IA
*ia
, uint32_t *expire
) {
41 uint32_t valid
= 0, t
;
43 assert_return(ia
, -EINVAL
);
44 assert_return(expire
, -EINVAL
);
46 LIST_FOREACH(addresses
, addr
, ia
->addresses
) {
47 t
= be32toh(addr
->iaaddr
.lifetime_valid
);
52 t
= be32toh(ia
->lifetime_t2
);
61 DHCP6IA
*dhcp6_lease_free_ia(DHCP6IA
*ia
) {
62 DHCP6Address
*address
;
67 dhcp6_lease_clear_timers(ia
);
69 while (ia
->addresses
) {
70 address
= ia
->addresses
;
72 LIST_REMOVE(addresses
, ia
->addresses
, address
);
80 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
,
82 assert_return(lease
, -EINVAL
);
83 assert_return(id
, -EINVAL
);
85 free(lease
->serverid
);
87 lease
->serverid
= memdup(id
, len
);
91 lease
->serverid_len
= len
;
96 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **id
, size_t *len
) {
97 assert_return(lease
, -EINVAL
);
98 assert_return(id
, -EINVAL
);
99 assert_return(len
, -EINVAL
);
101 *id
= lease
->serverid
;
102 *len
= lease
->serverid_len
;
107 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
108 assert_return(lease
, -EINVAL
);
110 lease
->preference
= preference
;
115 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *preference
) {
116 assert_return(preference
, -EINVAL
);
121 *preference
= lease
->preference
;
126 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
127 assert_return(lease
, -EINVAL
);
129 lease
->rapid_commit
= true;
134 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *rapid_commit
) {
135 assert_return(lease
, -EINVAL
);
136 assert_return(rapid_commit
, -EINVAL
);
138 *rapid_commit
= lease
->rapid_commit
;
143 int dhcp6_lease_get_iaid(sd_dhcp6_lease
*lease
, be32_t
*iaid
) {
144 assert_return(lease
, -EINVAL
);
145 assert_return(iaid
, -EINVAL
);
147 *iaid
= lease
->ia
.id
;
152 int sd_dhcp6_lease_get_address(sd_dhcp6_lease
*lease
, struct in6_addr
*addr
,
153 uint32_t *lifetime_preferred
,
154 uint32_t *lifetime_valid
) {
155 assert_return(lease
, -EINVAL
);
156 assert_return(addr
, -EINVAL
);
157 assert_return(lifetime_preferred
, -EINVAL
);
158 assert_return(lifetime_valid
, -EINVAL
);
160 if (!lease
->addr_iter
)
163 memcpy(addr
, &lease
->addr_iter
->iaaddr
.address
,
164 sizeof(struct in6_addr
));
165 *lifetime_preferred
=
166 be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
167 *lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
169 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
174 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
176 lease
->addr_iter
= lease
->ia
.addresses
;
179 int dhcp6_lease_set_dns(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
182 assert_return(lease
, -EINVAL
);
183 assert_return(optval
, -EINVAL
);
188 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->dns
,
190 &lease
->dns_allocated
);
192 log_dhcp6_client(client
, "Invalid DNS server option: %s",
198 lease
->dns_count
= r
;
203 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, struct in6_addr
**addrs
) {
204 assert_return(lease
, -EINVAL
);
205 assert_return(addrs
, -EINVAL
);
207 if (lease
->dns_count
) {
209 return lease
->dns_count
;
215 int dhcp6_lease_set_domains(sd_dhcp6_lease
*lease
, uint8_t *optval
,
220 assert_return(lease
, -EINVAL
);
221 assert_return(optval
, -EINVAL
);
226 r
= dhcp6_option_parse_domainname(optval
, optlen
, &domains
);
230 strv_free(lease
->domains
);
231 lease
->domains
= domains
;
232 lease
->domains_count
= r
;
237 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***domains
) {
238 assert_return(lease
, -EINVAL
);
239 assert_return(domains
, -EINVAL
);
241 if (lease
->domains_count
) {
242 *domains
= lease
->domains
;
243 return lease
->domains_count
;
249 int dhcp6_lease_set_ntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
255 assert_return(lease
, -EINVAL
);
256 assert_return(optval
, -EINVAL
);
258 lease
->ntp
= mfree(lease
->ntp
);
259 lease
->ntp_count
= 0;
260 lease
->ntp_allocated
= 0;
262 while ((r
= dhcp6_option_parse(&optval
, &optlen
, &subopt
, &sublen
,
268 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
269 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
273 s
= dhcp6_option_parse_ip6addrs(subval
, sublen
,
276 &lease
->ntp_allocated
);
280 lease
->ntp_count
= s
;
284 case DHCP6_NTP_SUBOPTION_SRV_FQDN
:
285 r
= dhcp6_option_parse_domainname(subval
, sublen
,
290 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
291 lease
->ntp_fqdn
= servers
;
292 lease
->ntp_fqdn_count
= r
;
304 int dhcp6_lease_set_sntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
307 assert_return(lease
, -EINVAL
);
308 assert_return(optval
, -EINVAL
);
313 if (lease
->ntp
|| lease
->ntp_fqdn
) {
314 log_dhcp6_client(client
, "NTP information already provided");
319 log_dhcp6_client(client
, "Using deprecated SNTP information");
321 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->ntp
,
323 &lease
->ntp_allocated
);
325 log_dhcp6_client(client
, "Invalid SNTP server option: %s",
331 lease
->ntp_count
= r
;
336 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
,
337 struct in6_addr
**addrs
) {
338 assert_return(lease
, -EINVAL
);
339 assert_return(addrs
, -EINVAL
);
341 if (lease
->ntp_count
) {
343 return lease
->ntp_count
;
349 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ntp_fqdn
) {
350 assert_return(lease
, -EINVAL
);
351 assert_return(ntp_fqdn
, -EINVAL
);
353 if (lease
->ntp_fqdn_count
) {
354 *ntp_fqdn
= lease
->ntp_fqdn
;
355 return lease
->ntp_fqdn_count
;
361 sd_dhcp6_lease
*sd_dhcp6_lease_ref(sd_dhcp6_lease
*lease
) {
366 assert(lease
->n_ref
>= 1);
372 sd_dhcp6_lease
*sd_dhcp6_lease_unref(sd_dhcp6_lease
*lease
) {
377 assert(lease
->n_ref
>= 1);
380 if (lease
->n_ref
> 0)
383 free(lease
->serverid
);
384 dhcp6_lease_free_ia(&lease
->ia
);
388 lease
->domains
= strv_free(lease
->domains
);
392 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
396 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
397 sd_dhcp6_lease
*lease
;
399 lease
= new0(sd_dhcp6_lease
, 1);
405 LIST_HEAD_INIT(lease
->ia
.addresses
);