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 "dhcp-lease-internal.h"
30 #include "dhcp-protocol.h"
31 #include "dns-domain.h"
34 #include "hostname-util.h"
35 #include "in-addr-util.h"
36 #include "network-internal.h"
37 #include "parse-util.h"
38 #include "unaligned.h"
40 int sd_dhcp_lease_get_address(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
41 assert_return(lease
, -EINVAL
);
42 assert_return(addr
, -EINVAL
);
44 if (lease
->address
== 0)
47 addr
->s_addr
= lease
->address
;
51 int sd_dhcp_lease_get_broadcast(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
52 assert_return(lease
, -EINVAL
);
53 assert_return(addr
, -EINVAL
);
55 if (!lease
->have_broadcast
)
58 addr
->s_addr
= lease
->broadcast
;
62 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease
*lease
, uint32_t *lifetime
) {
63 assert_return(lease
, -EINVAL
);
64 assert_return(lifetime
, -EINVAL
);
66 if (lease
->lifetime
<= 0)
69 *lifetime
= lease
->lifetime
;
73 int sd_dhcp_lease_get_t1(sd_dhcp_lease
*lease
, uint32_t *t1
) {
74 assert_return(lease
, -EINVAL
);
75 assert_return(t1
, -EINVAL
);
84 int sd_dhcp_lease_get_t2(sd_dhcp_lease
*lease
, uint32_t *t2
) {
85 assert_return(lease
, -EINVAL
);
86 assert_return(t2
, -EINVAL
);
95 int sd_dhcp_lease_get_mtu(sd_dhcp_lease
*lease
, uint16_t *mtu
) {
96 assert_return(lease
, -EINVAL
);
97 assert_return(mtu
, -EINVAL
);
106 int sd_dhcp_lease_get_dns(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
107 assert_return(lease
, -EINVAL
);
108 assert_return(addr
, -EINVAL
);
110 if (lease
->dns_size
<= 0)
114 return (int) lease
->dns_size
;
117 int sd_dhcp_lease_get_ntp(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
118 assert_return(lease
, -EINVAL
);
119 assert_return(addr
, -EINVAL
);
121 if (lease
->ntp_size
<= 0)
125 return (int) lease
->ntp_size
;
128 int sd_dhcp_lease_get_domainname(sd_dhcp_lease
*lease
, const char **domainname
) {
129 assert_return(lease
, -EINVAL
);
130 assert_return(domainname
, -EINVAL
);
132 if (!lease
->domainname
)
135 *domainname
= lease
->domainname
;
139 int sd_dhcp_lease_get_hostname(sd_dhcp_lease
*lease
, const char **hostname
) {
140 assert_return(lease
, -EINVAL
);
141 assert_return(hostname
, -EINVAL
);
143 if (!lease
->hostname
)
146 *hostname
= lease
->hostname
;
150 int sd_dhcp_lease_get_root_path(sd_dhcp_lease
*lease
, const char **root_path
) {
151 assert_return(lease
, -EINVAL
);
152 assert_return(root_path
, -EINVAL
);
154 if (!lease
->root_path
)
157 *root_path
= lease
->root_path
;
161 int sd_dhcp_lease_get_router(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
162 assert_return(lease
, -EINVAL
);
163 assert_return(addr
, -EINVAL
);
165 if (lease
->router
== 0)
168 addr
->s_addr
= lease
->router
;
172 int sd_dhcp_lease_get_netmask(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
173 assert_return(lease
, -EINVAL
);
174 assert_return(addr
, -EINVAL
);
176 if (!lease
->have_subnet_mask
)
179 addr
->s_addr
= lease
->subnet_mask
;
183 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
184 assert_return(lease
, -EINVAL
);
185 assert_return(addr
, -EINVAL
);
187 if (lease
->server_address
== 0)
190 addr
->s_addr
= lease
->server_address
;
194 int sd_dhcp_lease_get_next_server(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
195 assert_return(lease
, -EINVAL
);
196 assert_return(addr
, -EINVAL
);
198 if (lease
->next_server
== 0)
201 addr
->s_addr
= lease
->next_server
;
205 int sd_dhcp_lease_get_routes(sd_dhcp_lease
*lease
, struct sd_dhcp_route
**routes
) {
206 assert_return(lease
, -EINVAL
);
207 assert_return(routes
, -EINVAL
);
209 if (lease
->static_route_size
<= 0)
212 *routes
= lease
->static_route
;
213 return (int) lease
->static_route_size
;
216 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease
*lease
, const void **data
, size_t *data_len
) {
217 assert_return(lease
, -EINVAL
);
218 assert_return(data
, -EINVAL
);
219 assert_return(data_len
, -EINVAL
);
221 if (lease
->vendor_specific_len
<= 0)
224 *data
= lease
->vendor_specific
;
225 *data_len
= lease
->vendor_specific_len
;
229 sd_dhcp_lease
*sd_dhcp_lease_ref(sd_dhcp_lease
*lease
) {
234 assert(lease
->n_ref
>= 1);
240 sd_dhcp_lease
*sd_dhcp_lease_unref(sd_dhcp_lease
*lease
) {
245 assert(lease
->n_ref
>= 1);
248 if (lease
->n_ref
> 0)
251 while (lease
->private_options
) {
252 struct sd_dhcp_raw_option
*option
= lease
->private_options
;
254 LIST_REMOVE(options
, lease
->private_options
, option
);
260 free(lease
->hostname
);
261 free(lease
->domainname
);
264 free(lease
->static_route
);
265 free(lease
->client_id
);
266 free(lease
->vendor_specific
);
272 static int lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
279 *ret
= unaligned_read_be32((be32_t
*) option
);
286 static int lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
293 *ret
= unaligned_read_be16((be16_t
*) option
);
300 static int lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
307 memcpy(ret
, option
, 4);
311 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
321 * One trailing NUL byte is OK, we don't mind. See:
322 * https://github.com/systemd/systemd/issues/1337
324 if (memchr(option
, 0, len
- 1))
327 string
= strndup((const char *) option
, len
);
338 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
348 struct in_addr
*addresses
;
353 n_addresses
= len
/ 4;
355 addresses
= newdup(struct in_addr
, option
, n_addresses
);
361 *n_ret
= n_addresses
;
367 static int lease_parse_routes(
368 const uint8_t *option
, size_t len
,
369 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
373 assert(option
|| len
<= 0);
376 assert(routes_allocated
);
384 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
388 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
391 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
393 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
397 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
398 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
401 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
411 /* parses RFC3442 Classless Static Route Option */
412 static int lease_parse_classless_routes(
413 const uint8_t *option
, size_t len
,
414 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
416 assert(option
|| len
<= 0);
419 assert(routes_allocated
);
424 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
428 struct sd_dhcp_route
*route
;
430 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
433 route
= *routes
+ *routes_size
;
435 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
436 route
->dst_prefixlen
= *option
;
440 /* can't have more than 4 octets in IPv4 */
441 if (dst_octets
> 4 || len
< dst_octets
)
444 route
->dst_addr
.s_addr
= 0;
445 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
446 option
+= dst_octets
;
452 lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
);
462 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
463 sd_dhcp_lease
*lease
= userdata
;
470 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
471 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
473 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
477 case DHCP_OPTION_SERVER_IDENTIFIER
:
478 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
480 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
484 case DHCP_OPTION_SUBNET_MASK
:
485 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
487 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
489 lease
->have_subnet_mask
= true;
492 case DHCP_OPTION_BROADCAST
:
493 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
495 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
497 lease
->have_broadcast
= true;
500 case DHCP_OPTION_ROUTER
:
502 r
= lease_parse_be32(option
, 4, &lease
->router
);
504 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
508 case DHCP_OPTION_DOMAIN_NAME_SERVER
:
509 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
511 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
514 case DHCP_OPTION_NTP_SERVER
:
515 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
517 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
520 case DHCP_OPTION_STATIC_ROUTE
:
521 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
523 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
526 case DHCP_OPTION_INTERFACE_MTU
:
527 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
529 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
532 case DHCP_OPTION_DOMAIN_NAME
: {
533 _cleanup_free_
char *domainname
= NULL
, *normalized
= NULL
;
535 r
= lease_parse_string(option
, len
, &domainname
);
537 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
541 r
= dns_name_normalize(domainname
, &normalized
);
543 log_debug_errno(r
, "Failed to normalize domain name '%s': %m", domainname
);
547 if (is_localhost(normalized
)) {
548 log_debug_errno(r
, "Detected 'localhost' as suggested domain name, ignoring.");
552 free(lease
->domainname
);
553 lease
->domainname
= normalized
;
559 case DHCP_OPTION_HOST_NAME
: {
560 _cleanup_free_
char *hostname
= NULL
, *normalized
= NULL
;
562 r
= lease_parse_string(option
, len
, &hostname
);
564 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
568 r
= dns_name_normalize(hostname
, &normalized
);
570 log_debug_errno(r
, "Failed to normalize host name '%s', ignoring: %m", hostname
);
574 if (is_localhost(normalized
)) {
575 log_debug_errno(r
, "Detected 'localhost' as suggested host name, ignoring.");
579 free(lease
->hostname
);
580 lease
->hostname
= normalized
;
586 case DHCP_OPTION_ROOT_PATH
:
587 r
= lease_parse_string(option
, len
, &lease
->root_path
);
589 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
592 case DHCP_OPTION_RENEWAL_T1_TIME
:
593 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
595 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
598 case DHCP_OPTION_REBINDING_T2_TIME
:
599 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
601 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
604 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
605 r
= lease_parse_classless_routes(
607 &lease
->static_route
,
608 &lease
->static_route_size
,
609 &lease
->static_route_allocated
);
611 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
614 case DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
615 _cleanup_free_
char *tz
= NULL
;
617 r
= lease_parse_string(option
, len
, &tz
);
619 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
623 if (!timezone_is_valid(tz
)) {
624 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
628 free(lease
->timezone
);
629 lease
->timezone
= tz
;
635 case DHCP_OPTION_VENDOR_SPECIFIC
:
638 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
642 p
= memdup(option
, len
);
646 free(lease
->vendor_specific
);
647 lease
->vendor_specific
= p
;
650 lease
->vendor_specific_len
= len
;
653 case DHCP_OPTION_PRIVATE_BASE
... DHCP_OPTION_PRIVATE_LAST
:
654 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
661 log_debug("Ignoring option DHCP option %i while parsing.", code
);
668 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
669 struct sd_dhcp_raw_option
*cur
, *option
;
673 LIST_FOREACH(options
, cur
, lease
->private_options
) {
676 if (tag
== cur
->tag
) {
677 log_debug("Ignoring duplicate option, tagged %i.", tag
);
682 option
= new(struct sd_dhcp_raw_option
, 1);
687 option
->length
= len
;
688 option
->data
= memdup(data
, len
);
694 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
698 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
699 sd_dhcp_lease
*lease
;
701 lease
= new0(sd_dhcp_lease
, 1);
705 lease
->router
= INADDR_ANY
;
712 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
713 _cleanup_free_
char *temp_path
= NULL
;
714 _cleanup_fclose_
FILE *f
= NULL
;
715 struct sd_dhcp_raw_option
*option
;
716 struct in_addr address
;
717 const struct in_addr
*addresses
;
718 const void *client_id
, *data
;
719 size_t client_id_len
, data_len
;
722 struct sd_dhcp_route
*routes
;
723 uint32_t t1
, t2
, lifetime
;
729 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
733 fchmod(fileno(f
), 0644);
736 "# This is private data. Do not parse.\n");
738 r
= sd_dhcp_lease_get_address(lease
, &address
);
740 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
742 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
744 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
746 r
= sd_dhcp_lease_get_router(lease
, &address
);
748 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
750 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
752 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
754 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
756 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
758 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
760 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
762 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
764 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
766 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
768 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
770 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
772 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
774 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
776 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
778 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
781 serialize_in_addrs(f
, addresses
, r
);
785 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
788 serialize_in_addrs(f
, addresses
, r
);
792 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
794 fprintf(f
, "DOMAINNAME=%s\n", string
);
796 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
798 fprintf(f
, "HOSTNAME=%s\n", string
);
800 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
802 fprintf(f
, "ROOT_PATH=%s\n", string
);
804 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
806 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
808 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
810 fprintf(f
, "TIMEZONE=%s\n", string
);
812 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
814 _cleanup_free_
char *client_id_hex
;
816 client_id_hex
= hexmem(client_id
, client_id_len
);
817 if (!client_id_hex
) {
821 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
824 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
826 _cleanup_free_
char *option_hex
= NULL
;
828 option_hex
= hexmem(data
, data_len
);
833 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
836 LIST_FOREACH(options
, option
, lease
->private_options
) {
837 char key
[strlen("OPTION_000")+1];
839 snprintf(key
, sizeof(key
), "OPTION_%"PRIu8
, option
->tag
);
840 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
845 r
= fflush_and_check(f
);
849 if (rename(temp_path
, lease_file
) < 0) {
858 (void) unlink(temp_path
);
860 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
863 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
865 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
870 *server_address
= NULL
,
877 *client_id_hex
= NULL
,
878 *vendor_specific_hex
= NULL
,
882 *options
[DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
889 r
= dhcp_lease_new(&lease
);
893 r
= parse_env_file(lease_file
, NEWLINE
,
897 "SERVER_IDENTIFIER", &server_address
,
898 "NEXT_SERVER", &next_server
,
899 "BROADCAST", &broadcast
,
903 "DOMAINNAME", &lease
->domainname
,
904 "HOSTNAME", &lease
->hostname
,
905 "ROOT_PATH", &lease
->root_path
,
907 "CLIENTID", &client_id_hex
,
908 "TIMEZONE", &lease
->timezone
,
909 "VENDOR_SPECIFIC", &vendor_specific_hex
,
910 "LIFETIME", &lifetime
,
913 "OPTION_224", &options
[0],
914 "OPTION_225", &options
[1],
915 "OPTION_226", &options
[2],
916 "OPTION_227", &options
[3],
917 "OPTION_228", &options
[4],
918 "OPTION_229", &options
[5],
919 "OPTION_230", &options
[6],
920 "OPTION_231", &options
[7],
921 "OPTION_232", &options
[8],
922 "OPTION_233", &options
[9],
923 "OPTION_234", &options
[10],
924 "OPTION_235", &options
[11],
925 "OPTION_236", &options
[12],
926 "OPTION_237", &options
[13],
927 "OPTION_238", &options
[14],
928 "OPTION_239", &options
[15],
929 "OPTION_240", &options
[16],
930 "OPTION_241", &options
[17],
931 "OPTION_242", &options
[18],
932 "OPTION_243", &options
[19],
933 "OPTION_244", &options
[20],
934 "OPTION_245", &options
[21],
935 "OPTION_246", &options
[22],
936 "OPTION_247", &options
[23],
937 "OPTION_248", &options
[24],
938 "OPTION_249", &options
[25],
939 "OPTION_250", &options
[26],
940 "OPTION_251", &options
[27],
941 "OPTION_252", &options
[28],
942 "OPTION_253", &options
[29],
943 "OPTION_254", &options
[30],
949 r
= inet_pton(AF_INET
, address
, &lease
->address
);
951 log_debug_errno(errno
, "Failed to parse address %s, ignoring: %m", address
);
955 r
= inet_pton(AF_INET
, router
, &lease
->router
);
957 log_debug_errno(errno
, "Failed to parse router %s, ignoring: %m", router
);
961 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
963 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", netmask
);
965 lease
->have_subnet_mask
= true;
968 if (server_address
) {
969 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
971 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", server_address
);
975 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
977 log_debug_errno(errno
, "Failed to parse next server %s, ignoring: %m", next_server
);
981 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
983 log_debug_errno(errno
, "Failed to parse broadcast address %s, ignoring: %m", broadcast
);
985 lease
->have_broadcast
= true;
989 r
= deserialize_in_addrs(&lease
->dns
, dns
);
991 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
997 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
999 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1001 lease
->ntp_size
= r
;
1005 r
= safe_atou16(mtu
, &lease
->mtu
);
1007 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1011 r
= deserialize_dhcp_routes(
1012 &lease
->static_route
,
1013 &lease
->static_route_size
,
1014 &lease
->static_route_allocated
,
1017 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1021 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1023 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1027 r
= safe_atou32(t1
, &lease
->t1
);
1029 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1033 r
= safe_atou32(t2
, &lease
->t2
);
1035 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1038 if (client_id_hex
) {
1039 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1041 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1044 if (vendor_specific_hex
) {
1045 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1047 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1050 for (i
= 0; i
<= DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
; i
++) {
1051 _cleanup_free_
void *data
= NULL
;
1057 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1059 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1063 r
= dhcp_lease_insert_private_option(lease
, DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1074 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1075 struct in_addr address
, mask
;
1080 if (lease
->address
== 0)
1083 address
.s_addr
= lease
->address
;
1085 /* fall back to the default subnet masks based on address class */
1086 r
= in_addr_default_subnet_mask(&address
, &mask
);
1090 lease
->subnet_mask
= mask
.s_addr
;
1091 lease
->have_subnet_mask
= true;
1096 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1097 assert_return(lease
, -EINVAL
);
1098 assert_return(client_id
, -EINVAL
);
1099 assert_return(client_id_len
, -EINVAL
);
1101 if (!lease
->client_id
)
1104 *client_id
= lease
->client_id
;
1105 *client_id_len
= lease
->client_id_len
;
1110 int dhcp_lease_set_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
|| client_id_len
<= 0, -EINVAL
);
1114 if (client_id_len
<= 0)
1115 lease
->client_id
= mfree(lease
->client_id
);
1119 p
= memdup(client_id
, client_id_len
);
1123 free(lease
->client_id
);
1124 lease
->client_id
= p
;
1125 lease
->client_id_len
= client_id_len
;
1131 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1132 assert_return(lease
, -EINVAL
);
1133 assert_return(tz
, -EINVAL
);
1135 if (!lease
->timezone
)
1138 *tz
= lease
->timezone
;