2 This file is part of systemd.
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5 Copyright (C) 2014 Tom Gundersen
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.
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.
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/>.
21 #include <arpa/inet.h>
27 #include "sd-dhcp-lease.h"
29 #include "alloc-util.h"
30 #include "dhcp-lease-internal.h"
31 #include "dhcp-protocol.h"
32 #include "dns-domain.h"
35 #include "hexdecoct.h"
36 #include "hostname-util.h"
37 #include "in-addr-util.h"
38 #include "network-internal.h"
39 #include "parse-util.h"
40 #include "stdio-util.h"
41 #include "string-util.h"
42 #include "unaligned.h"
44 int sd_dhcp_lease_get_address(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
45 assert_return(lease
, -EINVAL
);
46 assert_return(addr
, -EINVAL
);
48 if (lease
->address
== 0)
51 addr
->s_addr
= lease
->address
;
55 int sd_dhcp_lease_get_broadcast(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
56 assert_return(lease
, -EINVAL
);
57 assert_return(addr
, -EINVAL
);
59 if (!lease
->have_broadcast
)
62 addr
->s_addr
= lease
->broadcast
;
66 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease
*lease
, uint32_t *lifetime
) {
67 assert_return(lease
, -EINVAL
);
68 assert_return(lifetime
, -EINVAL
);
70 if (lease
->lifetime
<= 0)
73 *lifetime
= lease
->lifetime
;
77 int sd_dhcp_lease_get_t1(sd_dhcp_lease
*lease
, uint32_t *t1
) {
78 assert_return(lease
, -EINVAL
);
79 assert_return(t1
, -EINVAL
);
88 int sd_dhcp_lease_get_t2(sd_dhcp_lease
*lease
, uint32_t *t2
) {
89 assert_return(lease
, -EINVAL
);
90 assert_return(t2
, -EINVAL
);
99 int sd_dhcp_lease_get_mtu(sd_dhcp_lease
*lease
, uint16_t *mtu
) {
100 assert_return(lease
, -EINVAL
);
101 assert_return(mtu
, -EINVAL
);
110 int sd_dhcp_lease_get_dns(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
111 assert_return(lease
, -EINVAL
);
112 assert_return(addr
, -EINVAL
);
114 if (lease
->dns_size
<= 0)
118 return (int) lease
->dns_size
;
121 int sd_dhcp_lease_get_ntp(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
122 assert_return(lease
, -EINVAL
);
123 assert_return(addr
, -EINVAL
);
125 if (lease
->ntp_size
<= 0)
129 return (int) lease
->ntp_size
;
132 int sd_dhcp_lease_get_domainname(sd_dhcp_lease
*lease
, const char **domainname
) {
133 assert_return(lease
, -EINVAL
);
134 assert_return(domainname
, -EINVAL
);
136 if (!lease
->domainname
)
139 *domainname
= lease
->domainname
;
143 int sd_dhcp_lease_get_hostname(sd_dhcp_lease
*lease
, const char **hostname
) {
144 assert_return(lease
, -EINVAL
);
145 assert_return(hostname
, -EINVAL
);
147 if (!lease
->hostname
)
150 *hostname
= lease
->hostname
;
154 int sd_dhcp_lease_get_root_path(sd_dhcp_lease
*lease
, const char **root_path
) {
155 assert_return(lease
, -EINVAL
);
156 assert_return(root_path
, -EINVAL
);
158 if (!lease
->root_path
)
161 *root_path
= lease
->root_path
;
165 int sd_dhcp_lease_get_router(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
166 assert_return(lease
, -EINVAL
);
167 assert_return(addr
, -EINVAL
);
169 if (lease
->router
== 0)
172 addr
->s_addr
= lease
->router
;
176 int sd_dhcp_lease_get_netmask(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
177 assert_return(lease
, -EINVAL
);
178 assert_return(addr
, -EINVAL
);
180 if (!lease
->have_subnet_mask
)
183 addr
->s_addr
= lease
->subnet_mask
;
187 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
188 assert_return(lease
, -EINVAL
);
189 assert_return(addr
, -EINVAL
);
191 if (lease
->server_address
== 0)
194 addr
->s_addr
= lease
->server_address
;
198 int sd_dhcp_lease_get_next_server(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
199 assert_return(lease
, -EINVAL
);
200 assert_return(addr
, -EINVAL
);
202 if (lease
->next_server
== 0)
205 addr
->s_addr
= lease
->next_server
;
210 * The returned routes array must be freed by the caller.
211 * Route objects have the same lifetime of the lease and must not be freed.
213 int sd_dhcp_lease_get_routes(sd_dhcp_lease
*lease
, sd_dhcp_route
***routes
) {
217 assert_return(lease
, -EINVAL
);
218 assert_return(routes
, -EINVAL
);
220 if (lease
->static_route_size
<= 0)
223 ret
= new(sd_dhcp_route
*, lease
->static_route_size
);
227 for (i
= 0; i
< lease
->static_route_size
; i
++)
228 ret
[i
] = &lease
->static_route
[i
];
231 return (int) lease
->static_route_size
;
234 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease
*lease
, const void **data
, size_t *data_len
) {
235 assert_return(lease
, -EINVAL
);
236 assert_return(data
, -EINVAL
);
237 assert_return(data_len
, -EINVAL
);
239 if (lease
->vendor_specific_len
<= 0)
242 *data
= lease
->vendor_specific
;
243 *data_len
= lease
->vendor_specific_len
;
247 sd_dhcp_lease
*sd_dhcp_lease_ref(sd_dhcp_lease
*lease
) {
252 assert(lease
->n_ref
>= 1);
258 sd_dhcp_lease
*sd_dhcp_lease_unref(sd_dhcp_lease
*lease
) {
263 assert(lease
->n_ref
>= 1);
266 if (lease
->n_ref
> 0)
269 while (lease
->private_options
) {
270 struct sd_dhcp_raw_option
*option
= lease
->private_options
;
272 LIST_REMOVE(options
, lease
->private_options
, option
);
278 free(lease
->hostname
);
279 free(lease
->domainname
);
282 free(lease
->static_route
);
283 free(lease
->client_id
);
284 free(lease
->vendor_specific
);
290 static int lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
297 *ret
= unaligned_read_be32((be32_t
*) option
);
304 static int lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
311 *ret
= unaligned_read_be16((be16_t
*) option
);
318 static int lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
325 memcpy(ret
, option
, 4);
329 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
339 * One trailing NUL byte is OK, we don't mind. See:
340 * https://github.com/systemd/systemd/issues/1337
342 if (memchr(option
, 0, len
- 1))
345 string
= strndup((const char *) option
, len
);
356 static int lease_parse_domain(const uint8_t *option
, size_t len
, char **ret
) {
357 _cleanup_free_
char *name
= NULL
, *normalized
= NULL
;
363 r
= lease_parse_string(option
, len
, &name
);
371 r
= dns_name_normalize(name
, &normalized
);
375 if (is_localhost(normalized
))
378 if (dns_name_is_root(normalized
))
388 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
398 struct in_addr
*addresses
;
403 n_addresses
= len
/ 4;
405 addresses
= newdup(struct in_addr
, option
, n_addresses
);
411 *n_ret
= n_addresses
;
417 static int lease_parse_routes(
418 const uint8_t *option
, size_t len
,
419 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
423 assert(option
|| len
<= 0);
426 assert(routes_allocated
);
434 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
438 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
441 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
443 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
447 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
448 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
451 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
461 /* parses RFC3442 Classless Static Route Option */
462 static int lease_parse_classless_routes(
463 const uint8_t *option
, size_t len
,
464 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
466 assert(option
|| len
<= 0);
469 assert(routes_allocated
);
474 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
478 struct sd_dhcp_route
*route
;
480 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
483 route
= *routes
+ *routes_size
;
485 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
486 route
->dst_prefixlen
= *option
;
490 /* can't have more than 4 octets in IPv4 */
491 if (dst_octets
> 4 || len
< dst_octets
)
494 route
->dst_addr
.s_addr
= 0;
495 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
496 option
+= dst_octets
;
502 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
512 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
513 sd_dhcp_lease
*lease
= userdata
;
520 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
521 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
523 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
527 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
528 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
530 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
534 case SD_DHCP_OPTION_SUBNET_MASK
:
535 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
537 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
539 lease
->have_subnet_mask
= true;
542 case SD_DHCP_OPTION_BROADCAST
:
543 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
545 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
547 lease
->have_broadcast
= true;
550 case SD_DHCP_OPTION_ROUTER
:
552 r
= lease_parse_be32(option
, 4, &lease
->router
);
554 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
558 case SD_DHCP_OPTION_DOMAIN_NAME_SERVER
:
559 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
561 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
564 case SD_DHCP_OPTION_NTP_SERVER
:
565 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
567 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
570 case SD_DHCP_OPTION_STATIC_ROUTE
:
571 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
573 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
576 case SD_DHCP_OPTION_INTERFACE_MTU
:
577 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
579 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
582 case SD_DHCP_OPTION_DOMAIN_NAME
:
583 r
= lease_parse_domain(option
, len
, &lease
->domainname
);
585 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
591 case SD_DHCP_OPTION_HOST_NAME
:
592 r
= lease_parse_domain(option
, len
, &lease
->hostname
);
594 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
600 case SD_DHCP_OPTION_ROOT_PATH
:
601 r
= lease_parse_string(option
, len
, &lease
->root_path
);
603 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
606 case SD_DHCP_OPTION_RENEWAL_T1_TIME
:
607 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
609 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
612 case SD_DHCP_OPTION_REBINDING_T2_TIME
:
613 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
615 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
618 case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
619 r
= lease_parse_classless_routes(
621 &lease
->static_route
,
622 &lease
->static_route_size
,
623 &lease
->static_route_allocated
);
625 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
628 case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
629 _cleanup_free_
char *tz
= NULL
;
631 r
= lease_parse_string(option
, len
, &tz
);
633 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
637 if (!timezone_is_valid(tz
)) {
638 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
642 free(lease
->timezone
);
643 lease
->timezone
= tz
;
649 case SD_DHCP_OPTION_VENDOR_SPECIFIC
:
652 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
656 p
= memdup(option
, len
);
660 free(lease
->vendor_specific
);
661 lease
->vendor_specific
= p
;
664 lease
->vendor_specific_len
= len
;
667 case SD_DHCP_OPTION_PRIVATE_BASE
... SD_DHCP_OPTION_PRIVATE_LAST
:
668 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
675 log_debug("Ignoring option DHCP option %"PRIu8
" while parsing.", code
);
682 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
683 struct sd_dhcp_raw_option
*cur
, *option
;
687 LIST_FOREACH(options
, cur
, lease
->private_options
) {
690 if (tag
== cur
->tag
) {
691 log_debug("Ignoring duplicate option, tagged %i.", tag
);
696 option
= new(struct sd_dhcp_raw_option
, 1);
701 option
->length
= len
;
702 option
->data
= memdup(data
, len
);
708 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
712 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
713 sd_dhcp_lease
*lease
;
715 lease
= new0(sd_dhcp_lease
, 1);
719 lease
->router
= INADDR_ANY
;
726 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
727 _cleanup_free_
char *temp_path
= NULL
;
728 _cleanup_fclose_
FILE *f
= NULL
;
729 struct sd_dhcp_raw_option
*option
;
730 struct in_addr address
;
731 const struct in_addr
*addresses
;
732 const void *client_id
, *data
;
733 size_t client_id_len
, data_len
;
736 _cleanup_free_ sd_dhcp_route
**routes
= NULL
;
737 uint32_t t1
, t2
, lifetime
;
743 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
747 fchmod(fileno(f
), 0644);
750 "# This is private data. Do not parse.\n");
752 r
= sd_dhcp_lease_get_address(lease
, &address
);
754 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
756 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
758 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
760 r
= sd_dhcp_lease_get_router(lease
, &address
);
762 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
764 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
766 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
768 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
770 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
772 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
774 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
776 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
778 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
780 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
782 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
784 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
786 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
788 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
790 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
792 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
795 serialize_in_addrs(f
, addresses
, r
);
799 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
802 serialize_in_addrs(f
, addresses
, r
);
806 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
808 fprintf(f
, "DOMAINNAME=%s\n", string
);
810 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
812 fprintf(f
, "HOSTNAME=%s\n", string
);
814 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
816 fprintf(f
, "ROOT_PATH=%s\n", string
);
818 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
820 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
822 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
824 fprintf(f
, "TIMEZONE=%s\n", string
);
826 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
828 _cleanup_free_
char *client_id_hex
= NULL
;
830 client_id_hex
= hexmem(client_id
, client_id_len
);
831 if (!client_id_hex
) {
835 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
838 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
840 _cleanup_free_
char *option_hex
= NULL
;
842 option_hex
= hexmem(data
, data_len
);
847 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
850 LIST_FOREACH(options
, option
, lease
->private_options
) {
851 char key
[strlen("OPTION_000")+1];
853 xsprintf(key
, "OPTION_%" PRIu8
, option
->tag
);
854 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
859 r
= fflush_and_check(f
);
863 if (rename(temp_path
, lease_file
) < 0) {
872 (void) unlink(temp_path
);
874 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
877 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
879 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
884 *server_address
= NULL
,
891 *client_id_hex
= NULL
,
892 *vendor_specific_hex
= NULL
,
896 *options
[SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
903 r
= dhcp_lease_new(&lease
);
907 r
= parse_env_file(lease_file
, NEWLINE
,
911 "SERVER_IDENTIFIER", &server_address
,
912 "NEXT_SERVER", &next_server
,
913 "BROADCAST", &broadcast
,
917 "DOMAINNAME", &lease
->domainname
,
918 "HOSTNAME", &lease
->hostname
,
919 "ROOT_PATH", &lease
->root_path
,
921 "CLIENTID", &client_id_hex
,
922 "TIMEZONE", &lease
->timezone
,
923 "VENDOR_SPECIFIC", &vendor_specific_hex
,
924 "LIFETIME", &lifetime
,
927 "OPTION_224", &options
[0],
928 "OPTION_225", &options
[1],
929 "OPTION_226", &options
[2],
930 "OPTION_227", &options
[3],
931 "OPTION_228", &options
[4],
932 "OPTION_229", &options
[5],
933 "OPTION_230", &options
[6],
934 "OPTION_231", &options
[7],
935 "OPTION_232", &options
[8],
936 "OPTION_233", &options
[9],
937 "OPTION_234", &options
[10],
938 "OPTION_235", &options
[11],
939 "OPTION_236", &options
[12],
940 "OPTION_237", &options
[13],
941 "OPTION_238", &options
[14],
942 "OPTION_239", &options
[15],
943 "OPTION_240", &options
[16],
944 "OPTION_241", &options
[17],
945 "OPTION_242", &options
[18],
946 "OPTION_243", &options
[19],
947 "OPTION_244", &options
[20],
948 "OPTION_245", &options
[21],
949 "OPTION_246", &options
[22],
950 "OPTION_247", &options
[23],
951 "OPTION_248", &options
[24],
952 "OPTION_249", &options
[25],
953 "OPTION_250", &options
[26],
954 "OPTION_251", &options
[27],
955 "OPTION_252", &options
[28],
956 "OPTION_253", &options
[29],
957 "OPTION_254", &options
[30],
963 r
= inet_pton(AF_INET
, address
, &lease
->address
);
965 log_debug("Failed to parse address %s, ignoring.", address
);
969 r
= inet_pton(AF_INET
, router
, &lease
->router
);
971 log_debug("Failed to parse router %s, ignoring.", router
);
975 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
977 log_debug("Failed to parse netmask %s, ignoring.", netmask
);
979 lease
->have_subnet_mask
= true;
982 if (server_address
) {
983 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
985 log_debug("Failed to parse server address %s, ignoring.", server_address
);
989 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
991 log_debug("Failed to parse next server %s, ignoring.", next_server
);
995 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
997 log_debug("Failed to parse broadcast address %s, ignoring.", broadcast
);
999 lease
->have_broadcast
= true;
1003 r
= deserialize_in_addrs(&lease
->dns
, dns
);
1005 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
1007 lease
->dns_size
= r
;
1011 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
1013 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1015 lease
->ntp_size
= r
;
1019 r
= safe_atou16(mtu
, &lease
->mtu
);
1021 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1025 r
= deserialize_dhcp_routes(
1026 &lease
->static_route
,
1027 &lease
->static_route_size
,
1028 &lease
->static_route_allocated
,
1031 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1035 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1037 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1041 r
= safe_atou32(t1
, &lease
->t1
);
1043 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1047 r
= safe_atou32(t2
, &lease
->t2
);
1049 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1052 if (client_id_hex
) {
1053 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1055 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1058 if (vendor_specific_hex
) {
1059 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1061 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1064 for (i
= 0; i
<= SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
; i
++) {
1065 _cleanup_free_
void *data
= NULL
;
1071 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1073 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1077 r
= dhcp_lease_insert_private_option(lease
, SD_DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1088 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1089 struct in_addr address
, mask
;
1094 if (lease
->address
== 0)
1097 address
.s_addr
= lease
->address
;
1099 /* fall back to the default subnet masks based on address class */
1100 r
= in_addr_default_subnet_mask(&address
, &mask
);
1104 lease
->subnet_mask
= mask
.s_addr
;
1105 lease
->have_subnet_mask
= true;
1110 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1111 assert_return(lease
, -EINVAL
);
1112 assert_return(client_id
, -EINVAL
);
1113 assert_return(client_id_len
, -EINVAL
);
1115 if (!lease
->client_id
)
1118 *client_id
= lease
->client_id
;
1119 *client_id_len
= lease
->client_id_len
;
1124 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1125 assert_return(lease
, -EINVAL
);
1126 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1128 if (client_id_len
<= 0)
1129 lease
->client_id
= mfree(lease
->client_id
);
1133 p
= memdup(client_id
, client_id_len
);
1137 free(lease
->client_id
);
1138 lease
->client_id
= p
;
1139 lease
->client_id_len
= client_id_len
;
1145 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1146 assert_return(lease
, -EINVAL
);
1147 assert_return(tz
, -EINVAL
);
1149 if (!lease
->timezone
)
1152 *tz
= lease
->timezone
;
1156 int sd_dhcp_route_get_destination(sd_dhcp_route
*route
, struct in_addr
*destination
) {
1157 assert_return(route
, -EINVAL
);
1158 assert_return(destination
, -EINVAL
);
1160 *destination
= route
->dst_addr
;
1164 int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route
*route
, uint8_t *length
) {
1165 assert_return(route
, -EINVAL
);
1166 assert_return(length
, -EINVAL
);
1168 *length
= route
->dst_prefixlen
;
1172 int sd_dhcp_route_get_gateway(sd_dhcp_route
*route
, struct in_addr
*gateway
) {
1173 assert_return(route
, -EINVAL
);
1174 assert_return(gateway
, -EINVAL
);
1176 *gateway
= route
->gw_addr
;