1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3   Copyright © 2013 Intel Corporation. All rights reserved.
4 ***/
5 
6 #include <arpa/inet.h>
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12 
13 #include "sd-dhcp-lease.h"
14 
15 #include "alloc-util.h"
16 #include "dhcp-lease-internal.h"
17 #include "dhcp-protocol.h"
18 #include "dns-domain.h"
19 #include "env-file.h"
20 #include "fd-util.h"
21 #include "fileio.h"
22 #include "fs-util.h"
23 #include "hexdecoct.h"
24 #include "hostname-util.h"
25 #include "in-addr-util.h"
26 #include "network-internal.h"
27 #include "parse-util.h"
28 #include "stdio-util.h"
29 #include "string-util.h"
30 #include "strv.h"
31 #include "tmpfile-util.h"
32 #include "unaligned.h"
33 
sd_dhcp_lease_get_address(sd_dhcp_lease * lease,struct in_addr * addr)34 int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
35         assert_return(lease, -EINVAL);
36         assert_return(addr, -EINVAL);
37 
38         if (lease->address == 0)
39                 return -ENODATA;
40 
41         addr->s_addr = lease->address;
42         return 0;
43 }
44 
sd_dhcp_lease_get_broadcast(sd_dhcp_lease * lease,struct in_addr * addr)45 int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) {
46         assert_return(lease, -EINVAL);
47         assert_return(addr, -EINVAL);
48 
49         if (!lease->have_broadcast)
50                 return -ENODATA;
51 
52         addr->s_addr = lease->broadcast;
53         return 0;
54 }
55 
sd_dhcp_lease_get_lifetime(sd_dhcp_lease * lease,uint32_t * lifetime)56 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
57         assert_return(lease, -EINVAL);
58         assert_return(lifetime, -EINVAL);
59 
60         if (lease->lifetime <= 0)
61                 return -ENODATA;
62 
63         *lifetime = lease->lifetime;
64         return 0;
65 }
66 
sd_dhcp_lease_get_t1(sd_dhcp_lease * lease,uint32_t * t1)67 int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) {
68         assert_return(lease, -EINVAL);
69         assert_return(t1, -EINVAL);
70 
71         if (lease->t1 <= 0)
72                 return -ENODATA;
73 
74         *t1 = lease->t1;
75         return 0;
76 }
77 
sd_dhcp_lease_get_t2(sd_dhcp_lease * lease,uint32_t * t2)78 int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) {
79         assert_return(lease, -EINVAL);
80         assert_return(t2, -EINVAL);
81 
82         if (lease->t2 <= 0)
83                 return -ENODATA;
84 
85         *t2 = lease->t2;
86         return 0;
87 }
88 
sd_dhcp_lease_get_mtu(sd_dhcp_lease * lease,uint16_t * mtu)89 int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
90         assert_return(lease, -EINVAL);
91         assert_return(mtu, -EINVAL);
92 
93         if (lease->mtu <= 0)
94                 return -ENODATA;
95 
96         *mtu = lease->mtu;
97         return 0;
98 }
99 
sd_dhcp_lease_get_servers(sd_dhcp_lease * lease,sd_dhcp_lease_server_type_t what,const struct in_addr ** addr)100 int sd_dhcp_lease_get_servers(
101                 sd_dhcp_lease *lease,
102                 sd_dhcp_lease_server_type_t what,
103                 const struct in_addr **addr) {
104 
105         assert_return(lease, -EINVAL);
106         assert_return(what >= 0, -EINVAL);
107         assert_return(what < _SD_DHCP_LEASE_SERVER_TYPE_MAX, -EINVAL);
108 
109         if (lease->servers[what].size <= 0)
110                 return -ENODATA;
111 
112         if (addr)
113                 *addr = lease->servers[what].addr;
114 
115         return (int) lease->servers[what].size;
116 }
117 
sd_dhcp_lease_get_dns(sd_dhcp_lease * lease,const struct in_addr ** addr)118 int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {
119         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS, addr);
120 }
sd_dhcp_lease_get_ntp(sd_dhcp_lease * lease,const struct in_addr ** addr)121 int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
122         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP, addr);
123 }
sd_dhcp_lease_get_sip(sd_dhcp_lease * lease,const struct in_addr ** addr)124 int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
125         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP, addr);
126 }
sd_dhcp_lease_get_pop3(sd_dhcp_lease * lease,const struct in_addr ** addr)127 int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr) {
128         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3, addr);
129 }
sd_dhcp_lease_get_smtp(sd_dhcp_lease * lease,const struct in_addr ** addr)130 int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr) {
131         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP, addr);
132 }
sd_dhcp_lease_get_lpr(sd_dhcp_lease * lease,const struct in_addr ** addr)133 int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr) {
134         return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR, addr);
135 }
136 
sd_dhcp_lease_get_domainname(sd_dhcp_lease * lease,const char ** domainname)137 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
138         assert_return(lease, -EINVAL);
139         assert_return(domainname, -EINVAL);
140 
141         if (!lease->domainname)
142                 return -ENODATA;
143 
144         *domainname = lease->domainname;
145         return 0;
146 }
147 
sd_dhcp_lease_get_hostname(sd_dhcp_lease * lease,const char ** hostname)148 int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
149         assert_return(lease, -EINVAL);
150         assert_return(hostname, -EINVAL);
151 
152         if (!lease->hostname)
153                 return -ENODATA;
154 
155         *hostname = lease->hostname;
156         return 0;
157 }
158 
sd_dhcp_lease_get_root_path(sd_dhcp_lease * lease,const char ** root_path)159 int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
160         assert_return(lease, -EINVAL);
161         assert_return(root_path, -EINVAL);
162 
163         if (!lease->root_path)
164                 return -ENODATA;
165 
166         *root_path = lease->root_path;
167         return 0;
168 }
169 
sd_dhcp_lease_get_router(sd_dhcp_lease * lease,const struct in_addr ** addr)170 int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) {
171         assert_return(lease, -EINVAL);
172         assert_return(addr, -EINVAL);
173 
174         if (lease->router_size <= 0)
175                 return -ENODATA;
176 
177         *addr = lease->router;
178         return (int) lease->router_size;
179 }
180 
sd_dhcp_lease_get_netmask(sd_dhcp_lease * lease,struct in_addr * addr)181 int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
182         assert_return(lease, -EINVAL);
183         assert_return(addr, -EINVAL);
184 
185         if (!lease->have_subnet_mask)
186                 return -ENODATA;
187 
188         addr->s_addr = lease->subnet_mask;
189         return 0;
190 }
191 
sd_dhcp_lease_get_server_identifier(sd_dhcp_lease * lease,struct in_addr * addr)192 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) {
193         assert_return(lease, -EINVAL);
194         assert_return(addr, -EINVAL);
195 
196         if (lease->server_address == 0)
197                 return -ENODATA;
198 
199         addr->s_addr = lease->server_address;
200         return 0;
201 }
202 
sd_dhcp_lease_get_next_server(sd_dhcp_lease * lease,struct in_addr * addr)203 int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
204         assert_return(lease, -EINVAL);
205         assert_return(addr, -EINVAL);
206 
207         if (lease->next_server == 0)
208                 return -ENODATA;
209 
210         addr->s_addr = lease->next_server;
211         return 0;
212 }
213 
214 /*
215  * The returned routes array must be freed by the caller.
216  * Route objects have the same lifetime of the lease and must not be freed.
217  */
dhcp_lease_get_routes(sd_dhcp_route * routes,size_t n_routes,sd_dhcp_route *** ret)218 static int dhcp_lease_get_routes(sd_dhcp_route *routes, size_t n_routes, sd_dhcp_route ***ret) {
219         assert(routes || n_routes == 0);
220 
221         if (n_routes <= 0)
222                 return -ENODATA;
223 
224         if (ret) {
225                 sd_dhcp_route **buf;
226 
227                 buf = new(sd_dhcp_route*, n_routes);
228                 if (!buf)
229                         return -ENOMEM;
230 
231                 for (size_t i = 0; i < n_routes; i++)
232                         buf[i] = &routes[i];
233 
234                 *ret = buf;
235         }
236 
237         return (int) n_routes;
238 }
239 
sd_dhcp_lease_get_static_routes(sd_dhcp_lease * lease,sd_dhcp_route *** ret)240 int sd_dhcp_lease_get_static_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret) {
241         assert_return(lease, -EINVAL);
242 
243         return dhcp_lease_get_routes(lease->static_routes, lease->n_static_routes, ret);
244 }
245 
sd_dhcp_lease_get_classless_routes(sd_dhcp_lease * lease,sd_dhcp_route *** ret)246 int sd_dhcp_lease_get_classless_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret) {
247         assert_return(lease, -EINVAL);
248 
249         return dhcp_lease_get_routes(lease->classless_routes, lease->n_classless_routes, ret);
250 }
251 
sd_dhcp_lease_get_search_domains(sd_dhcp_lease * lease,char *** domains)252 int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
253         size_t r;
254 
255         assert_return(lease, -EINVAL);
256         assert_return(domains, -EINVAL);
257 
258         r = strv_length(lease->search_domains);
259         if (r > 0) {
260                 *domains = lease->search_domains;
261                 return (int) r;
262         }
263 
264         return -ENODATA;
265 }
266 
sd_dhcp_lease_get_6rd(sd_dhcp_lease * lease,uint8_t * ret_ipv4masklen,uint8_t * ret_prefixlen,struct in6_addr * ret_prefix,const struct in_addr ** ret_br_addresses,size_t * ret_n_br_addresses)267 int sd_dhcp_lease_get_6rd(
268                 sd_dhcp_lease *lease,
269                 uint8_t *ret_ipv4masklen,
270                 uint8_t *ret_prefixlen,
271                 struct in6_addr *ret_prefix,
272                 const struct in_addr **ret_br_addresses,
273                 size_t *ret_n_br_addresses) {
274 
275         assert_return(lease, -EINVAL);
276 
277         if (lease->sixrd_n_br_addresses <= 0)
278                 return -ENODATA;
279 
280         if (ret_ipv4masklen)
281                 *ret_ipv4masklen = lease->sixrd_ipv4masklen;
282         if (ret_prefixlen)
283                 *ret_prefixlen = lease->sixrd_prefixlen;
284         if (ret_prefix)
285                 *ret_prefix = lease->sixrd_prefix;
286         if (ret_br_addresses)
287                 *ret_br_addresses = lease->sixrd_br_addresses;
288         if (ret_n_br_addresses)
289                 *ret_n_br_addresses = lease->sixrd_n_br_addresses;
290 
291         return 0;
292 }
293 
sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease * lease,const void ** data,size_t * data_len)294 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) {
295         assert_return(lease, -EINVAL);
296         assert_return(data, -EINVAL);
297         assert_return(data_len, -EINVAL);
298 
299         if (lease->vendor_specific_len <= 0)
300                 return -ENODATA;
301 
302         *data = lease->vendor_specific;
303         *data_len = lease->vendor_specific_len;
304         return 0;
305 }
306 
dhcp_lease_free(sd_dhcp_lease * lease)307 static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
308         assert(lease);
309 
310         while (lease->private_options) {
311                 struct sd_dhcp_raw_option *option = lease->private_options;
312 
313                 LIST_REMOVE(options, lease->private_options, option);
314 
315                 free(option->data);
316                 free(option);
317         }
318 
319         free(lease->root_path);
320         free(lease->router);
321         free(lease->timezone);
322         free(lease->hostname);
323         free(lease->domainname);
324 
325         for (sd_dhcp_lease_server_type_t i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++)
326                 free(lease->servers[i].addr);
327 
328         free(lease->static_routes);
329         free(lease->classless_routes);
330         free(lease->client_id);
331         free(lease->vendor_specific);
332         strv_free(lease->search_domains);
333         free(lease->sixrd_br_addresses);
334         return mfree(lease);
335 }
336 
337 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_lease, sd_dhcp_lease, dhcp_lease_free);
338 
lease_parse_u32(const uint8_t * option,size_t len,uint32_t * ret,uint32_t min)339 static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
340         assert(option);
341         assert(ret);
342 
343         if (len != 4)
344                 return -EINVAL;
345 
346         *ret = unaligned_read_be32((be32_t*) option);
347         if (*ret < min)
348                 *ret = min;
349 
350         return 0;
351 }
352 
lease_parse_u16(const uint8_t * option,size_t len,uint16_t * ret,uint16_t min)353 static int lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
354         assert(option);
355         assert(ret);
356 
357         if (len != 2)
358                 return -EINVAL;
359 
360         *ret = unaligned_read_be16((be16_t*) option);
361         if (*ret < min)
362                 *ret = min;
363 
364         return 0;
365 }
366 
lease_parse_be32(const uint8_t * option,size_t len,be32_t * ret)367 static int lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
368         assert(option);
369         assert(ret);
370 
371         if (len != 4)
372                 return -EINVAL;
373 
374         memcpy(ret, option, 4);
375         return 0;
376 }
377 
lease_parse_string(const uint8_t * option,size_t len,char ** ret)378 static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
379         assert(option);
380         assert(ret);
381 
382         if (len <= 0)
383                 *ret = mfree(*ret);
384         else {
385                 char *string;
386 
387                 /*
388                  * One trailing NUL byte is OK, we don't mind. See:
389                  * https://github.com/systemd/systemd/issues/1337
390                  */
391                 if (memchr(option, 0, len - 1))
392                         return -EINVAL;
393 
394                 string = memdup_suffix0((const char *) option, len);
395                 if (!string)
396                         return -ENOMEM;
397 
398                 free_and_replace(*ret, string);
399         }
400 
401         return 0;
402 }
403 
lease_parse_domain(const uint8_t * option,size_t len,char ** ret)404 static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
405         _cleanup_free_ char *name = NULL, *normalized = NULL;
406         int r;
407 
408         assert(option);
409         assert(ret);
410 
411         r = lease_parse_string(option, len, &name);
412         if (r < 0)
413                 return r;
414         if (!name) {
415                 *ret = mfree(*ret);
416                 return 0;
417         }
418 
419         r = dns_name_normalize(name, 0, &normalized);
420         if (r < 0)
421                 return r;
422 
423         if (is_localhost(normalized))
424                 return -EINVAL;
425 
426         if (dns_name_is_root(normalized))
427                 return -EINVAL;
428 
429         free_and_replace(*ret, normalized);
430 
431         return 0;
432 }
433 
lease_parse_in_addrs(const uint8_t * option,size_t len,struct in_addr ** ret,size_t * n_ret)434 static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
435         assert(option || len == 0);
436         assert(ret);
437         assert(n_ret);
438 
439         if (len <= 0) {
440                 *ret = mfree(*ret);
441                 *n_ret = 0;
442         } else {
443                 size_t n_addresses;
444                 struct in_addr *addresses;
445 
446                 if (len % 4 != 0)
447                         return -EINVAL;
448 
449                 n_addresses = len / 4;
450 
451                 addresses = newdup(struct in_addr, option, n_addresses);
452                 if (!addresses)
453                         return -ENOMEM;
454 
455                 free(*ret);
456                 *ret = addresses;
457                 *n_ret = n_addresses;
458         }
459 
460         return 0;
461 }
462 
lease_parse_sip_server(const uint8_t * option,size_t len,struct in_addr ** ret,size_t * n_ret)463 static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
464         assert(option || len == 0);
465         assert(ret);
466         assert(n_ret);
467 
468         if (len <= 0)
469                 return -EINVAL;
470 
471         /* The SIP record is like the other, regular server records, but prefixed with a single "encoding"
472          * byte that is either 0 or 1. We only support it to be 1 for now. Let's drop it and parse it like
473          * the other fields */
474 
475         if (option[0] != 1) { /* We only support IP address encoding for now */
476                 *ret = mfree(*ret);
477                 *n_ret = 0;
478                 return 0;
479         }
480 
481         return lease_parse_in_addrs(option + 1, len - 1, ret, n_ret);
482 }
483 
lease_parse_static_routes(sd_dhcp_lease * lease,const uint8_t * option,size_t len)484 static int lease_parse_static_routes(sd_dhcp_lease *lease, const uint8_t *option, size_t len) {
485         int r;
486 
487         assert(lease);
488         assert(option || len <= 0);
489 
490         if (len % 8 != 0)
491                 return -EINVAL;
492 
493         while (len >= 8) {
494                 struct in_addr dst, gw;
495                 uint8_t prefixlen;
496 
497                 assert_se(lease_parse_be32(option, 4, &dst.s_addr) >= 0);
498                 option += 4;
499 
500                 assert_se(lease_parse_be32(option, 4, &gw.s_addr) >= 0);
501                 option += 4;
502 
503                 len -= 8;
504 
505                 r = in4_addr_default_prefixlen(&dst, &prefixlen);
506                 if (r < 0) {
507                         log_debug("sd-dhcp-lease: cannot determine class of received static route, ignoring.");
508                         continue;
509                 }
510 
511                 (void) in4_addr_mask(&dst, prefixlen);
512 
513                 if (!GREEDY_REALLOC(lease->static_routes, lease->n_static_routes + 1))
514                         return -ENOMEM;
515 
516                 lease->static_routes[lease->n_static_routes++] = (struct sd_dhcp_route) {
517                         .dst_addr = dst,
518                         .gw_addr = gw,
519                         .dst_prefixlen = prefixlen,
520                 };
521         }
522 
523         return 0;
524 }
525 
526 /* parses RFC3442 Classless Static Route Option */
lease_parse_classless_routes(sd_dhcp_lease * lease,const uint8_t * option,size_t len)527 static int lease_parse_classless_routes(sd_dhcp_lease *lease, const uint8_t *option, size_t len) {
528         assert(lease);
529         assert(option || len <= 0);
530 
531         /* option format: (subnet-mask-width significant-subnet-octets gateway-ip) */
532 
533         while (len > 0) {
534                 uint8_t prefixlen, dst_octets;
535                 struct in_addr dst = {}, gw;
536 
537                 prefixlen = *option;
538                 option++;
539                 len--;
540 
541                 dst_octets = DIV_ROUND_UP(prefixlen, 8);
542 
543                 /* can't have more than 4 octets in IPv4 */
544                 if (dst_octets > 4 || len < dst_octets)
545                         return -EINVAL;
546 
547                 memcpy(&dst, option, dst_octets);
548                 option += dst_octets;
549                 len -= dst_octets;
550 
551                 if (len < 4)
552                         return -EINVAL;
553 
554                 assert_se(lease_parse_be32(option, 4, &gw.s_addr) >= 0);
555                 option += 4;
556                 len -= 4;
557 
558                 if (!GREEDY_REALLOC(lease->classless_routes, lease->n_classless_routes + 1))
559                         return -ENOMEM;
560 
561                 lease->classless_routes[lease->n_classless_routes++] = (struct sd_dhcp_route) {
562                         .dst_addr = dst,
563                         .gw_addr = gw,
564                         .dst_prefixlen = prefixlen,
565                 };
566         }
567 
568         return 0;
569 }
570 
lease_parse_6rd(sd_dhcp_lease * lease,const uint8_t * option,size_t len)571 static int lease_parse_6rd(sd_dhcp_lease *lease, const uint8_t *option, size_t len) {
572         uint8_t ipv4masklen, prefixlen;
573         struct in6_addr prefix;
574         _cleanup_free_ struct in_addr *br_addresses = NULL;
575         size_t n_br_addresses;
576 
577         assert(lease);
578         assert(option);
579 
580         /* See RFC 5969 Section 7.1.1 */
581 
582         if (lease->sixrd_n_br_addresses > 0)
583                 /* Multiple 6rd option?? */
584                 return -EINVAL;
585 
586         /* option-length: The length of the DHCP option in octets (22 octets with one BR IPv4 address). */
587         if (len < 2 + sizeof(struct in6_addr) + sizeof(struct in_addr) ||
588             (len - 2 - sizeof(struct in6_addr)) % sizeof(struct in_addr) != 0)
589                 return -EINVAL;
590 
591         /* IPv4MaskLen: The number of high-order bits that are identical across all CE IPv4 addresses
592          *              within a given 6rd domain. This may be any value between 0 and 32. Any value
593          *              greater than 32 is invalid. */
594         ipv4masklen = option[0];
595         if (ipv4masklen > 32)
596                 return -EINVAL;
597 
598         /* 6rdPrefixLen: The IPv6 prefix length of the SP's 6rd IPv6 prefix in number of bits. For the
599          *               purpose of bounds checking by DHCP option processing, the sum of
600          *               (32 - IPv4MaskLen) + 6rdPrefixLen MUST be less than or equal to 128. */
601         prefixlen = option[1];
602         if (32 - ipv4masklen + prefixlen > 128)
603                 return -EINVAL;
604 
605         /* 6rdPrefix: The service provider's 6rd IPv6 prefix represented as a 16-octet IPv6 address.
606          *            The bits in the prefix after the 6rdPrefixlen number of bits are reserved and
607          *            MUST be initialized to zero by the sender and ignored by the receiver. */
608         memcpy(&prefix, option + 2, sizeof(struct in6_addr));
609         (void) in6_addr_mask(&prefix, prefixlen);
610 
611         /* 6rdBRIPv4Address: One or more IPv4 addresses of the 6rd Border Relay(s) for a given 6rd domain. */
612         n_br_addresses = (len - 2 - sizeof(struct in6_addr)) / sizeof(struct in_addr);
613         br_addresses = newdup(struct in_addr, option + 2 + sizeof(struct in6_addr), n_br_addresses);
614         if (!br_addresses)
615                 return -ENOMEM;
616 
617         lease->sixrd_ipv4masklen = ipv4masklen;
618         lease->sixrd_prefixlen = prefixlen;
619         lease->sixrd_prefix = prefix;
620         lease->sixrd_br_addresses = TAKE_PTR(br_addresses);
621         lease->sixrd_n_br_addresses = n_br_addresses;
622 
623         return 0;
624 }
625 
dhcp_lease_parse_options(uint8_t code,uint8_t len,const void * option,void * userdata)626 int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
627         sd_dhcp_lease *lease = userdata;
628         int r;
629 
630         assert(lease);
631 
632         switch (code) {
633 
634         case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
635                 r = lease_parse_u32(option, len, &lease->lifetime, 1);
636                 if (r < 0)
637                         log_debug_errno(r, "Failed to parse lease time, ignoring: %m");
638 
639                 break;
640 
641         case SD_DHCP_OPTION_SERVER_IDENTIFIER:
642                 r = lease_parse_be32(option, len, &lease->server_address);
643                 if (r < 0)
644                         log_debug_errno(r, "Failed to parse server identifier, ignoring: %m");
645 
646                 break;
647 
648         case SD_DHCP_OPTION_SUBNET_MASK:
649                 r = lease_parse_be32(option, len, &lease->subnet_mask);
650                 if (r < 0)
651                         log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m");
652                 else
653                         lease->have_subnet_mask = true;
654                 break;
655 
656         case SD_DHCP_OPTION_BROADCAST:
657                 r = lease_parse_be32(option, len, &lease->broadcast);
658                 if (r < 0)
659                         log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m");
660                 else
661                         lease->have_broadcast = true;
662                 break;
663 
664         case SD_DHCP_OPTION_ROUTER:
665                 r = lease_parse_in_addrs(option, len, &lease->router, &lease->router_size);
666                 if (r < 0)
667                         log_debug_errno(r, "Failed to parse router addresses, ignoring: %m");
668                 break;
669 
670         case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
671                 r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_DNS].addr, &lease->servers[SD_DHCP_LEASE_DNS].size);
672                 if (r < 0)
673                         log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");
674                 break;
675 
676         case SD_DHCP_OPTION_NTP_SERVER:
677                 r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_NTP].addr, &lease->servers[SD_DHCP_LEASE_NTP].size);
678                 if (r < 0)
679                         log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
680                 break;
681 
682         case SD_DHCP_OPTION_SIP_SERVER:
683                 r = lease_parse_sip_server(option, len, &lease->servers[SD_DHCP_LEASE_SIP].addr, &lease->servers[SD_DHCP_LEASE_SIP].size);
684                 if (r < 0)
685                         log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
686                 break;
687 
688         case SD_DHCP_OPTION_POP3_SERVER:
689                 r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_POP3].addr, &lease->servers[SD_DHCP_LEASE_POP3].size);
690                 if (r < 0)
691                         log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m");
692                 break;
693 
694         case SD_DHCP_OPTION_SMTP_SERVER:
695                 r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_SMTP].addr, &lease->servers[SD_DHCP_LEASE_SMTP].size);
696                 if (r < 0)
697                         log_debug_errno(r, "Failed to parse SMTP server, ignoring: %m");
698                 break;
699 
700         case SD_DHCP_OPTION_LPR_SERVER:
701                 r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_LPR].addr, &lease->servers[SD_DHCP_LEASE_LPR].size);
702                 if (r < 0)
703                         log_debug_errno(r, "Failed to parse LPR server, ignoring: %m");
704                 break;
705 
706         case SD_DHCP_OPTION_STATIC_ROUTE:
707                 r = lease_parse_static_routes(lease, option, len);
708                 if (r < 0)
709                         log_debug_errno(r, "Failed to parse static routes, ignoring: %m");
710                 break;
711 
712         case SD_DHCP_OPTION_MTU_INTERFACE:
713                 r = lease_parse_u16(option, len, &lease->mtu, 68);
714                 if (r < 0)
715                         log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
716                 if (lease->mtu < DHCP_DEFAULT_MIN_SIZE) {
717                         log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_DEFAULT_MIN_SIZE);
718                         lease->mtu = DHCP_DEFAULT_MIN_SIZE;
719                 }
720 
721                 break;
722 
723         case SD_DHCP_OPTION_DOMAIN_NAME:
724                 r = lease_parse_domain(option, len, &lease->domainname);
725                 if (r < 0) {
726                         log_debug_errno(r, "Failed to parse domain name, ignoring: %m");
727                         return 0;
728                 }
729 
730                 break;
731 
732         case SD_DHCP_OPTION_DOMAIN_SEARCH:
733                 r = dhcp_lease_parse_search_domains(option, len, &lease->search_domains);
734                 if (r < 0)
735                         log_debug_errno(r, "Failed to parse Domain Search List, ignoring: %m");
736                 break;
737 
738         case SD_DHCP_OPTION_HOST_NAME:
739                 r = lease_parse_domain(option, len, &lease->hostname);
740                 if (r < 0) {
741                         log_debug_errno(r, "Failed to parse hostname, ignoring: %m");
742                         return 0;
743                 }
744 
745                 break;
746 
747         case SD_DHCP_OPTION_ROOT_PATH:
748                 r = lease_parse_string(option, len, &lease->root_path);
749                 if (r < 0)
750                         log_debug_errno(r, "Failed to parse root path, ignoring: %m");
751                 break;
752 
753         case SD_DHCP_OPTION_RENEWAL_TIME:
754                 r = lease_parse_u32(option, len, &lease->t1, 1);
755                 if (r < 0)
756                         log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");
757                 break;
758 
759         case SD_DHCP_OPTION_REBINDING_TIME:
760                 r = lease_parse_u32(option, len, &lease->t2, 1);
761                 if (r < 0)
762                         log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");
763                 break;
764 
765         case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
766                 r = lease_parse_classless_routes(lease, option, len);
767                 if (r < 0)
768                         log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
769                 break;
770 
771         case SD_DHCP_OPTION_TZDB_TIMEZONE: {
772                 _cleanup_free_ char *tz = NULL;
773 
774                 r = lease_parse_string(option, len, &tz);
775                 if (r < 0) {
776                         log_debug_errno(r, "Failed to parse timezone option, ignoring: %m");
777                         return 0;
778                 }
779 
780                 if (!timezone_is_valid(tz, LOG_DEBUG)) {
781                         log_debug("Timezone is not valid, ignoring.");
782                         return 0;
783                 }
784 
785                 free_and_replace(lease->timezone, tz);
786 
787                 break;
788         }
789 
790         case SD_DHCP_OPTION_VENDOR_SPECIFIC:
791 
792                 if (len <= 0)
793                         lease->vendor_specific = mfree(lease->vendor_specific);
794                 else {
795                         void *p;
796 
797                         p = memdup(option, len);
798                         if (!p)
799                                 return -ENOMEM;
800 
801                         free(lease->vendor_specific);
802                         lease->vendor_specific = p;
803                 }
804 
805                 lease->vendor_specific_len = len;
806                 break;
807 
808         case SD_DHCP_OPTION_6RD:
809                 r = lease_parse_6rd(lease, option, len);
810                 if (r < 0)
811                         log_debug_errno(r, "Failed to parse 6rd option, ignoring: %m");
812                 break;
813 
814         case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST:
815                 r = dhcp_lease_insert_private_option(lease, code, option, len);
816                 if (r < 0)
817                         return r;
818 
819                 break;
820 
821         default:
822                 log_debug("Ignoring option DHCP option %"PRIu8" while parsing.", code);
823                 break;
824         }
825 
826         return 0;
827 }
828 
829 /* Parses compressed domain names. */
dhcp_lease_parse_search_domains(const uint8_t * option,size_t len,char *** domains)830 int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains) {
831         _cleanup_strv_free_ char **names = NULL;
832         size_t pos = 0, cnt = 0;
833         int r;
834 
835         assert(domains);
836         assert_return(option && len > 0, -ENODATA);
837 
838         while (pos < len) {
839                 _cleanup_free_ char *name = NULL;
840                 size_t n = 0;
841                 size_t jump_barrier = pos, next_chunk = 0;
842                 bool first = true;
843 
844                 for (;;) {
845                         uint8_t c;
846                         c = option[pos++];
847 
848                         if (c == 0) {
849                                 /* End of name */
850                                 break;
851                         } else if (c <= 63) {
852                                 const char *label;
853 
854                                 /* Literal label */
855                                 label = (const char*) (option + pos);
856                                 pos += c;
857                                 if (pos >= len)
858                                         return -EBADMSG;
859 
860                                 if (!GREEDY_REALLOC(name, n + !first + DNS_LABEL_ESCAPED_MAX))
861                                         return -ENOMEM;
862 
863                                 if (first)
864                                         first = false;
865                                 else
866                                         name[n++] = '.';
867 
868                                 r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX);
869                                 if (r < 0)
870                                         return r;
871 
872                                 n += r;
873                         } else if (FLAGS_SET(c, 0xc0)) {
874                                 /* Pointer */
875 
876                                 uint8_t d;
877                                 uint16_t ptr;
878 
879                                 if (pos >= len)
880                                         return -EBADMSG;
881 
882                                 d = option[pos++];
883                                 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
884 
885                                 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
886                                 if (ptr >= jump_barrier)
887                                         return -EBADMSG;
888                                 jump_barrier = ptr;
889 
890                                 /* Save current location so we don't end up re-parsing what's parsed so far. */
891                                 if (next_chunk == 0)
892                                         next_chunk = pos;
893 
894                                 pos = ptr;
895                         } else
896                                 return -EBADMSG;
897                 }
898 
899                 if (!GREEDY_REALLOC(name, n + 1))
900                         return -ENOMEM;
901                 name[n] = 0;
902 
903                 r = strv_extend(&names, name);
904                 if (r < 0)
905                         return r;
906 
907                 cnt++;
908 
909                 if (next_chunk != 0)
910                       pos = next_chunk;
911         }
912 
913         strv_free_and_replace(*domains, names);
914 
915         return cnt;
916 }
917 
dhcp_lease_insert_private_option(sd_dhcp_lease * lease,uint8_t tag,const void * data,uint8_t len)918 int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) {
919         struct sd_dhcp_raw_option *option, *before = NULL;
920 
921         assert(lease);
922 
923         LIST_FOREACH(options, cur, lease->private_options) {
924                 if (tag < cur->tag) {
925                         before = cur;
926                         break;
927                 }
928                 if (tag == cur->tag) {
929                         log_debug("Ignoring duplicate option, tagged %i.", tag);
930                         return 0;
931                 }
932         }
933 
934         option = new(struct sd_dhcp_raw_option, 1);
935         if (!option)
936                 return -ENOMEM;
937 
938         option->tag = tag;
939         option->length = len;
940         option->data = memdup(data, len);
941         if (!option->data) {
942                 free(option);
943                 return -ENOMEM;
944         }
945 
946         LIST_INSERT_BEFORE(options, lease->private_options, before, option);
947         return 0;
948 }
949 
dhcp_lease_new(sd_dhcp_lease ** ret)950 int dhcp_lease_new(sd_dhcp_lease **ret) {
951         sd_dhcp_lease *lease;
952 
953         lease = new0(sd_dhcp_lease, 1);
954         if (!lease)
955                 return -ENOMEM;
956 
957         lease->n_ref = 1;
958 
959         *ret = lease;
960         return 0;
961 }
962 
dhcp_lease_save(sd_dhcp_lease * lease,const char * lease_file)963 int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
964         _cleanup_(unlink_and_freep) char *temp_path = NULL;
965         _cleanup_fclose_ FILE *f = NULL;
966         struct in_addr address;
967         const struct in_addr *addresses;
968         const void *client_id, *data;
969         size_t client_id_len, data_len;
970         char sbuf[INET_ADDRSTRLEN];
971         const char *string;
972         uint16_t mtu;
973         _cleanup_free_ sd_dhcp_route **routes = NULL;
974         char **search_domains;
975         uint32_t t1, t2, lifetime;
976         int r;
977 
978         assert(lease);
979         assert(lease_file);
980 
981         r = fopen_temporary(lease_file, &f, &temp_path);
982         if (r < 0)
983                 return r;
984 
985         (void) fchmod(fileno(f), 0644);
986 
987         fprintf(f,
988                 "# This is private data. Do not parse.\n");
989 
990         r = sd_dhcp_lease_get_address(lease, &address);
991         if (r >= 0)
992                 fprintf(f, "ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
993 
994         r = sd_dhcp_lease_get_netmask(lease, &address);
995         if (r >= 0)
996                 fprintf(f, "NETMASK=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
997 
998         r = sd_dhcp_lease_get_router(lease, &addresses);
999         if (r > 0) {
1000                 fputs("ROUTER=", f);
1001                 serialize_in_addrs(f, addresses, r, false, NULL);
1002                 fputc('\n', f);
1003         }
1004 
1005         r = sd_dhcp_lease_get_server_identifier(lease, &address);
1006         if (r >= 0)
1007                 fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
1008 
1009         r = sd_dhcp_lease_get_next_server(lease, &address);
1010         if (r >= 0)
1011                 fprintf(f, "NEXT_SERVER=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
1012 
1013         r = sd_dhcp_lease_get_broadcast(lease, &address);
1014         if (r >= 0)
1015                 fprintf(f, "BROADCAST=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
1016 
1017         r = sd_dhcp_lease_get_mtu(lease, &mtu);
1018         if (r >= 0)
1019                 fprintf(f, "MTU=%" PRIu16 "\n", mtu);
1020 
1021         r = sd_dhcp_lease_get_t1(lease, &t1);
1022         if (r >= 0)
1023                 fprintf(f, "T1=%" PRIu32 "\n", t1);
1024 
1025         r = sd_dhcp_lease_get_t2(lease, &t2);
1026         if (r >= 0)
1027                 fprintf(f, "T2=%" PRIu32 "\n", t2);
1028 
1029         r = sd_dhcp_lease_get_lifetime(lease, &lifetime);
1030         if (r >= 0)
1031                 fprintf(f, "LIFETIME=%" PRIu32 "\n", lifetime);
1032 
1033         r = sd_dhcp_lease_get_dns(lease, &addresses);
1034         if (r > 0) {
1035                 fputs("DNS=", f);
1036                 serialize_in_addrs(f, addresses, r, false, NULL);
1037                 fputc('\n', f);
1038         }
1039 
1040         r = sd_dhcp_lease_get_ntp(lease, &addresses);
1041         if (r > 0) {
1042                 fputs("NTP=", f);
1043                 serialize_in_addrs(f, addresses, r, false, NULL);
1044                 fputc('\n', f);
1045         }
1046 
1047         r = sd_dhcp_lease_get_sip(lease, &addresses);
1048         if (r > 0) {
1049                 fputs("SIP=", f);
1050                 serialize_in_addrs(f, addresses, r, false, NULL);
1051                 fputc('\n', f);
1052         }
1053 
1054         r = sd_dhcp_lease_get_domainname(lease, &string);
1055         if (r >= 0)
1056                 fprintf(f, "DOMAINNAME=%s\n", string);
1057 
1058         r = sd_dhcp_lease_get_search_domains(lease, &search_domains);
1059         if (r > 0) {
1060                 fputs("DOMAIN_SEARCH_LIST=", f);
1061                 fputstrv(f, search_domains, NULL, NULL);
1062                 fputc('\n', f);
1063         }
1064 
1065         r = sd_dhcp_lease_get_hostname(lease, &string);
1066         if (r >= 0)
1067                 fprintf(f, "HOSTNAME=%s\n", string);
1068 
1069         r = sd_dhcp_lease_get_root_path(lease, &string);
1070         if (r >= 0)
1071                 fprintf(f, "ROOT_PATH=%s\n", string);
1072 
1073         r = sd_dhcp_lease_get_static_routes(lease, &routes);
1074         if (r > 0)
1075                 serialize_dhcp_routes(f, "STATIC_ROUTES", routes, r);
1076 
1077         routes = mfree(routes);
1078         r = sd_dhcp_lease_get_classless_routes(lease, &routes);
1079         if (r > 0)
1080                 serialize_dhcp_routes(f, "CLASSLESS_ROUTES", routes, r);
1081 
1082         r = sd_dhcp_lease_get_timezone(lease, &string);
1083         if (r >= 0)
1084                 fprintf(f, "TIMEZONE=%s\n", string);
1085 
1086         r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
1087         if (r >= 0) {
1088                 _cleanup_free_ char *client_id_hex = NULL;
1089 
1090                 client_id_hex = hexmem(client_id, client_id_len);
1091                 if (!client_id_hex)
1092                         return -ENOMEM;
1093                 fprintf(f, "CLIENTID=%s\n", client_id_hex);
1094         }
1095 
1096         r = sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len);
1097         if (r >= 0) {
1098                 _cleanup_free_ char *option_hex = NULL;
1099 
1100                 option_hex = hexmem(data, data_len);
1101                 if (!option_hex)
1102                         return -ENOMEM;
1103                 fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex);
1104         }
1105 
1106         LIST_FOREACH(options, option, lease->private_options) {
1107                 char key[STRLEN("OPTION_000")+1];
1108 
1109                 xsprintf(key, "OPTION_%" PRIu8, option->tag);
1110                 r = serialize_dhcp_option(f, key, option->data, option->length);
1111                 if (r < 0)
1112                         return r;
1113         }
1114 
1115         r = fflush_and_check(f);
1116         if (r < 0)
1117                 return r;
1118 
1119         r = conservative_rename(temp_path, lease_file);
1120         if (r < 0)
1121                 return r;
1122 
1123         temp_path = mfree(temp_path);
1124 
1125         return 0;
1126 }
1127 
private_options_free(char ** options)1128 static char **private_options_free(char **options) {
1129         if (!options)
1130                 return NULL;
1131 
1132         for (unsigned i = 0; i < SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1; i++)
1133                 free(options[i]);
1134 
1135         return mfree(options);
1136 }
1137 
1138 DEFINE_TRIVIAL_CLEANUP_FUNC(char**, private_options_free);
1139 
dhcp_lease_load(sd_dhcp_lease ** ret,const char * lease_file)1140 int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
1141         _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1142         _cleanup_free_ char
1143                 *address = NULL,
1144                 *router = NULL,
1145                 *netmask = NULL,
1146                 *server_address = NULL,
1147                 *next_server = NULL,
1148                 *broadcast = NULL,
1149                 *dns = NULL,
1150                 *ntp = NULL,
1151                 *sip = NULL,
1152                 *pop3 = NULL,
1153                 *smtp = NULL,
1154                 *lpr = NULL,
1155                 *mtu = NULL,
1156                 *static_routes = NULL,
1157                 *classless_routes = NULL,
1158                 *domains = NULL,
1159                 *client_id_hex = NULL,
1160                 *vendor_specific_hex = NULL,
1161                 *lifetime = NULL,
1162                 *t1 = NULL,
1163                 *t2 = NULL;
1164         _cleanup_(private_options_freep) char **options = NULL;
1165 
1166         int r, i;
1167 
1168         assert(lease_file);
1169         assert(ret);
1170 
1171         r = dhcp_lease_new(&lease);
1172         if (r < 0)
1173                 return r;
1174 
1175         options = new0(char*, SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1);
1176         if (!options)
1177                 return -ENOMEM;
1178 
1179         r = parse_env_file(NULL, lease_file,
1180                            "ADDRESS", &address,
1181                            "ROUTER", &router,
1182                            "NETMASK", &netmask,
1183                            "SERVER_ADDRESS", &server_address,
1184                            "NEXT_SERVER", &next_server,
1185                            "BROADCAST", &broadcast,
1186                            "DNS", &dns,
1187                            "NTP", &ntp,
1188                            "SIP", &sip,
1189                            "POP3", &pop3,
1190                            "SMTP", &smtp,
1191                            "LPR", &lpr,
1192                            "MTU", &mtu,
1193                            "DOMAINNAME", &lease->domainname,
1194                            "HOSTNAME", &lease->hostname,
1195                            "DOMAIN_SEARCH_LIST", &domains,
1196                            "ROOT_PATH", &lease->root_path,
1197                            "STATIC_ROUTES", &static_routes,
1198                            "CLASSLESS_ROUTES", &classless_routes,
1199                            "CLIENTID", &client_id_hex,
1200                            "TIMEZONE", &lease->timezone,
1201                            "VENDOR_SPECIFIC", &vendor_specific_hex,
1202                            "LIFETIME", &lifetime,
1203                            "T1", &t1,
1204                            "T2", &t2,
1205                            "OPTION_224", &options[0],
1206                            "OPTION_225", &options[1],
1207                            "OPTION_226", &options[2],
1208                            "OPTION_227", &options[3],
1209                            "OPTION_228", &options[4],
1210                            "OPTION_229", &options[5],
1211                            "OPTION_230", &options[6],
1212                            "OPTION_231", &options[7],
1213                            "OPTION_232", &options[8],
1214                            "OPTION_233", &options[9],
1215                            "OPTION_234", &options[10],
1216                            "OPTION_235", &options[11],
1217                            "OPTION_236", &options[12],
1218                            "OPTION_237", &options[13],
1219                            "OPTION_238", &options[14],
1220                            "OPTION_239", &options[15],
1221                            "OPTION_240", &options[16],
1222                            "OPTION_241", &options[17],
1223                            "OPTION_242", &options[18],
1224                            "OPTION_243", &options[19],
1225                            "OPTION_244", &options[20],
1226                            "OPTION_245", &options[21],
1227                            "OPTION_246", &options[22],
1228                            "OPTION_247", &options[23],
1229                            "OPTION_248", &options[24],
1230                            "OPTION_249", &options[25],
1231                            "OPTION_250", &options[26],
1232                            "OPTION_251", &options[27],
1233                            "OPTION_252", &options[28],
1234                            "OPTION_253", &options[29],
1235                            "OPTION_254", &options[30]);
1236         if (r < 0)
1237                 return r;
1238 
1239         if (address) {
1240                 r = inet_pton(AF_INET, address, &lease->address);
1241                 if (r <= 0)
1242                         log_debug("Failed to parse address %s, ignoring.", address);
1243         }
1244 
1245         if (router) {
1246                 r = deserialize_in_addrs(&lease->router, router);
1247                 if (r < 0)
1248                         log_debug_errno(r, "Failed to deserialize router addresses %s, ignoring: %m", router);
1249                 else
1250                         lease->router_size = r;
1251         }
1252 
1253         if (netmask) {
1254                 r = inet_pton(AF_INET, netmask, &lease->subnet_mask);
1255                 if (r <= 0)
1256                         log_debug("Failed to parse netmask %s, ignoring.", netmask);
1257                 else
1258                         lease->have_subnet_mask = true;
1259         }
1260 
1261         if (server_address) {
1262                 r = inet_pton(AF_INET, server_address, &lease->server_address);
1263                 if (r <= 0)
1264                         log_debug("Failed to parse server address %s, ignoring.", server_address);
1265         }
1266 
1267         if (next_server) {
1268                 r = inet_pton(AF_INET, next_server, &lease->next_server);
1269                 if (r <= 0)
1270                         log_debug("Failed to parse next server %s, ignoring.", next_server);
1271         }
1272 
1273         if (broadcast) {
1274                 r = inet_pton(AF_INET, broadcast, &lease->broadcast);
1275                 if (r <= 0)
1276                         log_debug("Failed to parse broadcast address %s, ignoring.", broadcast);
1277                 else
1278                         lease->have_broadcast = true;
1279         }
1280 
1281         if (dns) {
1282                 r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_DNS].addr, dns);
1283                 if (r < 0)
1284                         log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns);
1285                 else
1286                         lease->servers[SD_DHCP_LEASE_DNS].size = r;
1287         }
1288 
1289         if (ntp) {
1290                 r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_NTP].addr, ntp);
1291                 if (r < 0)
1292                         log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp);
1293                 else
1294                         lease->servers[SD_DHCP_LEASE_NTP].size = r;
1295         }
1296 
1297         if (sip) {
1298                 r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SIP].addr, sip);
1299                 if (r < 0)
1300                         log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip);
1301                 else
1302                         lease->servers[SD_DHCP_LEASE_SIP].size = r;
1303         }
1304 
1305         if (pop3) {
1306                 r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_POP3].addr, pop3);
1307                 if (r < 0)
1308                         log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3);
1309                 else
1310                         lease->servers[SD_DHCP_LEASE_POP3].size = r;
1311         }
1312 
1313         if (smtp) {
1314                 r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SMTP].addr, smtp);
1315                 if (r < 0)
1316                         log_debug_errno(r, "Failed to deserialize SMTP server %s, ignoring: %m", smtp);
1317                 else
1318                         lease->servers[SD_DHCP_LEASE_SMTP].size = r;
1319         }
1320 
1321         if (lpr) {
1322                 r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_LPR].addr, lpr);
1323                 if (r < 0)
1324                         log_debug_errno(r, "Failed to deserialize LPR server %s, ignoring: %m", lpr);
1325                 else
1326                         lease->servers[SD_DHCP_LEASE_LPR].size = r;
1327         }
1328 
1329         if (mtu) {
1330                 r = safe_atou16(mtu, &lease->mtu);
1331                 if (r < 0)
1332                         log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu);
1333         }
1334 
1335         if (domains) {
1336                 _cleanup_strv_free_ char **a = NULL;
1337                 a = strv_split(domains, " ");
1338                 if (!a)
1339                         return -ENOMEM;
1340 
1341                 if (!strv_isempty(a))
1342                         lease->search_domains = TAKE_PTR(a);
1343         }
1344 
1345         if (static_routes) {
1346                 r = deserialize_dhcp_routes(
1347                                 &lease->static_routes,
1348                                 &lease->n_static_routes,
1349                                 static_routes);
1350                 if (r < 0)
1351                         log_debug_errno(r, "Failed to parse DHCP static routes %s, ignoring: %m", static_routes);
1352         }
1353 
1354         if (classless_routes) {
1355                 r = deserialize_dhcp_routes(
1356                                 &lease->classless_routes,
1357                                 &lease->n_classless_routes,
1358                                 classless_routes);
1359                 if (r < 0)
1360                         log_debug_errno(r, "Failed to parse DHCP classless routes %s, ignoring: %m", classless_routes);
1361         }
1362 
1363         if (lifetime) {
1364                 r = safe_atou32(lifetime, &lease->lifetime);
1365                 if (r < 0)
1366                         log_debug_errno(r, "Failed to parse lifetime %s, ignoring: %m", lifetime);
1367         }
1368 
1369         if (t1) {
1370                 r = safe_atou32(t1, &lease->t1);
1371                 if (r < 0)
1372                         log_debug_errno(r, "Failed to parse T1 %s, ignoring: %m", t1);
1373         }
1374 
1375         if (t2) {
1376                 r = safe_atou32(t2, &lease->t2);
1377                 if (r < 0)
1378                         log_debug_errno(r, "Failed to parse T2 %s, ignoring: %m", t2);
1379         }
1380 
1381         if (client_id_hex) {
1382                 r = unhexmem(client_id_hex, SIZE_MAX, &lease->client_id, &lease->client_id_len);
1383                 if (r < 0)
1384                         log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);
1385         }
1386 
1387         if (vendor_specific_hex) {
1388                 r = unhexmem(vendor_specific_hex, SIZE_MAX, &lease->vendor_specific, &lease->vendor_specific_len);
1389                 if (r < 0)
1390                         log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
1391         }
1392 
1393         for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) {
1394                 _cleanup_free_ void *data = NULL;
1395                 size_t len;
1396 
1397                 if (!options[i])
1398                         continue;
1399 
1400                 r = unhexmem(options[i], SIZE_MAX, &data, &len);
1401                 if (r < 0) {
1402                         log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]);
1403                         continue;
1404                 }
1405 
1406                 r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len);
1407                 if (r < 0)
1408                         return r;
1409         }
1410 
1411         *ret = TAKE_PTR(lease);
1412 
1413         return 0;
1414 }
1415 
dhcp_lease_set_default_subnet_mask(sd_dhcp_lease * lease)1416 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
1417         struct in_addr address, mask;
1418         int r;
1419 
1420         assert(lease);
1421 
1422         if (lease->address == 0)
1423                 return -ENODATA;
1424 
1425         address.s_addr = lease->address;
1426 
1427         /* fall back to the default subnet masks based on address class */
1428         r = in4_addr_default_subnet_mask(&address, &mask);
1429         if (r < 0)
1430                 return r;
1431 
1432         lease->subnet_mask = mask.s_addr;
1433         lease->have_subnet_mask = true;
1434 
1435         return 0;
1436 }
1437 
sd_dhcp_lease_get_client_id(sd_dhcp_lease * lease,const void ** client_id,size_t * client_id_len)1438 int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) {
1439         assert_return(lease, -EINVAL);
1440         assert_return(client_id, -EINVAL);
1441         assert_return(client_id_len, -EINVAL);
1442 
1443         if (!lease->client_id)
1444                 return -ENODATA;
1445 
1446         *client_id = lease->client_id;
1447         *client_id_len = lease->client_id_len;
1448 
1449         return 0;
1450 }
1451 
dhcp_lease_set_client_id(sd_dhcp_lease * lease,const void * client_id,size_t client_id_len)1452 int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) {
1453         assert_return(lease, -EINVAL);
1454         assert_return(client_id || client_id_len <= 0, -EINVAL);
1455 
1456         if (client_id_len <= 0)
1457                 lease->client_id = mfree(lease->client_id);
1458         else {
1459                 void *p;
1460 
1461                 p = memdup(client_id, client_id_len);
1462                 if (!p)
1463                         return -ENOMEM;
1464 
1465                 free(lease->client_id);
1466                 lease->client_id = p;
1467                 lease->client_id_len = client_id_len;
1468         }
1469 
1470         return 0;
1471 }
1472 
sd_dhcp_lease_get_timezone(sd_dhcp_lease * lease,const char ** tz)1473 int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
1474         assert_return(lease, -EINVAL);
1475         assert_return(tz, -EINVAL);
1476 
1477         if (!lease->timezone)
1478                 return -ENODATA;
1479 
1480         *tz = lease->timezone;
1481         return 0;
1482 }
1483 
sd_dhcp_route_get_destination(sd_dhcp_route * route,struct in_addr * destination)1484 int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) {
1485         assert_return(route, -EINVAL);
1486         assert_return(destination, -EINVAL);
1487 
1488         *destination = route->dst_addr;
1489         return 0;
1490 }
1491 
sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route * route,uint8_t * length)1492 int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) {
1493         assert_return(route, -EINVAL);
1494         assert_return(length, -EINVAL);
1495 
1496         *length = route->dst_prefixlen;
1497         return 0;
1498 }
1499 
sd_dhcp_route_get_gateway(sd_dhcp_route * route,struct in_addr * gateway)1500 int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
1501         assert_return(route, -EINVAL);
1502         assert_return(gateway, -EINVAL);
1503 
1504         *gateway = route->gw_addr;
1505         return 0;
1506 }
1507