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 "string-util.h"
41 #include "unaligned.h"
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
);
47 if (lease
->address
== 0)
50 addr
->s_addr
= lease
->address
;
54 int sd_dhcp_lease_get_broadcast(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
55 assert_return(lease
, -EINVAL
);
56 assert_return(addr
, -EINVAL
);
58 if (!lease
->have_broadcast
)
61 addr
->s_addr
= lease
->broadcast
;
65 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease
*lease
, uint32_t *lifetime
) {
66 assert_return(lease
, -EINVAL
);
67 assert_return(lifetime
, -EINVAL
);
69 if (lease
->lifetime
<= 0)
72 *lifetime
= lease
->lifetime
;
76 int sd_dhcp_lease_get_t1(sd_dhcp_lease
*lease
, uint32_t *t1
) {
77 assert_return(lease
, -EINVAL
);
78 assert_return(t1
, -EINVAL
);
87 int sd_dhcp_lease_get_t2(sd_dhcp_lease
*lease
, uint32_t *t2
) {
88 assert_return(lease
, -EINVAL
);
89 assert_return(t2
, -EINVAL
);
98 int sd_dhcp_lease_get_mtu(sd_dhcp_lease
*lease
, uint16_t *mtu
) {
99 assert_return(lease
, -EINVAL
);
100 assert_return(mtu
, -EINVAL
);
109 int sd_dhcp_lease_get_dns(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
110 assert_return(lease
, -EINVAL
);
111 assert_return(addr
, -EINVAL
);
113 if (lease
->dns_size
<= 0)
117 return (int) lease
->dns_size
;
120 int sd_dhcp_lease_get_ntp(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
121 assert_return(lease
, -EINVAL
);
122 assert_return(addr
, -EINVAL
);
124 if (lease
->ntp_size
<= 0)
128 return (int) lease
->ntp_size
;
131 int sd_dhcp_lease_get_domainname(sd_dhcp_lease
*lease
, const char **domainname
) {
132 assert_return(lease
, -EINVAL
);
133 assert_return(domainname
, -EINVAL
);
135 if (!lease
->domainname
)
138 *domainname
= lease
->domainname
;
142 int sd_dhcp_lease_get_hostname(sd_dhcp_lease
*lease
, const char **hostname
) {
143 assert_return(lease
, -EINVAL
);
144 assert_return(hostname
, -EINVAL
);
146 if (!lease
->hostname
)
149 *hostname
= lease
->hostname
;
153 int sd_dhcp_lease_get_root_path(sd_dhcp_lease
*lease
, const char **root_path
) {
154 assert_return(lease
, -EINVAL
);
155 assert_return(root_path
, -EINVAL
);
157 if (!lease
->root_path
)
160 *root_path
= lease
->root_path
;
164 int sd_dhcp_lease_get_router(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
165 assert_return(lease
, -EINVAL
);
166 assert_return(addr
, -EINVAL
);
168 if (lease
->router
== 0)
171 addr
->s_addr
= lease
->router
;
175 int sd_dhcp_lease_get_netmask(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
176 assert_return(lease
, -EINVAL
);
177 assert_return(addr
, -EINVAL
);
179 if (!lease
->have_subnet_mask
)
182 addr
->s_addr
= lease
->subnet_mask
;
186 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
187 assert_return(lease
, -EINVAL
);
188 assert_return(addr
, -EINVAL
);
190 if (lease
->server_address
== 0)
193 addr
->s_addr
= lease
->server_address
;
197 int sd_dhcp_lease_get_next_server(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
198 assert_return(lease
, -EINVAL
);
199 assert_return(addr
, -EINVAL
);
201 if (lease
->next_server
== 0)
204 addr
->s_addr
= lease
->next_server
;
208 int sd_dhcp_lease_get_routes(sd_dhcp_lease
*lease
, struct sd_dhcp_route
**routes
) {
209 assert_return(lease
, -EINVAL
);
210 assert_return(routes
, -EINVAL
);
212 if (lease
->static_route_size
<= 0)
215 *routes
= lease
->static_route
;
216 return (int) lease
->static_route_size
;
219 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease
*lease
, const void **data
, size_t *data_len
) {
220 assert_return(lease
, -EINVAL
);
221 assert_return(data
, -EINVAL
);
222 assert_return(data_len
, -EINVAL
);
224 if (lease
->vendor_specific_len
<= 0)
227 *data
= lease
->vendor_specific
;
228 *data_len
= lease
->vendor_specific_len
;
232 sd_dhcp_lease
*sd_dhcp_lease_ref(sd_dhcp_lease
*lease
) {
237 assert(lease
->n_ref
>= 1);
243 sd_dhcp_lease
*sd_dhcp_lease_unref(sd_dhcp_lease
*lease
) {
248 assert(lease
->n_ref
>= 1);
251 if (lease
->n_ref
> 0)
254 while (lease
->private_options
) {
255 struct sd_dhcp_raw_option
*option
= lease
->private_options
;
257 LIST_REMOVE(options
, lease
->private_options
, option
);
263 free(lease
->hostname
);
264 free(lease
->domainname
);
267 free(lease
->static_route
);
268 free(lease
->client_id
);
269 free(lease
->vendor_specific
);
275 static int lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
282 *ret
= unaligned_read_be32((be32_t
*) option
);
289 static int lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
296 *ret
= unaligned_read_be16((be16_t
*) option
);
303 static int lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
310 memcpy(ret
, option
, 4);
314 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
324 * One trailing NUL byte is OK, we don't mind. See:
325 * https://github.com/systemd/systemd/issues/1337
327 if (memchr(option
, 0, len
- 1))
330 string
= strndup((const char *) option
, len
);
341 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
351 struct in_addr
*addresses
;
356 n_addresses
= len
/ 4;
358 addresses
= newdup(struct in_addr
, option
, n_addresses
);
364 *n_ret
= n_addresses
;
370 static int lease_parse_routes(
371 const uint8_t *option
, size_t len
,
372 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
376 assert(option
|| len
<= 0);
379 assert(routes_allocated
);
387 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
391 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
394 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
396 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
400 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
401 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
404 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
414 /* parses RFC3442 Classless Static Route Option */
415 static int lease_parse_classless_routes(
416 const uint8_t *option
, size_t len
,
417 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
419 assert(option
|| len
<= 0);
422 assert(routes_allocated
);
427 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
431 struct sd_dhcp_route
*route
;
433 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
436 route
= *routes
+ *routes_size
;
438 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
439 route
->dst_prefixlen
= *option
;
443 /* can't have more than 4 octets in IPv4 */
444 if (dst_octets
> 4 || len
< dst_octets
)
447 route
->dst_addr
.s_addr
= 0;
448 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
449 option
+= dst_octets
;
455 lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
);
465 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
466 sd_dhcp_lease
*lease
= userdata
;
473 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
474 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
476 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
480 case DHCP_OPTION_SERVER_IDENTIFIER
:
481 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
483 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
487 case DHCP_OPTION_SUBNET_MASK
:
488 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
490 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
492 lease
->have_subnet_mask
= true;
495 case DHCP_OPTION_BROADCAST
:
496 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
498 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
500 lease
->have_broadcast
= true;
503 case DHCP_OPTION_ROUTER
:
505 r
= lease_parse_be32(option
, 4, &lease
->router
);
507 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
511 case DHCP_OPTION_DOMAIN_NAME_SERVER
:
512 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
514 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
517 case DHCP_OPTION_NTP_SERVER
:
518 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
520 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
523 case DHCP_OPTION_STATIC_ROUTE
:
524 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
526 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
529 case DHCP_OPTION_INTERFACE_MTU
:
530 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
532 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
535 case DHCP_OPTION_DOMAIN_NAME
: {
536 _cleanup_free_
char *domainname
= NULL
, *normalized
= NULL
;
538 r
= lease_parse_string(option
, len
, &domainname
);
540 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
544 r
= dns_name_normalize(domainname
, &normalized
);
546 log_debug_errno(r
, "Failed to normalize domain name '%s': %m", domainname
);
550 if (is_localhost(normalized
)) {
551 log_debug_errno(r
, "Detected 'localhost' as suggested domain name, ignoring.");
555 free(lease
->domainname
);
556 lease
->domainname
= normalized
;
562 case DHCP_OPTION_HOST_NAME
: {
563 _cleanup_free_
char *hostname
= NULL
, *normalized
= NULL
;
565 r
= lease_parse_string(option
, len
, &hostname
);
567 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
571 r
= dns_name_normalize(hostname
, &normalized
);
573 log_debug_errno(r
, "Failed to normalize host name '%s', ignoring: %m", hostname
);
577 if (is_localhost(normalized
)) {
578 log_debug_errno(r
, "Detected 'localhost' as suggested host name, ignoring.");
582 free(lease
->hostname
);
583 lease
->hostname
= normalized
;
589 case DHCP_OPTION_ROOT_PATH
:
590 r
= lease_parse_string(option
, len
, &lease
->root_path
);
592 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
595 case DHCP_OPTION_RENEWAL_T1_TIME
:
596 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
598 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
601 case DHCP_OPTION_REBINDING_T2_TIME
:
602 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
604 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
607 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
608 r
= lease_parse_classless_routes(
610 &lease
->static_route
,
611 &lease
->static_route_size
,
612 &lease
->static_route_allocated
);
614 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
617 case DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
618 _cleanup_free_
char *tz
= NULL
;
620 r
= lease_parse_string(option
, len
, &tz
);
622 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
626 if (!timezone_is_valid(tz
)) {
627 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
631 free(lease
->timezone
);
632 lease
->timezone
= tz
;
638 case DHCP_OPTION_VENDOR_SPECIFIC
:
641 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
645 p
= memdup(option
, len
);
649 free(lease
->vendor_specific
);
650 lease
->vendor_specific
= p
;
653 lease
->vendor_specific_len
= len
;
656 case DHCP_OPTION_PRIVATE_BASE
... DHCP_OPTION_PRIVATE_LAST
:
657 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
664 log_debug("Ignoring option DHCP option %i while parsing.", code
);
671 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
672 struct sd_dhcp_raw_option
*cur
, *option
;
676 LIST_FOREACH(options
, cur
, lease
->private_options
) {
679 if (tag
== cur
->tag
) {
680 log_debug("Ignoring duplicate option, tagged %i.", tag
);
685 option
= new(struct sd_dhcp_raw_option
, 1);
690 option
->length
= len
;
691 option
->data
= memdup(data
, len
);
697 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
701 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
702 sd_dhcp_lease
*lease
;
704 lease
= new0(sd_dhcp_lease
, 1);
708 lease
->router
= INADDR_ANY
;
715 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
716 _cleanup_free_
char *temp_path
= NULL
;
717 _cleanup_fclose_
FILE *f
= NULL
;
718 struct sd_dhcp_raw_option
*option
;
719 struct in_addr address
;
720 const struct in_addr
*addresses
;
721 const void *client_id
, *data
;
722 size_t client_id_len
, data_len
;
725 struct sd_dhcp_route
*routes
;
726 uint32_t t1
, t2
, lifetime
;
732 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
736 fchmod(fileno(f
), 0644);
739 "# This is private data. Do not parse.\n");
741 r
= sd_dhcp_lease_get_address(lease
, &address
);
743 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
745 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
747 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
749 r
= sd_dhcp_lease_get_router(lease
, &address
);
751 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
753 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
755 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
757 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
759 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
761 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
763 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
765 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
767 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
769 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
771 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
773 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
775 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
777 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
779 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
781 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
784 serialize_in_addrs(f
, addresses
, r
);
788 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
791 serialize_in_addrs(f
, addresses
, r
);
795 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
797 fprintf(f
, "DOMAINNAME=%s\n", string
);
799 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
801 fprintf(f
, "HOSTNAME=%s\n", string
);
803 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
805 fprintf(f
, "ROOT_PATH=%s\n", string
);
807 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
809 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
811 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
813 fprintf(f
, "TIMEZONE=%s\n", string
);
815 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
817 _cleanup_free_
char *client_id_hex
;
819 client_id_hex
= hexmem(client_id
, client_id_len
);
820 if (!client_id_hex
) {
824 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
827 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
829 _cleanup_free_
char *option_hex
= NULL
;
831 option_hex
= hexmem(data
, data_len
);
836 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
839 LIST_FOREACH(options
, option
, lease
->private_options
) {
840 char key
[strlen("OPTION_000")+1];
842 snprintf(key
, sizeof(key
), "OPTION_%"PRIu8
, option
->tag
);
843 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
848 r
= fflush_and_check(f
);
852 if (rename(temp_path
, lease_file
) < 0) {
861 (void) unlink(temp_path
);
863 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
866 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
868 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
873 *server_address
= NULL
,
880 *client_id_hex
= NULL
,
881 *vendor_specific_hex
= NULL
,
885 *options
[DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
892 r
= dhcp_lease_new(&lease
);
896 r
= parse_env_file(lease_file
, NEWLINE
,
900 "SERVER_IDENTIFIER", &server_address
,
901 "NEXT_SERVER", &next_server
,
902 "BROADCAST", &broadcast
,
906 "DOMAINNAME", &lease
->domainname
,
907 "HOSTNAME", &lease
->hostname
,
908 "ROOT_PATH", &lease
->root_path
,
910 "CLIENTID", &client_id_hex
,
911 "TIMEZONE", &lease
->timezone
,
912 "VENDOR_SPECIFIC", &vendor_specific_hex
,
913 "LIFETIME", &lifetime
,
916 "OPTION_224", &options
[0],
917 "OPTION_225", &options
[1],
918 "OPTION_226", &options
[2],
919 "OPTION_227", &options
[3],
920 "OPTION_228", &options
[4],
921 "OPTION_229", &options
[5],
922 "OPTION_230", &options
[6],
923 "OPTION_231", &options
[7],
924 "OPTION_232", &options
[8],
925 "OPTION_233", &options
[9],
926 "OPTION_234", &options
[10],
927 "OPTION_235", &options
[11],
928 "OPTION_236", &options
[12],
929 "OPTION_237", &options
[13],
930 "OPTION_238", &options
[14],
931 "OPTION_239", &options
[15],
932 "OPTION_240", &options
[16],
933 "OPTION_241", &options
[17],
934 "OPTION_242", &options
[18],
935 "OPTION_243", &options
[19],
936 "OPTION_244", &options
[20],
937 "OPTION_245", &options
[21],
938 "OPTION_246", &options
[22],
939 "OPTION_247", &options
[23],
940 "OPTION_248", &options
[24],
941 "OPTION_249", &options
[25],
942 "OPTION_250", &options
[26],
943 "OPTION_251", &options
[27],
944 "OPTION_252", &options
[28],
945 "OPTION_253", &options
[29],
946 "OPTION_254", &options
[30],
952 r
= inet_pton(AF_INET
, address
, &lease
->address
);
954 log_debug("Failed to parse address %s, ignoring.", address
);
958 r
= inet_pton(AF_INET
, router
, &lease
->router
);
960 log_debug("Failed to parse router %s, ignoring.", router
);
964 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
966 log_debug("Failed to parse netmask %s, ignoring.", netmask
);
968 lease
->have_subnet_mask
= true;
971 if (server_address
) {
972 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
974 log_debug("Failed to parse server address %s, ignoring.", server_address
);
978 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
980 log_debug("Failed to parse next server %s, ignoring.", next_server
);
984 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
986 log_debug("Failed to parse broadcast address %s, ignoring.", broadcast
);
988 lease
->have_broadcast
= true;
992 r
= deserialize_in_addrs(&lease
->dns
, dns
);
994 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
1000 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
1002 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1004 lease
->ntp_size
= r
;
1008 r
= safe_atou16(mtu
, &lease
->mtu
);
1010 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1014 r
= deserialize_dhcp_routes(
1015 &lease
->static_route
,
1016 &lease
->static_route_size
,
1017 &lease
->static_route_allocated
,
1020 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1024 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1026 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1030 r
= safe_atou32(t1
, &lease
->t1
);
1032 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1036 r
= safe_atou32(t2
, &lease
->t2
);
1038 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1041 if (client_id_hex
) {
1042 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1044 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1047 if (vendor_specific_hex
) {
1048 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1050 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1053 for (i
= 0; i
<= DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
; i
++) {
1054 _cleanup_free_
void *data
= NULL
;
1060 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1062 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1066 r
= dhcp_lease_insert_private_option(lease
, DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1077 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1078 struct in_addr address
, mask
;
1083 if (lease
->address
== 0)
1086 address
.s_addr
= lease
->address
;
1088 /* fall back to the default subnet masks based on address class */
1089 r
= in_addr_default_subnet_mask(&address
, &mask
);
1093 lease
->subnet_mask
= mask
.s_addr
;
1094 lease
->have_subnet_mask
= true;
1099 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1100 assert_return(lease
, -EINVAL
);
1101 assert_return(client_id
, -EINVAL
);
1102 assert_return(client_id_len
, -EINVAL
);
1104 if (!lease
->client_id
)
1107 *client_id
= lease
->client_id
;
1108 *client_id_len
= lease
->client_id_len
;
1113 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1114 assert_return(lease
, -EINVAL
);
1115 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1117 if (client_id_len
<= 0)
1118 lease
->client_id
= mfree(lease
->client_id
);
1122 p
= memdup(client_id
, client_id_len
);
1126 free(lease
->client_id
);
1127 lease
->client_id
= p
;
1128 lease
->client_id_len
= client_id_len
;
1134 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1135 assert_return(lease
, -EINVAL
);
1136 assert_return(tz
, -EINVAL
);
1138 if (!lease
->timezone
)
1141 *tz
= lease
->timezone
;