]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-lease.c
treewide: more log_*_errno + return simplifications
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp-lease.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5 Copyright (C) 2014 Tom Gundersen
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 <stdlib.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <net/ethernet.h>
26 #include <arpa/inet.h>
27 #include <sys/param.h>
28
29 #include "util.h"
30 #include "list.h"
31 #include "mkdir.h"
32 #include "fileio.h"
33 #include "unaligned.h"
34 #include "in-addr-util.h"
35
36 #include "dhcp-protocol.h"
37 #include "dhcp-internal.h"
38 #include "dhcp-lease-internal.h"
39 #include "sd-dhcp-lease.h"
40 #include "sd-dhcp-client.h"
41 #include "network-internal.h"
42
43 int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
44 assert_return(lease, -EINVAL);
45 assert_return(addr, -EINVAL);
46
47 addr->s_addr = lease->address;
48
49 return 0;
50 }
51
52 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
53 assert_return(lease, -EINVAL);
54 assert_return(lifetime, -EINVAL);
55
56 *lifetime = lease->lifetime;
57
58 return 0;
59 }
60
61 int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
62 assert_return(lease, -EINVAL);
63 assert_return(mtu, -EINVAL);
64
65 if (lease->mtu)
66 *mtu = lease->mtu;
67 else
68 return -ENOENT;
69
70 return 0;
71 }
72
73 int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {
74 assert_return(lease, -EINVAL);
75 assert_return(addr, -EINVAL);
76
77 if (lease->dns_size) {
78 *addr = lease->dns;
79 return lease->dns_size;
80 } else
81 return -ENOENT;
82
83 return 0;
84 }
85
86 int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
87 assert_return(lease, -EINVAL);
88 assert_return(addr, -EINVAL);
89
90 if (lease->ntp_size) {
91 *addr = lease->ntp;
92 return lease->ntp_size;
93 } else
94 return -ENOENT;
95
96 return 0;
97 }
98
99 int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
100 assert_return(lease, -EINVAL);
101 assert_return(domainname, -EINVAL);
102
103 if (lease->domainname)
104 *domainname = lease->domainname;
105 else
106 return -ENOENT;
107
108 return 0;
109 }
110
111 int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
112 assert_return(lease, -EINVAL);
113 assert_return(hostname, -EINVAL);
114
115 if (lease->hostname)
116 *hostname = lease->hostname;
117 else
118 return -ENOENT;
119
120 return 0;
121 }
122
123 int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
124 assert_return(lease, -EINVAL);
125 assert_return(root_path, -EINVAL);
126
127 if (lease->root_path)
128 *root_path = lease->root_path;
129 else
130 return -ENOENT;
131
132 return 0;
133 }
134
135 int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
136 assert_return(lease, -EINVAL);
137 assert_return(addr, -EINVAL);
138
139 if (lease->router != INADDR_ANY)
140 addr->s_addr = lease->router;
141 else
142 return -ENOENT;
143
144 return 0;
145 }
146
147 int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
148 assert_return(lease, -EINVAL);
149 assert_return(addr, -EINVAL);
150
151 addr->s_addr = lease->subnet_mask;
152
153 return 0;
154 }
155
156 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) {
157 assert_return(lease, -EINVAL);
158 assert_return(addr, -EINVAL);
159
160 addr->s_addr = lease->server_address;
161
162 return 0;
163 }
164
165 int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
166 assert_return(lease, -EINVAL);
167 assert_return(addr, -EINVAL);
168
169 addr->s_addr = lease->next_server;
170
171 return 0;
172 }
173
174 int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) {
175
176 assert_return(lease, -EINVAL);
177 assert_return(routes, -EINVAL);
178
179 if (lease->static_route_size) {
180 *routes = lease->static_route;
181 return lease->static_route_size;
182 } else
183 return -ENOENT;
184
185 return 0;
186 }
187
188 sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
189 if (lease)
190 assert_se(REFCNT_INC(lease->n_ref) >= 2);
191
192 return lease;
193 }
194
195 sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
196 if (lease && REFCNT_DEC(lease->n_ref) <= 0) {
197 free(lease->hostname);
198 free(lease->domainname);
199 free(lease->dns);
200 free(lease->ntp);
201 free(lease->static_route);
202 free(lease->client_id);
203 free(lease);
204 }
205
206 return NULL;
207 }
208
209 static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
210 assert(option);
211 assert(ret);
212
213 if (len == 4) {
214 *ret = unaligned_read_be32((be32_t*) option);
215
216 if (*ret < min)
217 *ret = min;
218 }
219 }
220
221 static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) {
222 lease_parse_u32(option, len, (uint32_t *)ret, 0);
223 }
224
225 static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
226 assert(option);
227 assert(ret);
228
229 if (len == 2) {
230 *ret = unaligned_read_be16((be16_t*) option);
231
232 if (*ret < min)
233 *ret = min;
234 }
235 }
236
237 static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
238 assert(option);
239 assert(ret);
240
241 if (len == 4)
242 memcpy(ret, option, 4);
243 }
244
245 static void lease_parse_bool(const uint8_t *option, size_t len, bool *ret) {
246 assert(option);
247 assert(ret);
248
249 if (len == 1)
250 *ret = !!(*option);
251 }
252
253 static void lease_parse_u8(const uint8_t *option, size_t len, uint8_t *ret, uint8_t min) {
254 assert(option);
255 assert(ret);
256
257 if (len == 1) {
258 *ret = *option;
259
260 if (*ret < min)
261 *ret = min;
262 }
263 }
264
265 static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
266 assert(option);
267 assert(ret);
268
269 if (len >= 1) {
270 char *string;
271
272 string = strndup((const char *)option, len);
273 if (!string)
274 return -errno;
275
276 free(*ret);
277 *ret = string;
278 }
279
280 return 0;
281 }
282
283 static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) {
284 assert(option);
285 assert(ret);
286 assert(ret_size);
287
288 if (len && !(len % (4 * mult))) {
289 size_t size;
290 struct in_addr *addresses;
291
292 size = len / 4;
293
294 addresses = newdup(struct in_addr, option, size);
295 if (!addresses)
296 return -ENOMEM;
297
298 free(*ret);
299 *ret = addresses;
300 *ret_size = size;
301 }
302
303 return 0;
304 }
305
306 static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
307 return lease_parse_in_addrs_aux(option, len, ret, ret_size, 1);
308 }
309
310 static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
311 return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2);
312 }
313
314 static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
315 size_t *routes_size, size_t *routes_allocated) {
316
317 struct in_addr addr;
318
319 assert(option);
320 assert(routes);
321 assert(routes_size);
322 assert(routes_allocated);
323
324 if (!len)
325 return 0;
326
327 if (len % 8 != 0)
328 return -EINVAL;
329
330 if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + (len / 8)))
331 return -ENOMEM;
332
333 while (len >= 8) {
334 struct sd_dhcp_route *route = *routes + *routes_size;
335 int r;
336
337 r = in_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen);
338 if (r < 0) {
339 log_error("Failed to determine destination prefix length from class based IP, ignoring");
340 continue;
341 }
342
343 lease_parse_be32(option, 4, &addr.s_addr);
344 route->dst_addr = inet_makeaddr(inet_netof(addr), 0);
345 option += 4;
346
347 lease_parse_be32(option, 4, &route->gw_addr.s_addr);
348 option += 4;
349
350 len -= 8;
351 (*routes_size)++;
352 }
353
354 return 0;
355 }
356
357 /* parses RFC3442 Classless Static Route Option */
358 static int lease_parse_classless_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
359 size_t *routes_size, size_t *routes_allocated) {
360
361 assert(option);
362 assert(routes);
363 assert(routes_size);
364 assert(routes_allocated);
365
366 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
367
368 while (len > 0) {
369 uint8_t dst_octets;
370 struct sd_dhcp_route *route;
371
372 if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1))
373 return -ENOMEM;
374
375 route = *routes + *routes_size;
376
377 dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1);
378 route->dst_prefixlen = *option;
379 option++;
380 len--;
381
382 /* can't have more than 4 octets in IPv4 */
383 if (dst_octets > 4 || len < dst_octets)
384 return -EINVAL;
385
386 route->dst_addr.s_addr = 0;
387 memcpy(&route->dst_addr.s_addr, option, dst_octets);
388 option += dst_octets;
389 len -= dst_octets;
390
391 if (len < 4)
392 return -EINVAL;
393
394 lease_parse_be32(option, 4, &route->gw_addr.s_addr);
395 option += 4;
396 len -= 4;
397
398 (*routes_size)++;
399 }
400
401 return 0;
402 }
403
404 int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
405 void *user_data) {
406 sd_dhcp_lease *lease = user_data;
407 int r;
408
409 assert(lease);
410
411 switch(code) {
412
413 case DHCP_OPTION_TIME_OFFSET:
414 lease_parse_s32(option, len, &lease->time_offset);
415
416 break;
417
418 case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT:
419 lease_parse_u32(option, len, &lease->mtu_aging_timeout, 0);
420
421 break;
422
423 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
424 lease_parse_u32(option, len, &lease->lifetime, 1);
425
426 break;
427
428 case DHCP_OPTION_SERVER_IDENTIFIER:
429 lease_parse_be32(option, len, &lease->server_address);
430
431 break;
432
433 case DHCP_OPTION_SUBNET_MASK:
434 lease_parse_be32(option, len, &lease->subnet_mask);
435
436 break;
437
438 case DHCP_OPTION_BROADCAST:
439 lease_parse_be32(option, len, &lease->broadcast);
440
441 break;
442
443 case DHCP_OPTION_ROUTER:
444 lease_parse_be32(option, len, &lease->router);
445
446 break;
447
448 case DHCP_OPTION_DOMAIN_NAME_SERVER:
449 r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
450 if (r < 0)
451 return r;
452
453 break;
454
455 case DHCP_OPTION_NTP_SERVER:
456 r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
457 if (r < 0)
458 return r;
459
460 break;
461
462 case DHCP_OPTION_POLICY_FILTER:
463 r = lease_parse_in_addrs_pairs(option, len, &lease->policy_filter, &lease->policy_filter_size);
464 if (r < 0)
465 return r;
466
467 break;
468
469 case DHCP_OPTION_STATIC_ROUTE:
470 r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size,
471 &lease->static_route_allocated);
472 if (r < 0)
473 return r;
474
475 break;
476
477 case DHCP_OPTION_INTERFACE_MTU:
478 lease_parse_u16(option, len, &lease->mtu, 68);
479
480 break;
481
482 case DHCP_OPTION_INTERFACE_MDR:
483 lease_parse_u16(option, len, &lease->mdr, 576);
484
485 break;
486
487 case DHCP_OPTION_INTERFACE_TTL:
488 lease_parse_u8(option, len, &lease->ttl, 1);
489
490 break;
491
492 case DHCP_OPTION_BOOT_FILE_SIZE:
493 lease_parse_u16(option, len, &lease->boot_file_size, 0);
494
495 break;
496
497 case DHCP_OPTION_DOMAIN_NAME:
498 {
499 _cleanup_free_ char *domainname = NULL;
500
501 r = lease_parse_string(option, len, &domainname);
502 if (r < 0)
503 return r;
504
505 if (!hostname_is_valid(domainname) || is_localhost(domainname))
506 break;
507
508 free(lease->domainname);
509 lease->domainname = domainname;
510 domainname = NULL;
511
512 break;
513 }
514 case DHCP_OPTION_HOST_NAME:
515 {
516 _cleanup_free_ char *hostname = NULL;
517
518 r = lease_parse_string(option, len, &hostname);
519 if (r < 0)
520 return r;
521
522 if (!hostname_is_valid(hostname) || is_localhost(hostname))
523 break;
524
525 free(lease->hostname);
526 lease->hostname = hostname;
527 hostname = NULL;
528
529 break;
530 }
531 case DHCP_OPTION_ROOT_PATH:
532 r = lease_parse_string(option, len, &lease->root_path);
533 if (r < 0)
534 return r;
535
536 break;
537
538 case DHCP_OPTION_RENEWAL_T1_TIME:
539 lease_parse_u32(option, len, &lease->t1, 1);
540
541 break;
542
543 case DHCP_OPTION_REBINDING_T2_TIME:
544 lease_parse_u32(option, len, &lease->t2, 1);
545
546 break;
547
548 case DHCP_OPTION_ENABLE_IP_FORWARDING:
549 lease_parse_bool(option, len, &lease->ip_forward);
550
551 break;
552
553 case DHCP_OPTION_ENABLE_IP_FORWARDING_NL:
554 lease_parse_bool(option, len, &lease->ip_forward_non_local);
555
556 break;
557
558 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
559 r = lease_parse_classless_routes(option, len, &lease->static_route, &lease->static_route_size,
560 &lease->static_route_allocated);
561 if (r < 0)
562 return r;
563
564 break;
565 }
566
567 return 0;
568 }
569
570 int dhcp_lease_new(sd_dhcp_lease **ret) {
571 sd_dhcp_lease *lease;
572
573 lease = new0(sd_dhcp_lease, 1);
574 if (!lease)
575 return -ENOMEM;
576
577 lease->router = INADDR_ANY;
578 lease->n_ref = REFCNT_INIT;
579
580 *ret = lease;
581 return 0;
582 }
583
584 int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
585 _cleanup_free_ char *temp_path = NULL;
586 _cleanup_fclose_ FILE *f = NULL;
587 struct in_addr address;
588 const struct in_addr *addresses;
589 const uint8_t *client_id;
590 size_t client_id_len;
591 const char *string;
592 uint16_t mtu;
593 struct sd_dhcp_route *routes;
594 int r;
595
596 assert(lease);
597 assert(lease_file);
598
599 r = fopen_temporary(lease_file, &f, &temp_path);
600 if (r < 0)
601 goto finish;
602
603 fchmod(fileno(f), 0644);
604
605 r = sd_dhcp_lease_get_address(lease, &address);
606 if (r < 0)
607 goto finish;
608
609 fprintf(f,
610 "# This is private data. Do not parse.\n"
611 "ADDRESS=%s\n", inet_ntoa(address));
612
613 r = sd_dhcp_lease_get_netmask(lease, &address);
614 if (r < 0)
615 goto finish;
616
617 fprintf(f, "NETMASK=%s\n", inet_ntoa(address));
618
619 r = sd_dhcp_lease_get_router(lease, &address);
620 if (r >= 0)
621 fprintf(f, "ROUTER=%s\n", inet_ntoa(address));
622
623 r = sd_dhcp_lease_get_server_identifier(lease, &address);
624 if (r >= 0)
625 fprintf(f, "SERVER_ADDRESS=%s\n",
626 inet_ntoa(address));
627
628 r = sd_dhcp_lease_get_next_server(lease, &address);
629 if (r >= 0)
630 fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address));
631
632 r = sd_dhcp_lease_get_mtu(lease, &mtu);
633 if (r >= 0)
634 fprintf(f, "MTU=%" PRIu16 "\n", mtu);
635
636 fputs("DNS=", f);
637 r = sd_dhcp_lease_get_dns(lease, &addresses);
638 if (r >= 0)
639 serialize_in_addrs(f, addresses, r);
640 fputs("\n", f);
641
642 fputs("NTP=", f);
643 r = sd_dhcp_lease_get_ntp(lease, &addresses);
644 if (r >= 0)
645 serialize_in_addrs(f, addresses, r);
646 fputs("\n", f);
647
648 r = sd_dhcp_lease_get_domainname(lease, &string);
649 if (r >= 0)
650 fprintf(f, "DOMAINNAME=%s\n", string);
651
652 r = sd_dhcp_lease_get_hostname(lease, &string);
653 if (r >= 0)
654 fprintf(f, "HOSTNAME=%s\n", string);
655
656 r = sd_dhcp_lease_get_root_path(lease, &string);
657 if (r >= 0)
658 fprintf(f, "ROOT_PATH=%s\n", string);
659
660 r = sd_dhcp_lease_get_routes(lease, &routes);
661 if (r >= 0)
662 serialize_dhcp_routes(f, "ROUTES", routes, r);
663
664 r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
665 if (r >= 0) {
666 _cleanup_free_ char *client_id_hex;
667
668 client_id_hex = hexmem (client_id, client_id_len);
669 if (!client_id_hex) {
670 r = -ENOMEM;
671 goto finish;
672 }
673 fprintf(f, "CLIENTID=%s\n", client_id_hex);
674 }
675
676 r = 0;
677
678 fflush(f);
679
680 if (ferror(f) || rename(temp_path, lease_file) < 0) {
681 r = -errno;
682 unlink(lease_file);
683 unlink(temp_path);
684 }
685
686 finish:
687 if (r < 0)
688 log_error_errno(r, "Failed to save lease data %s: %m", lease_file);
689
690 return r;
691 }
692
693 int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
694 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
695 _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL,
696 *server_address = NULL, *next_server = NULL,
697 *dns = NULL, *ntp = NULL, *mtu = NULL,
698 *routes = NULL, *client_id_hex = NULL;
699 struct in_addr addr;
700 int r;
701
702 assert(lease_file);
703 assert(ret);
704
705 r = dhcp_lease_new(&lease);
706 if (r < 0)
707 return r;
708
709 r = parse_env_file(lease_file, NEWLINE,
710 "ADDRESS", &address,
711 "ROUTER", &router,
712 "NETMASK", &netmask,
713 "SERVER_IDENTIFIER", &server_address,
714 "NEXT_SERVER", &next_server,
715 "DNS", &dns,
716 "NTP", &ntp,
717 "MTU", &mtu,
718 "DOMAINNAME", &lease->domainname,
719 "HOSTNAME", &lease->hostname,
720 "ROOT_PATH", &lease->root_path,
721 "ROUTES", &routes,
722 "CLIENTID", &client_id_hex,
723 NULL);
724 if (r < 0) {
725 if (r == -ENOENT)
726 return 0;
727
728 return log_error_errno(r, "Failed to read %s: %m", lease_file);
729 }
730
731 r = inet_pton(AF_INET, address, &addr);
732 if (r < 0)
733 return r;
734
735 lease->address = addr.s_addr;
736
737 if (router) {
738 r = inet_pton(AF_INET, router, &addr);
739 if (r < 0)
740 return r;
741
742 lease->router = addr.s_addr;
743 }
744
745 r = inet_pton(AF_INET, netmask, &addr);
746 if (r < 0)
747 return r;
748
749 lease->subnet_mask = addr.s_addr;
750
751 if (server_address) {
752 r = inet_pton(AF_INET, server_address, &addr);
753 if (r < 0)
754 return r;
755
756 lease->server_address = addr.s_addr;
757 }
758
759 if (next_server) {
760 r = inet_pton(AF_INET, next_server, &addr);
761 if (r < 0)
762 return r;
763
764 lease->next_server = addr.s_addr;
765 }
766
767 if (dns) {
768 r = deserialize_in_addrs(&lease->dns, dns);
769 if (r < 0)
770 return r;
771
772 lease->dns_size = r;
773 }
774
775 if (ntp) {
776 r = deserialize_in_addrs(&lease->ntp, ntp);
777 if (r < 0)
778 return r;
779
780 lease->ntp_size = r;
781 }
782
783 if (mtu) {
784 uint16_t u;
785 if (sscanf(mtu, "%" SCNu16, &u) > 0)
786 lease->mtu = u;
787 }
788
789 if (routes) {
790 r = deserialize_dhcp_routes(&lease->static_route, &lease->static_route_size,
791 &lease->static_route_allocated, routes);
792 if (r < 0)
793 return r;
794 }
795
796 if (client_id_hex) {
797 if (strlen (client_id_hex) % 2)
798 return -EINVAL;
799
800 lease->client_id = unhexmem (client_id_hex, strlen (client_id_hex));
801 if (!lease->client_id)
802 return -ENOMEM;
803 lease->client_id_len = strlen (client_id_hex) / 2;
804 }
805
806 *ret = lease;
807 lease = NULL;
808
809 return 0;
810 }
811
812 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
813 struct in_addr address;
814 struct in_addr mask;
815 int r;
816
817 assert(lease);
818
819 address.s_addr = lease->address;
820
821 /* fall back to the default subnet masks based on address class */
822 r = in_addr_default_subnet_mask(&address, &mask);
823 if (r < 0)
824 return r;
825
826 lease->subnet_mask = mask.s_addr;
827
828 return 0;
829 }
830
831 int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
832 size_t *client_id_len) {
833 assert_return(lease, -EINVAL);
834 assert_return(client_id, -EINVAL);
835 assert_return(client_id_len, -EINVAL);
836
837 *client_id = lease->client_id;
838 *client_id_len = lease->client_id_len;
839 return 0;
840 }
841
842 int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id,
843 size_t client_id_len) {
844 assert_return(lease, -EINVAL);
845 assert_return((!client_id && !client_id_len) ||
846 (client_id && client_id_len), -EINVAL);
847
848 free (lease->client_id);
849 lease->client_id = NULL;
850 lease->client_id_len = 0;
851
852 if (client_id) {
853 lease->client_id = memdup (client_id, client_id_len);
854 lease->client_id_len = client_id_len;
855 }
856
857 return 0;
858 }