]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/sd-dhcp6-lease.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp6-lease.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
3fb2c570
PF
2/***
3 This file is part of systemd.
4
5 Copyright (C) 2014 Tom Gundersen
5da1b97f 6 Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
3fb2c570
PF
7
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.
12
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.
17
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/>.
20***/
21
22#include <errno.h>
23
b5efdb8a 24#include "alloc-util.h"
3fb2c570 25#include "dhcp6-lease-internal.h"
6599680e 26#include "dhcp6-protocol.h"
b5efdb8a
LP
27#include "strv.h"
28#include "util.h"
3fb2c570
PF
29
30int dhcp6_lease_clear_timers(DHCP6IA *ia) {
31 assert_return(ia, -EINVAL);
32
33 ia->timeout_t1 = sd_event_source_unref(ia->timeout_t1);
34 ia->timeout_t2 = sd_event_source_unref(ia->timeout_t2);
35
36 return 0;
37}
38
709d6710
PF
39int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
40 DHCP6Address *addr;
41 uint32_t valid = 0, t;
42
43 assert_return(ia, -EINVAL);
44 assert_return(expire, -EINVAL);
45
46 LIST_FOREACH(addresses, addr, ia->addresses) {
ee3a5027 47 t = be32toh(addr->iaaddr.lifetime_valid);
709d6710
PF
48 if (valid < t)
49 valid = t;
50 }
51
52 t = be32toh(ia->lifetime_t2);
53 if (t > valid)
54 return -EINVAL;
55
56 *expire = valid - t;
57
58 return 0;
59}
60
3fb2c570
PF
61DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
62 DHCP6Address *address;
63
64 if (!ia)
65 return NULL;
66
67 dhcp6_lease_clear_timers(ia);
68
69 while (ia->addresses) {
70 address = ia->addresses;
71
72 LIST_REMOVE(addresses, ia->addresses, address);
73
74 free(address);
75 }
76
77 return NULL;
78}
79
80int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
81 size_t len) {
82 assert_return(lease, -EINVAL);
83 assert_return(id, -EINVAL);
84
85 free(lease->serverid);
86
87 lease->serverid = memdup(id, len);
88 if (!lease->serverid)
89 return -EINVAL;
90
91 lease->serverid_len = len;
92
93 return 0;
94}
95
96int 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);
100
101 *id = lease->serverid;
102 *len = lease->serverid_len;
103
104 return 0;
105}
106
107int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference) {
108 assert_return(lease, -EINVAL);
109
110 lease->preference = preference;
111
112 return 0;
113}
114
115int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) {
3fb2c570
PF
116 assert_return(preference, -EINVAL);
117
fab15fec
PF
118 if (!lease)
119 return -EINVAL;
120
3fb2c570
PF
121 *preference = lease->preference;
122
123 return 0;
124}
125
ed6ee219
PF
126int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease) {
127 assert_return(lease, -EINVAL);
128
129 lease->rapid_commit = true;
130
131 return 0;
132}
133
134int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) {
135 assert_return(lease, -EINVAL);
136 assert_return(rapid_commit, -EINVAL);
137
138 *rapid_commit = lease->rapid_commit;
139
140 return 0;
141}
142
3fb2c570
PF
143int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
144 assert_return(lease, -EINVAL);
145 assert_return(iaid, -EINVAL);
146
147 *iaid = lease->ia.id;
148
149 return 0;
150}
151
e7504d95
PF
152int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
153 uint32_t *lifetime_preferred,
154 uint32_t *lifetime_valid) {
ea3b3a75
PF
155 assert_return(lease, -EINVAL);
156 assert_return(addr, -EINVAL);
157 assert_return(lifetime_preferred, -EINVAL);
158 assert_return(lifetime_valid, -EINVAL);
159
160 if (!lease->addr_iter)
161 return -ENOMSG;
162
ee3a5027
PF
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);
ea3b3a75
PF
168
169 lease->addr_iter = lease->addr_iter->addresses_next;
170
171 return 0;
172}
173
e7504d95
PF
174void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
175 if (lease)
176 lease->addr_iter = lease->ia.addresses;
ea3b3a75
PF
177}
178
7bd8e95d
PF
179int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
180 int r;
181
182 assert_return(lease, -EINVAL);
183 assert_return(optval, -EINVAL);
184
185 if (!optlen)
186 return 0;
187
188 r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
189 lease->dns_count,
190 &lease->dns_allocated);
191 if (r < 0) {
192 log_dhcp6_client(client, "Invalid DNS server option: %s",
193 strerror(-r));
194
195 return r;
196 }
197
198 lease->dns_count = r;
199
200 return 0;
201}
202
203int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) {
204 assert_return(lease, -EINVAL);
205 assert_return(addrs, -EINVAL);
206
207 if (lease->dns_count) {
208 *addrs = lease->dns;
209 return lease->dns_count;
210 }
211
212 return -ENOENT;
213}
214
5da1b97f
PF
215int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
216 size_t optlen) {
217 int r;
218 char **domains;
219
220 assert_return(lease, -EINVAL);
221 assert_return(optval, -EINVAL);
222
223 if (!optlen)
224 return 0;
225
226 r = dhcp6_option_parse_domainname(optval, optlen, &domains);
227 if (r < 0)
228 return 0;
229
0b75a95a 230 strv_free(lease->domains);
5da1b97f
PF
231 lease->domains = domains;
232 lease->domains_count = r;
233
234 return r;
235}
236
237int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {
238 assert_return(lease, -EINVAL);
239 assert_return(domains, -EINVAL);
240
241 if (lease->domains_count) {
242 *domains = lease->domains;
243 return lease->domains_count;
244 }
245
246 return -ENOENT;
247}
248
52efd56a 249int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
6599680e
PF
250 int r;
251 uint16_t subopt;
252 size_t sublen;
253 uint8_t *subval;
254
255 assert_return(lease, -EINVAL);
256 assert_return(optval, -EINVAL);
257
63a54aa1 258 lease->ntp = mfree(lease->ntp);
41e4615d
PF
259 lease->ntp_count = 0;
260 lease->ntp_allocated = 0;
261
6599680e
PF
262 while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen,
263 &subval)) >= 0) {
264 int s;
265 char **servers;
266
267 switch(subopt) {
268 case DHCP6_NTP_SUBOPTION_SRV_ADDR:
269 case DHCP6_NTP_SUBOPTION_MC_ADDR:
270 if (sublen != 16)
271 return 0;
272
273 s = dhcp6_option_parse_ip6addrs(subval, sublen,
274 &lease->ntp,
275 lease->ntp_count,
276 &lease->ntp_allocated);
277 if (s < 0)
278 return s;
279
280 lease->ntp_count = s;
281
282 break;
283
284 case DHCP6_NTP_SUBOPTION_SRV_FQDN:
285 r = dhcp6_option_parse_domainname(subval, sublen,
286 &servers);
287 if (r < 0)
288 return 0;
289
290 lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
291 lease->ntp_fqdn = servers;
292 lease->ntp_fqdn_count = r;
293
294 break;
295 }
296 }
297
298 if (r != -ENOMSG)
299 return r;
300
301 return 0;
302}
303
41e4615d
PF
304int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
305 int r;
306
307 assert_return(lease, -EINVAL);
308 assert_return(optval, -EINVAL);
309
310 if (!optlen)
311 return 0;
312
313 if (lease->ntp || lease->ntp_fqdn) {
314 log_dhcp6_client(client, "NTP information already provided");
315
316 return 0;
317 }
318
319 log_dhcp6_client(client, "Using deprecated SNTP information");
320
321 r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
322 lease->ntp_count,
323 &lease->ntp_allocated);
324 if (r < 0) {
325 log_dhcp6_client(client, "Invalid SNTP server option: %s",
326 strerror(-r));
327
328 return r;
329 }
330
331 lease->ntp_count = r;
332
333 return 0;
334}
335
6599680e
PF
336int 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);
340
341 if (lease->ntp_count) {
342 *addrs = lease->ntp;
343 return lease->ntp_count;
344 }
345
346 return -ENOENT;
347}
348
349int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
350 assert_return(lease, -EINVAL);
351 assert_return(ntp_fqdn, -EINVAL);
352
353 if (lease->ntp_fqdn_count) {
354 *ntp_fqdn = lease->ntp_fqdn;
355 return lease->ntp_fqdn_count;
356 }
357
358 return -ENOENT;
359}
360
3fb2c570 361sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
3733eec3
LP
362
363 if (!lease)
364 return NULL;
365
366 assert(lease->n_ref >= 1);
367 lease->n_ref++;
3fb2c570
PF
368
369 return lease;
370}
371
372sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
3fb2c570 373
3733eec3
LP
374 if (!lease)
375 return NULL;
5da1b97f 376
3733eec3
LP
377 assert(lease->n_ref >= 1);
378 lease->n_ref--;
5da1b97f 379
3733eec3
LP
380 if (lease->n_ref > 0)
381 return NULL;
6599680e 382
3733eec3
LP
383 free(lease->serverid);
384 dhcp6_lease_free_ia(&lease->ia);
385
386 free(lease->dns);
387
388 lease->domains = strv_free(lease->domains);
389
390 free(lease->ntp);
391
392 lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
6b430fdb 393 return mfree(lease);
3fb2c570
PF
394}
395
396int dhcp6_lease_new(sd_dhcp6_lease **ret) {
397 sd_dhcp6_lease *lease;
398
399 lease = new0(sd_dhcp6_lease, 1);
400 if (!lease)
401 return -ENOMEM;
402
3733eec3 403 lease->n_ref = 1;
3fb2c570
PF
404
405 LIST_HEAD_INIT(lease->ia.addresses);
406
407 *ret = lease;
408 return 0;
409}