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
);
288 static int lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
295 *ret
= unaligned_read_be32((be32_t
*) option
);
302 static int lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
309 *ret
= unaligned_read_be16((be16_t
*) option
);
316 static int lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
323 memcpy(ret
, option
, 4);
327 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
337 * One trailing NUL byte is OK, we don't mind. See:
338 * https://github.com/systemd/systemd/issues/1337
340 if (memchr(option
, 0, len
- 1))
343 string
= strndup((const char *) option
, len
);
354 static int lease_parse_domain(const uint8_t *option
, size_t len
, char **ret
) {
355 _cleanup_free_
char *name
= NULL
, *normalized
= NULL
;
361 r
= lease_parse_string(option
, len
, &name
);
369 r
= dns_name_normalize(name
, &normalized
);
373 if (is_localhost(normalized
))
376 if (dns_name_is_root(normalized
))
386 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
396 struct in_addr
*addresses
;
401 n_addresses
= len
/ 4;
403 addresses
= newdup(struct in_addr
, option
, n_addresses
);
409 *n_ret
= n_addresses
;
415 static int lease_parse_routes(
416 const uint8_t *option
, size_t len
,
417 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
421 assert(option
|| len
<= 0);
424 assert(routes_allocated
);
432 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
436 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
439 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
441 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
445 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
446 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
449 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
459 /* parses RFC3442 Classless Static Route Option */
460 static int lease_parse_classless_routes(
461 const uint8_t *option
, size_t len
,
462 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
464 assert(option
|| len
<= 0);
467 assert(routes_allocated
);
472 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
476 struct sd_dhcp_route
*route
;
478 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
481 route
= *routes
+ *routes_size
;
483 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
484 route
->dst_prefixlen
= *option
;
488 /* can't have more than 4 octets in IPv4 */
489 if (dst_octets
> 4 || len
< dst_octets
)
492 route
->dst_addr
.s_addr
= 0;
493 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
494 option
+= dst_octets
;
500 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
510 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
511 sd_dhcp_lease
*lease
= userdata
;
518 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
519 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
521 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
525 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
526 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
528 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
532 case SD_DHCP_OPTION_SUBNET_MASK
:
533 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
535 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
537 lease
->have_subnet_mask
= true;
540 case SD_DHCP_OPTION_BROADCAST
:
541 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
543 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
545 lease
->have_broadcast
= true;
548 case SD_DHCP_OPTION_ROUTER
:
550 r
= lease_parse_be32(option
, 4, &lease
->router
);
552 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
556 case SD_DHCP_OPTION_DOMAIN_NAME_SERVER
:
557 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
559 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
562 case SD_DHCP_OPTION_NTP_SERVER
:
563 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
565 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
568 case SD_DHCP_OPTION_STATIC_ROUTE
:
569 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
571 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
574 case SD_DHCP_OPTION_INTERFACE_MTU
:
575 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
577 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
580 case SD_DHCP_OPTION_DOMAIN_NAME
:
581 r
= lease_parse_domain(option
, len
, &lease
->domainname
);
583 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
589 case SD_DHCP_OPTION_HOST_NAME
:
590 r
= lease_parse_domain(option
, len
, &lease
->hostname
);
592 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
598 case SD_DHCP_OPTION_ROOT_PATH
:
599 r
= lease_parse_string(option
, len
, &lease
->root_path
);
601 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
604 case SD_DHCP_OPTION_RENEWAL_T1_TIME
:
605 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
607 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
610 case SD_DHCP_OPTION_REBINDING_T2_TIME
:
611 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
613 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
616 case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
617 r
= lease_parse_classless_routes(
619 &lease
->static_route
,
620 &lease
->static_route_size
,
621 &lease
->static_route_allocated
);
623 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
626 case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
627 _cleanup_free_
char *tz
= NULL
;
629 r
= lease_parse_string(option
, len
, &tz
);
631 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
635 if (!timezone_is_valid(tz
)) {
636 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
640 free(lease
->timezone
);
641 lease
->timezone
= tz
;
647 case SD_DHCP_OPTION_VENDOR_SPECIFIC
:
650 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
654 p
= memdup(option
, len
);
658 free(lease
->vendor_specific
);
659 lease
->vendor_specific
= p
;
662 lease
->vendor_specific_len
= len
;
665 case SD_DHCP_OPTION_PRIVATE_BASE
... SD_DHCP_OPTION_PRIVATE_LAST
:
666 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
673 log_debug("Ignoring option DHCP option %"PRIu8
" while parsing.", code
);
680 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
681 struct sd_dhcp_raw_option
*cur
, *option
;
685 LIST_FOREACH(options
, cur
, lease
->private_options
) {
688 if (tag
== cur
->tag
) {
689 log_debug("Ignoring duplicate option, tagged %i.", tag
);
694 option
= new(struct sd_dhcp_raw_option
, 1);
699 option
->length
= len
;
700 option
->data
= memdup(data
, len
);
706 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
710 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
711 sd_dhcp_lease
*lease
;
713 lease
= new0(sd_dhcp_lease
, 1);
717 lease
->router
= INADDR_ANY
;
724 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
725 _cleanup_free_
char *temp_path
= NULL
;
726 _cleanup_fclose_
FILE *f
= NULL
;
727 struct sd_dhcp_raw_option
*option
;
728 struct in_addr address
;
729 const struct in_addr
*addresses
;
730 const void *client_id
, *data
;
731 size_t client_id_len
, data_len
;
734 _cleanup_free_ sd_dhcp_route
**routes
= NULL
;
735 uint32_t t1
, t2
, lifetime
;
741 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
745 fchmod(fileno(f
), 0644);
748 "# This is private data. Do not parse.\n");
750 r
= sd_dhcp_lease_get_address(lease
, &address
);
752 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
754 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
756 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
758 r
= sd_dhcp_lease_get_router(lease
, &address
);
760 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
762 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
764 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
766 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
768 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
770 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
772 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
774 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
776 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
778 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
780 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
782 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
784 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
786 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
788 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
790 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
793 serialize_in_addrs(f
, addresses
, r
);
797 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
800 serialize_in_addrs(f
, addresses
, r
);
804 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
806 fprintf(f
, "DOMAINNAME=%s\n", string
);
808 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
810 fprintf(f
, "HOSTNAME=%s\n", string
);
812 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
814 fprintf(f
, "ROOT_PATH=%s\n", string
);
816 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
818 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
820 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
822 fprintf(f
, "TIMEZONE=%s\n", string
);
824 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
826 _cleanup_free_
char *client_id_hex
= NULL
;
828 client_id_hex
= hexmem(client_id
, client_id_len
);
829 if (!client_id_hex
) {
833 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
836 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
838 _cleanup_free_
char *option_hex
= NULL
;
840 option_hex
= hexmem(data
, data_len
);
845 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
848 LIST_FOREACH(options
, option
, lease
->private_options
) {
849 char key
[strlen("OPTION_000")+1];
851 xsprintf(key
, "OPTION_%" PRIu8
, option
->tag
);
852 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
857 r
= fflush_and_check(f
);
861 if (rename(temp_path
, lease_file
) < 0) {
870 (void) unlink(temp_path
);
872 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
875 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
877 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
882 *server_address
= NULL
,
889 *client_id_hex
= NULL
,
890 *vendor_specific_hex
= NULL
,
894 *options
[SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
901 r
= dhcp_lease_new(&lease
);
905 r
= parse_env_file(lease_file
, NEWLINE
,
909 "SERVER_IDENTIFIER", &server_address
,
910 "NEXT_SERVER", &next_server
,
911 "BROADCAST", &broadcast
,
915 "DOMAINNAME", &lease
->domainname
,
916 "HOSTNAME", &lease
->hostname
,
917 "ROOT_PATH", &lease
->root_path
,
919 "CLIENTID", &client_id_hex
,
920 "TIMEZONE", &lease
->timezone
,
921 "VENDOR_SPECIFIC", &vendor_specific_hex
,
922 "LIFETIME", &lifetime
,
925 "OPTION_224", &options
[0],
926 "OPTION_225", &options
[1],
927 "OPTION_226", &options
[2],
928 "OPTION_227", &options
[3],
929 "OPTION_228", &options
[4],
930 "OPTION_229", &options
[5],
931 "OPTION_230", &options
[6],
932 "OPTION_231", &options
[7],
933 "OPTION_232", &options
[8],
934 "OPTION_233", &options
[9],
935 "OPTION_234", &options
[10],
936 "OPTION_235", &options
[11],
937 "OPTION_236", &options
[12],
938 "OPTION_237", &options
[13],
939 "OPTION_238", &options
[14],
940 "OPTION_239", &options
[15],
941 "OPTION_240", &options
[16],
942 "OPTION_241", &options
[17],
943 "OPTION_242", &options
[18],
944 "OPTION_243", &options
[19],
945 "OPTION_244", &options
[20],
946 "OPTION_245", &options
[21],
947 "OPTION_246", &options
[22],
948 "OPTION_247", &options
[23],
949 "OPTION_248", &options
[24],
950 "OPTION_249", &options
[25],
951 "OPTION_250", &options
[26],
952 "OPTION_251", &options
[27],
953 "OPTION_252", &options
[28],
954 "OPTION_253", &options
[29],
955 "OPTION_254", &options
[30],
961 r
= inet_pton(AF_INET
, address
, &lease
->address
);
963 log_debug("Failed to parse address %s, ignoring.", address
);
967 r
= inet_pton(AF_INET
, router
, &lease
->router
);
969 log_debug("Failed to parse router %s, ignoring.", router
);
973 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
975 log_debug("Failed to parse netmask %s, ignoring.", netmask
);
977 lease
->have_subnet_mask
= true;
980 if (server_address
) {
981 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
983 log_debug("Failed to parse server address %s, ignoring.", server_address
);
987 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
989 log_debug("Failed to parse next server %s, ignoring.", next_server
);
993 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
995 log_debug("Failed to parse broadcast address %s, ignoring.", broadcast
);
997 lease
->have_broadcast
= true;
1001 r
= deserialize_in_addrs(&lease
->dns
, dns
);
1003 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
1005 lease
->dns_size
= r
;
1009 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
1011 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1013 lease
->ntp_size
= r
;
1017 r
= safe_atou16(mtu
, &lease
->mtu
);
1019 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1023 r
= deserialize_dhcp_routes(
1024 &lease
->static_route
,
1025 &lease
->static_route_size
,
1026 &lease
->static_route_allocated
,
1029 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1033 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1035 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1039 r
= safe_atou32(t1
, &lease
->t1
);
1041 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1045 r
= safe_atou32(t2
, &lease
->t2
);
1047 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1050 if (client_id_hex
) {
1051 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1053 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1056 if (vendor_specific_hex
) {
1057 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1059 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1062 for (i
= 0; i
<= SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
; i
++) {
1063 _cleanup_free_
void *data
= NULL
;
1069 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1071 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1075 r
= dhcp_lease_insert_private_option(lease
, SD_DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1086 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1087 struct in_addr address
, mask
;
1092 if (lease
->address
== 0)
1095 address
.s_addr
= lease
->address
;
1097 /* fall back to the default subnet masks based on address class */
1098 r
= in_addr_default_subnet_mask(&address
, &mask
);
1102 lease
->subnet_mask
= mask
.s_addr
;
1103 lease
->have_subnet_mask
= true;
1108 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1109 assert_return(lease
, -EINVAL
);
1110 assert_return(client_id
, -EINVAL
);
1111 assert_return(client_id_len
, -EINVAL
);
1113 if (!lease
->client_id
)
1116 *client_id
= lease
->client_id
;
1117 *client_id_len
= lease
->client_id_len
;
1122 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1123 assert_return(lease
, -EINVAL
);
1124 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1126 if (client_id_len
<= 0)
1127 lease
->client_id
= mfree(lease
->client_id
);
1131 p
= memdup(client_id
, client_id_len
);
1135 free(lease
->client_id
);
1136 lease
->client_id
= p
;
1137 lease
->client_id_len
= client_id_len
;
1143 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1144 assert_return(lease
, -EINVAL
);
1145 assert_return(tz
, -EINVAL
);
1147 if (!lease
->timezone
)
1150 *tz
= lease
->timezone
;
1154 int sd_dhcp_route_get_destination(sd_dhcp_route
*route
, struct in_addr
*destination
) {
1155 assert_return(route
, -EINVAL
);
1156 assert_return(destination
, -EINVAL
);
1158 *destination
= route
->dst_addr
;
1162 int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route
*route
, uint8_t *length
) {
1163 assert_return(route
, -EINVAL
);
1164 assert_return(length
, -EINVAL
);
1166 *length
= route
->dst_prefixlen
;
1170 int sd_dhcp_route_get_gateway(sd_dhcp_route
*route
, struct in_addr
*gateway
) {
1171 assert_return(route
, -EINVAL
);
1172 assert_return(gateway
, -EINVAL
);
1174 *gateway
= route
->gw_addr
;