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