1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2014 Tom Gundersen
7 Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "dhcp6-lease-internal.h"
29 #include "dhcp6-protocol.h"
31 int dhcp6_lease_clear_timers(DHCP6IA
*ia
) {
32 assert_return(ia
, -EINVAL
);
34 ia
->timeout_t1
= sd_event_source_unref(ia
->timeout_t1
);
35 ia
->timeout_t2
= sd_event_source_unref(ia
->timeout_t2
);
40 int dhcp6_lease_ia_rebind_expire(const DHCP6IA
*ia
, uint32_t *expire
) {
42 uint32_t valid
= 0, t
;
44 assert_return(ia
, -EINVAL
);
45 assert_return(expire
, -EINVAL
);
47 LIST_FOREACH(addresses
, addr
, ia
->addresses
) {
48 t
= be32toh(addr
->iaaddr
.lifetime_valid
);
53 t
= be32toh(ia
->lifetime_t2
);
62 DHCP6IA
*dhcp6_lease_free_ia(DHCP6IA
*ia
) {
63 DHCP6Address
*address
;
68 dhcp6_lease_clear_timers(ia
);
70 while (ia
->addresses
) {
71 address
= ia
->addresses
;
73 LIST_REMOVE(addresses
, ia
->addresses
, address
);
81 int dhcp6_lease_set_serverid(sd_dhcp6_lease
*lease
, const uint8_t *id
,
83 assert_return(lease
, -EINVAL
);
84 assert_return(id
, -EINVAL
);
86 free(lease
->serverid
);
88 lease
->serverid
= memdup(id
, len
);
92 lease
->serverid_len
= len
;
97 int dhcp6_lease_get_serverid(sd_dhcp6_lease
*lease
, uint8_t **id
, size_t *len
) {
98 assert_return(lease
, -EINVAL
);
99 assert_return(id
, -EINVAL
);
100 assert_return(len
, -EINVAL
);
102 *id
= lease
->serverid
;
103 *len
= lease
->serverid_len
;
108 int dhcp6_lease_set_preference(sd_dhcp6_lease
*lease
, uint8_t preference
) {
109 assert_return(lease
, -EINVAL
);
111 lease
->preference
= preference
;
116 int dhcp6_lease_get_preference(sd_dhcp6_lease
*lease
, uint8_t *preference
) {
117 assert_return(preference
, -EINVAL
);
122 *preference
= lease
->preference
;
127 int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease
*lease
) {
128 assert_return(lease
, -EINVAL
);
130 lease
->rapid_commit
= true;
135 int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease
*lease
, bool *rapid_commit
) {
136 assert_return(lease
, -EINVAL
);
137 assert_return(rapid_commit
, -EINVAL
);
139 *rapid_commit
= lease
->rapid_commit
;
144 int dhcp6_lease_get_iaid(sd_dhcp6_lease
*lease
, be32_t
*iaid
) {
145 assert_return(lease
, -EINVAL
);
146 assert_return(iaid
, -EINVAL
);
148 *iaid
= lease
->ia
.id
;
153 int sd_dhcp6_lease_get_address(sd_dhcp6_lease
*lease
, struct in6_addr
*addr
,
154 uint32_t *lifetime_preferred
,
155 uint32_t *lifetime_valid
) {
156 assert_return(lease
, -EINVAL
);
157 assert_return(addr
, -EINVAL
);
158 assert_return(lifetime_preferred
, -EINVAL
);
159 assert_return(lifetime_valid
, -EINVAL
);
161 if (!lease
->addr_iter
)
164 memcpy(addr
, &lease
->addr_iter
->iaaddr
.address
,
165 sizeof(struct in6_addr
));
166 *lifetime_preferred
=
167 be32toh(lease
->addr_iter
->iaaddr
.lifetime_preferred
);
168 *lifetime_valid
= be32toh(lease
->addr_iter
->iaaddr
.lifetime_valid
);
170 lease
->addr_iter
= lease
->addr_iter
->addresses_next
;
175 void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease
*lease
) {
177 lease
->addr_iter
= lease
->ia
.addresses
;
180 int dhcp6_lease_set_dns(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
183 assert_return(lease
, -EINVAL
);
184 assert_return(optval
, -EINVAL
);
189 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->dns
,
191 &lease
->dns_allocated
);
193 log_dhcp6_client(client
, "Invalid DNS server option: %s",
199 lease
->dns_count
= r
;
204 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease
*lease
, struct in6_addr
**addrs
) {
205 assert_return(lease
, -EINVAL
);
206 assert_return(addrs
, -EINVAL
);
208 if (lease
->dns_count
) {
210 return lease
->dns_count
;
216 int dhcp6_lease_set_domains(sd_dhcp6_lease
*lease
, uint8_t *optval
,
221 assert_return(lease
, -EINVAL
);
222 assert_return(optval
, -EINVAL
);
227 r
= dhcp6_option_parse_domainname(optval
, optlen
, &domains
);
231 free(lease
->domains
);
232 lease
->domains
= domains
;
233 lease
->domains_count
= r
;
238 int sd_dhcp6_lease_get_domains(sd_dhcp6_lease
*lease
, char ***domains
) {
239 assert_return(lease
, -EINVAL
);
240 assert_return(domains
, -EINVAL
);
242 if (lease
->domains_count
) {
243 *domains
= lease
->domains
;
244 return lease
->domains_count
;
250 int dhcp6_lease_set_ntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
256 assert_return(lease
, -EINVAL
);
257 assert_return(optval
, -EINVAL
);
260 lease
->ntp_count
= 0;
261 lease
->ntp_allocated
= 0;
263 while ((r
= dhcp6_option_parse(&optval
, &optlen
, &subopt
, &sublen
,
269 case DHCP6_NTP_SUBOPTION_SRV_ADDR
:
270 case DHCP6_NTP_SUBOPTION_MC_ADDR
:
274 s
= dhcp6_option_parse_ip6addrs(subval
, sublen
,
277 &lease
->ntp_allocated
);
281 lease
->ntp_count
= s
;
285 case DHCP6_NTP_SUBOPTION_SRV_FQDN
:
286 r
= dhcp6_option_parse_domainname(subval
, sublen
,
291 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
292 lease
->ntp_fqdn
= servers
;
293 lease
->ntp_fqdn_count
= r
;
305 int dhcp6_lease_set_sntp(sd_dhcp6_lease
*lease
, uint8_t *optval
, size_t optlen
) {
308 assert_return(lease
, -EINVAL
);
309 assert_return(optval
, -EINVAL
);
314 if (lease
->ntp
|| lease
->ntp_fqdn
) {
315 log_dhcp6_client(client
, "NTP information already provided");
320 log_dhcp6_client(client
, "Using deprecated SNTP information");
322 r
= dhcp6_option_parse_ip6addrs(optval
, optlen
, &lease
->ntp
,
324 &lease
->ntp_allocated
);
326 log_dhcp6_client(client
, "Invalid SNTP server option: %s",
332 lease
->ntp_count
= r
;
337 int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease
*lease
,
338 struct in6_addr
**addrs
) {
339 assert_return(lease
, -EINVAL
);
340 assert_return(addrs
, -EINVAL
);
342 if (lease
->ntp_count
) {
344 return lease
->ntp_count
;
350 int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease
*lease
, char ***ntp_fqdn
) {
351 assert_return(lease
, -EINVAL
);
352 assert_return(ntp_fqdn
, -EINVAL
);
354 if (lease
->ntp_fqdn_count
) {
355 *ntp_fqdn
= lease
->ntp_fqdn
;
356 return lease
->ntp_fqdn_count
;
362 sd_dhcp6_lease
*sd_dhcp6_lease_ref(sd_dhcp6_lease
*lease
) {
367 assert(lease
->n_ref
>= 1);
373 sd_dhcp6_lease
*sd_dhcp6_lease_unref(sd_dhcp6_lease
*lease
) {
378 assert(lease
->n_ref
>= 1);
381 if (lease
->n_ref
> 0)
384 free(lease
->serverid
);
385 dhcp6_lease_free_ia(&lease
->ia
);
389 lease
->domains
= strv_free(lease
->domains
);
393 lease
->ntp_fqdn
= strv_free(lease
->ntp_fqdn
);
399 int dhcp6_lease_new(sd_dhcp6_lease
**ret
) {
400 sd_dhcp6_lease
*lease
;
402 lease
= new0(sd_dhcp6_lease
, 1);
408 LIST_HEAD_INIT(lease
->ia
.addresses
);