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_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
366 struct in_addr
*addresses
;
371 n_addresses
= len
/ 4;
373 addresses
= newdup(struct in_addr
, option
, n_addresses
);
379 *n_ret
= n_addresses
;
385 static int lease_parse_routes(
386 const uint8_t *option
, size_t len
,
387 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
391 assert(option
|| len
<= 0);
394 assert(routes_allocated
);
402 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
406 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
409 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
411 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
415 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
416 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
419 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
429 /* parses RFC3442 Classless Static Route Option */
430 static int lease_parse_classless_routes(
431 const uint8_t *option
, size_t len
,
432 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
434 assert(option
|| len
<= 0);
437 assert(routes_allocated
);
442 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
446 struct sd_dhcp_route
*route
;
448 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
451 route
= *routes
+ *routes_size
;
453 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
454 route
->dst_prefixlen
= *option
;
458 /* can't have more than 4 octets in IPv4 */
459 if (dst_octets
> 4 || len
< dst_octets
)
462 route
->dst_addr
.s_addr
= 0;
463 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
464 option
+= dst_octets
;
470 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
480 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
481 sd_dhcp_lease
*lease
= userdata
;
488 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
489 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
491 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
495 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
496 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
498 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
502 case SD_DHCP_OPTION_SUBNET_MASK
:
503 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
505 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
507 lease
->have_subnet_mask
= true;
510 case SD_DHCP_OPTION_BROADCAST
:
511 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
513 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
515 lease
->have_broadcast
= true;
518 case SD_DHCP_OPTION_ROUTER
:
520 r
= lease_parse_be32(option
, 4, &lease
->router
);
522 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
526 case SD_DHCP_OPTION_DOMAIN_NAME_SERVER
:
527 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
529 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
532 case SD_DHCP_OPTION_NTP_SERVER
:
533 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
535 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
538 case SD_DHCP_OPTION_STATIC_ROUTE
:
539 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
541 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
544 case SD_DHCP_OPTION_INTERFACE_MTU
:
545 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
547 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
550 case SD_DHCP_OPTION_DOMAIN_NAME
: {
551 _cleanup_free_
char *domainname
= NULL
, *normalized
= NULL
;
553 r
= lease_parse_string(option
, len
, &domainname
);
555 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
559 r
= dns_name_normalize(domainname
, &normalized
);
561 log_debug_errno(r
, "Failed to normalize domain name '%s': %m", domainname
);
565 if (is_localhost(normalized
)) {
566 log_debug_errno(r
, "Detected 'localhost' as suggested domain name, ignoring.");
570 free(lease
->domainname
);
571 lease
->domainname
= normalized
;
577 case SD_DHCP_OPTION_HOST_NAME
: {
578 _cleanup_free_
char *hostname
= NULL
, *normalized
= NULL
;
580 r
= lease_parse_string(option
, len
, &hostname
);
582 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
586 r
= dns_name_normalize(hostname
, &normalized
);
588 log_debug_errno(r
, "Failed to normalize host name '%s', ignoring: %m", hostname
);
592 if (is_localhost(normalized
)) {
593 log_debug_errno(r
, "Detected 'localhost' as suggested host name, ignoring.");
597 free(lease
->hostname
);
598 lease
->hostname
= normalized
;
604 case SD_DHCP_OPTION_ROOT_PATH
:
605 r
= lease_parse_string(option
, len
, &lease
->root_path
);
607 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
610 case SD_DHCP_OPTION_RENEWAL_T1_TIME
:
611 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
613 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
616 case SD_DHCP_OPTION_REBINDING_T2_TIME
:
617 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
619 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
622 case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
623 r
= lease_parse_classless_routes(
625 &lease
->static_route
,
626 &lease
->static_route_size
,
627 &lease
->static_route_allocated
);
629 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
632 case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
633 _cleanup_free_
char *tz
= NULL
;
635 r
= lease_parse_string(option
, len
, &tz
);
637 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
641 if (!timezone_is_valid(tz
)) {
642 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
646 free(lease
->timezone
);
647 lease
->timezone
= tz
;
653 case SD_DHCP_OPTION_VENDOR_SPECIFIC
:
656 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
660 p
= memdup(option
, len
);
664 free(lease
->vendor_specific
);
665 lease
->vendor_specific
= p
;
668 lease
->vendor_specific_len
= len
;
671 case SD_DHCP_OPTION_PRIVATE_BASE
... SD_DHCP_OPTION_PRIVATE_LAST
:
672 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
679 log_debug("Ignoring option DHCP option %"PRIu8
" while parsing.", code
);
686 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
687 struct sd_dhcp_raw_option
*cur
, *option
;
691 LIST_FOREACH(options
, cur
, lease
->private_options
) {
694 if (tag
== cur
->tag
) {
695 log_debug("Ignoring duplicate option, tagged %i.", tag
);
700 option
= new(struct sd_dhcp_raw_option
, 1);
705 option
->length
= len
;
706 option
->data
= memdup(data
, len
);
712 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
716 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
717 sd_dhcp_lease
*lease
;
719 lease
= new0(sd_dhcp_lease
, 1);
723 lease
->router
= INADDR_ANY
;
730 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
731 _cleanup_free_
char *temp_path
= NULL
;
732 _cleanup_fclose_
FILE *f
= NULL
;
733 struct sd_dhcp_raw_option
*option
;
734 struct in_addr address
;
735 const struct in_addr
*addresses
;
736 const void *client_id
, *data
;
737 size_t client_id_len
, data_len
;
740 _cleanup_free_ sd_dhcp_route
**routes
= NULL
;
741 uint32_t t1
, t2
, lifetime
;
747 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
751 fchmod(fileno(f
), 0644);
754 "# This is private data. Do not parse.\n");
756 r
= sd_dhcp_lease_get_address(lease
, &address
);
758 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
760 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
762 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
764 r
= sd_dhcp_lease_get_router(lease
, &address
);
766 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
768 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
770 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
772 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
774 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
776 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
778 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
780 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
782 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
784 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
786 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
788 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
790 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
792 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
794 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
796 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
799 serialize_in_addrs(f
, addresses
, r
);
803 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
806 serialize_in_addrs(f
, addresses
, r
);
810 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
812 fprintf(f
, "DOMAINNAME=%s\n", string
);
814 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
816 fprintf(f
, "HOSTNAME=%s\n", string
);
818 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
820 fprintf(f
, "ROOT_PATH=%s\n", string
);
822 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
824 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
826 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
828 fprintf(f
, "TIMEZONE=%s\n", string
);
830 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
832 _cleanup_free_
char *client_id_hex
;
834 client_id_hex
= hexmem(client_id
, client_id_len
);
835 if (!client_id_hex
) {
839 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
842 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
844 _cleanup_free_
char *option_hex
= NULL
;
846 option_hex
= hexmem(data
, data_len
);
851 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
854 LIST_FOREACH(options
, option
, lease
->private_options
) {
855 char key
[strlen("OPTION_000")+1];
857 xsprintf(key
, "OPTION_%" PRIu8
, option
->tag
);
858 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
863 r
= fflush_and_check(f
);
867 if (rename(temp_path
, lease_file
) < 0) {
876 (void) unlink(temp_path
);
878 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
881 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
883 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
888 *server_address
= NULL
,
895 *client_id_hex
= NULL
,
896 *vendor_specific_hex
= NULL
,
900 *options
[SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
907 r
= dhcp_lease_new(&lease
);
911 r
= parse_env_file(lease_file
, NEWLINE
,
915 "SERVER_IDENTIFIER", &server_address
,
916 "NEXT_SERVER", &next_server
,
917 "BROADCAST", &broadcast
,
921 "DOMAINNAME", &lease
->domainname
,
922 "HOSTNAME", &lease
->hostname
,
923 "ROOT_PATH", &lease
->root_path
,
925 "CLIENTID", &client_id_hex
,
926 "TIMEZONE", &lease
->timezone
,
927 "VENDOR_SPECIFIC", &vendor_specific_hex
,
928 "LIFETIME", &lifetime
,
931 "OPTION_224", &options
[0],
932 "OPTION_225", &options
[1],
933 "OPTION_226", &options
[2],
934 "OPTION_227", &options
[3],
935 "OPTION_228", &options
[4],
936 "OPTION_229", &options
[5],
937 "OPTION_230", &options
[6],
938 "OPTION_231", &options
[7],
939 "OPTION_232", &options
[8],
940 "OPTION_233", &options
[9],
941 "OPTION_234", &options
[10],
942 "OPTION_235", &options
[11],
943 "OPTION_236", &options
[12],
944 "OPTION_237", &options
[13],
945 "OPTION_238", &options
[14],
946 "OPTION_239", &options
[15],
947 "OPTION_240", &options
[16],
948 "OPTION_241", &options
[17],
949 "OPTION_242", &options
[18],
950 "OPTION_243", &options
[19],
951 "OPTION_244", &options
[20],
952 "OPTION_245", &options
[21],
953 "OPTION_246", &options
[22],
954 "OPTION_247", &options
[23],
955 "OPTION_248", &options
[24],
956 "OPTION_249", &options
[25],
957 "OPTION_250", &options
[26],
958 "OPTION_251", &options
[27],
959 "OPTION_252", &options
[28],
960 "OPTION_253", &options
[29],
961 "OPTION_254", &options
[30],
967 r
= inet_pton(AF_INET
, address
, &lease
->address
);
969 log_debug("Failed to parse address %s, ignoring.", address
);
973 r
= inet_pton(AF_INET
, router
, &lease
->router
);
975 log_debug("Failed to parse router %s, ignoring.", router
);
979 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
981 log_debug("Failed to parse netmask %s, ignoring.", netmask
);
983 lease
->have_subnet_mask
= true;
986 if (server_address
) {
987 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
989 log_debug("Failed to parse server address %s, ignoring.", server_address
);
993 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
995 log_debug("Failed to parse next server %s, ignoring.", next_server
);
999 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
1001 log_debug("Failed to parse broadcast address %s, ignoring.", broadcast
);
1003 lease
->have_broadcast
= true;
1007 r
= deserialize_in_addrs(&lease
->dns
, dns
);
1009 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
1011 lease
->dns_size
= r
;
1015 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
1017 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1019 lease
->ntp_size
= r
;
1023 r
= safe_atou16(mtu
, &lease
->mtu
);
1025 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1029 r
= deserialize_dhcp_routes(
1030 &lease
->static_route
,
1031 &lease
->static_route_size
,
1032 &lease
->static_route_allocated
,
1035 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1039 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1041 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1045 r
= safe_atou32(t1
, &lease
->t1
);
1047 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1051 r
= safe_atou32(t2
, &lease
->t2
);
1053 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1056 if (client_id_hex
) {
1057 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1059 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1062 if (vendor_specific_hex
) {
1063 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1065 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1068 for (i
= 0; i
<= SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
; i
++) {
1069 _cleanup_free_
void *data
= NULL
;
1075 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1077 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1081 r
= dhcp_lease_insert_private_option(lease
, SD_DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1092 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1093 struct in_addr address
, mask
;
1098 if (lease
->address
== 0)
1101 address
.s_addr
= lease
->address
;
1103 /* fall back to the default subnet masks based on address class */
1104 r
= in_addr_default_subnet_mask(&address
, &mask
);
1108 lease
->subnet_mask
= mask
.s_addr
;
1109 lease
->have_subnet_mask
= true;
1114 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1115 assert_return(lease
, -EINVAL
);
1116 assert_return(client_id
, -EINVAL
);
1117 assert_return(client_id_len
, -EINVAL
);
1119 if (!lease
->client_id
)
1122 *client_id
= lease
->client_id
;
1123 *client_id_len
= lease
->client_id_len
;
1128 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1129 assert_return(lease
, -EINVAL
);
1130 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1132 if (client_id_len
<= 0)
1133 lease
->client_id
= mfree(lease
->client_id
);
1137 p
= memdup(client_id
, client_id_len
);
1141 free(lease
->client_id
);
1142 lease
->client_id
= p
;
1143 lease
->client_id_len
= client_id_len
;
1149 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1150 assert_return(lease
, -EINVAL
);
1151 assert_return(tz
, -EINVAL
);
1153 if (!lease
->timezone
)
1156 *tz
= lease
->timezone
;
1160 int sd_dhcp_route_get_destination(sd_dhcp_route
*route
, struct in_addr
*destination
) {
1161 assert_return(route
, -EINVAL
);
1162 assert_return(destination
, -EINVAL
);
1164 *destination
= route
->dst_addr
;
1168 int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route
*route
, uint8_t *length
) {
1169 assert_return(route
, -EINVAL
);
1170 assert_return(length
, -EINVAL
);
1172 *length
= route
->dst_prefixlen
;
1176 int sd_dhcp_route_get_gateway(sd_dhcp_route
*route
, struct in_addr
*gateway
) {
1177 assert_return(route
, -EINVAL
);
1178 assert_return(gateway
, -EINVAL
);
1180 *gateway
= route
->gw_addr
;