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