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