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 "unaligned.h"
39 int sd_dhcp_lease_get_address(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
40 assert_return(lease
, -EINVAL
);
41 assert_return(addr
, -EINVAL
);
43 if (lease
->address
== 0)
46 addr
->s_addr
= lease
->address
;
50 int sd_dhcp_lease_get_broadcast(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
51 assert_return(lease
, -EINVAL
);
52 assert_return(addr
, -EINVAL
);
54 if (!lease
->have_broadcast
)
57 addr
->s_addr
= lease
->broadcast
;
61 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease
*lease
, uint32_t *lifetime
) {
62 assert_return(lease
, -EINVAL
);
63 assert_return(lifetime
, -EINVAL
);
65 if (lease
->lifetime
<= 0)
68 *lifetime
= lease
->lifetime
;
72 int sd_dhcp_lease_get_t1(sd_dhcp_lease
*lease
, uint32_t *t1
) {
73 assert_return(lease
, -EINVAL
);
74 assert_return(t1
, -EINVAL
);
83 int sd_dhcp_lease_get_t2(sd_dhcp_lease
*lease
, uint32_t *t2
) {
84 assert_return(lease
, -EINVAL
);
85 assert_return(t2
, -EINVAL
);
94 int sd_dhcp_lease_get_mtu(sd_dhcp_lease
*lease
, uint16_t *mtu
) {
95 assert_return(lease
, -EINVAL
);
96 assert_return(mtu
, -EINVAL
);
105 int sd_dhcp_lease_get_dns(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
106 assert_return(lease
, -EINVAL
);
107 assert_return(addr
, -EINVAL
);
109 if (lease
->dns_size
<= 0)
113 return (int) lease
->dns_size
;
116 int sd_dhcp_lease_get_ntp(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
117 assert_return(lease
, -EINVAL
);
118 assert_return(addr
, -EINVAL
);
120 if (lease
->ntp_size
<= 0)
124 return (int) lease
->ntp_size
;
127 int sd_dhcp_lease_get_domainname(sd_dhcp_lease
*lease
, const char **domainname
) {
128 assert_return(lease
, -EINVAL
);
129 assert_return(domainname
, -EINVAL
);
131 if (!lease
->domainname
)
134 *domainname
= lease
->domainname
;
138 int sd_dhcp_lease_get_hostname(sd_dhcp_lease
*lease
, const char **hostname
) {
139 assert_return(lease
, -EINVAL
);
140 assert_return(hostname
, -EINVAL
);
142 if (!lease
->hostname
)
145 *hostname
= lease
->hostname
;
149 int sd_dhcp_lease_get_root_path(sd_dhcp_lease
*lease
, const char **root_path
) {
150 assert_return(lease
, -EINVAL
);
151 assert_return(root_path
, -EINVAL
);
153 if (!lease
->root_path
)
156 *root_path
= lease
->root_path
;
160 int sd_dhcp_lease_get_router(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
161 assert_return(lease
, -EINVAL
);
162 assert_return(addr
, -EINVAL
);
164 if (lease
->router
== 0)
167 addr
->s_addr
= lease
->router
;
171 int sd_dhcp_lease_get_netmask(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
172 assert_return(lease
, -EINVAL
);
173 assert_return(addr
, -EINVAL
);
175 if (!lease
->have_subnet_mask
)
178 addr
->s_addr
= lease
->subnet_mask
;
182 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
183 assert_return(lease
, -EINVAL
);
184 assert_return(addr
, -EINVAL
);
186 if (lease
->server_address
== 0)
189 addr
->s_addr
= lease
->server_address
;
193 int sd_dhcp_lease_get_next_server(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
194 assert_return(lease
, -EINVAL
);
195 assert_return(addr
, -EINVAL
);
197 if (lease
->next_server
== 0)
200 addr
->s_addr
= lease
->next_server
;
204 int sd_dhcp_lease_get_routes(sd_dhcp_lease
*lease
, struct sd_dhcp_route
**routes
) {
205 assert_return(lease
, -EINVAL
);
206 assert_return(routes
, -EINVAL
);
208 if (lease
->static_route_size
<= 0)
211 *routes
= lease
->static_route
;
212 return (int) lease
->static_route_size
;
215 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease
*lease
, const void **data
, size_t *data_len
) {
216 assert_return(lease
, -EINVAL
);
217 assert_return(data
, -EINVAL
);
218 assert_return(data_len
, -EINVAL
);
220 if (lease
->vendor_specific_len
<= 0)
223 *data
= lease
->vendor_specific
;
224 *data_len
= lease
->vendor_specific_len
;
228 sd_dhcp_lease
*sd_dhcp_lease_ref(sd_dhcp_lease
*lease
) {
233 assert(lease
->n_ref
>= 1);
239 sd_dhcp_lease
*sd_dhcp_lease_unref(sd_dhcp_lease
*lease
) {
244 assert(lease
->n_ref
>= 1);
247 if (lease
->n_ref
> 0)
250 while (lease
->private_options
) {
251 struct sd_dhcp_raw_option
*option
= lease
->private_options
;
253 LIST_REMOVE(options
, lease
->private_options
, option
);
259 free(lease
->hostname
);
260 free(lease
->domainname
);
263 free(lease
->static_route
);
264 free(lease
->client_id
);
265 free(lease
->vendor_specific
);
271 static int lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
278 *ret
= unaligned_read_be32((be32_t
*) option
);
285 static int lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
292 *ret
= unaligned_read_be16((be16_t
*) option
);
299 static int lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
306 memcpy(ret
, option
, 4);
310 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
320 * One trailing NUL byte is OK, we don't mind. See:
321 * https://github.com/systemd/systemd/issues/1337
323 if (memchr(option
, 0, len
- 1))
326 string
= strndup((const char *) option
, len
);
337 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
347 struct in_addr
*addresses
;
352 n_addresses
= len
/ 4;
354 addresses
= newdup(struct in_addr
, option
, n_addresses
);
360 *n_ret
= n_addresses
;
366 static int lease_parse_routes(
367 const uint8_t *option
, size_t len
,
368 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
372 assert(option
|| len
<= 0);
375 assert(routes_allocated
);
383 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
387 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
390 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
392 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
396 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
397 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
400 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
410 /* parses RFC3442 Classless Static Route Option */
411 static int lease_parse_classless_routes(
412 const uint8_t *option
, size_t len
,
413 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
415 assert(option
|| len
<= 0);
418 assert(routes_allocated
);
423 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
427 struct sd_dhcp_route
*route
;
429 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
432 route
= *routes
+ *routes_size
;
434 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
435 route
->dst_prefixlen
= *option
;
439 /* can't have more than 4 octets in IPv4 */
440 if (dst_octets
> 4 || len
< dst_octets
)
443 route
->dst_addr
.s_addr
= 0;
444 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
445 option
+= dst_octets
;
451 lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
);
461 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
462 sd_dhcp_lease
*lease
= userdata
;
469 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
470 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
472 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
476 case DHCP_OPTION_SERVER_IDENTIFIER
:
477 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
479 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
483 case DHCP_OPTION_SUBNET_MASK
:
484 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
486 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
488 lease
->have_subnet_mask
= true;
491 case DHCP_OPTION_BROADCAST
:
492 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
494 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
496 lease
->have_broadcast
= true;
499 case DHCP_OPTION_ROUTER
:
501 r
= lease_parse_be32(option
, 4, &lease
->router
);
503 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
507 case DHCP_OPTION_DOMAIN_NAME_SERVER
:
508 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
510 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
513 case DHCP_OPTION_NTP_SERVER
:
514 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
516 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
519 case DHCP_OPTION_STATIC_ROUTE
:
520 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
522 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
525 case DHCP_OPTION_INTERFACE_MTU
:
526 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
528 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
531 case DHCP_OPTION_DOMAIN_NAME
: {
532 _cleanup_free_
char *domainname
= NULL
, *normalized
= NULL
;
534 r
= lease_parse_string(option
, len
, &domainname
);
536 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
540 r
= dns_name_normalize(domainname
, &normalized
);
542 log_debug_errno(r
, "Failed to normalize domain name '%s': %m", domainname
);
546 if (is_localhost(normalized
)) {
547 log_debug_errno(r
, "Detected 'localhost' as suggested domain name, ignoring.");
551 free(lease
->domainname
);
552 lease
->domainname
= normalized
;
558 case DHCP_OPTION_HOST_NAME
: {
559 _cleanup_free_
char *hostname
= NULL
, *normalized
= NULL
;
561 r
= lease_parse_string(option
, len
, &hostname
);
563 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
567 r
= dns_name_normalize(hostname
, &normalized
);
569 log_debug_errno(r
, "Failed to normalize host name '%s', ignoring: %m", hostname
);
573 if (is_localhost(normalized
)) {
574 log_debug_errno(r
, "Detected 'localhost' as suggested host name, ignoring.");
578 free(lease
->hostname
);
579 lease
->hostname
= normalized
;
585 case DHCP_OPTION_ROOT_PATH
:
586 r
= lease_parse_string(option
, len
, &lease
->root_path
);
588 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
591 case DHCP_OPTION_RENEWAL_T1_TIME
:
592 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
594 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
597 case DHCP_OPTION_REBINDING_T2_TIME
:
598 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
600 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
603 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
604 r
= lease_parse_classless_routes(
606 &lease
->static_route
,
607 &lease
->static_route_size
,
608 &lease
->static_route_allocated
);
610 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
613 case DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
614 _cleanup_free_
char *tz
= NULL
;
616 r
= lease_parse_string(option
, len
, &tz
);
618 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
622 if (!timezone_is_valid(tz
)) {
623 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
627 free(lease
->timezone
);
628 lease
->timezone
= tz
;
634 case DHCP_OPTION_VENDOR_SPECIFIC
:
637 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
641 p
= memdup(option
, len
);
645 free(lease
->vendor_specific
);
646 lease
->vendor_specific
= p
;
649 lease
->vendor_specific_len
= len
;
652 case DHCP_OPTION_PRIVATE_BASE
... DHCP_OPTION_PRIVATE_LAST
:
653 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
660 log_debug("Ignoring option DHCP option %i while parsing.", code
);
667 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
668 struct sd_dhcp_raw_option
*cur
, *option
;
672 LIST_FOREACH(options
, cur
, lease
->private_options
) {
675 if (tag
== cur
->tag
) {
676 log_debug("Ignoring duplicate option, tagged %i.", tag
);
681 option
= new(struct sd_dhcp_raw_option
, 1);
686 option
->length
= len
;
687 option
->data
= memdup(data
, len
);
693 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
697 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
698 sd_dhcp_lease
*lease
;
700 lease
= new0(sd_dhcp_lease
, 1);
704 lease
->router
= INADDR_ANY
;
711 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
712 _cleanup_free_
char *temp_path
= NULL
;
713 _cleanup_fclose_
FILE *f
= NULL
;
714 struct sd_dhcp_raw_option
*option
;
715 struct in_addr address
;
716 const struct in_addr
*addresses
;
717 const void *client_id
, *data
;
718 size_t client_id_len
, data_len
;
721 struct sd_dhcp_route
*routes
;
722 uint32_t t1
, t2
, lifetime
;
728 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
732 fchmod(fileno(f
), 0644);
735 "# This is private data. Do not parse.\n");
737 r
= sd_dhcp_lease_get_address(lease
, &address
);
739 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
741 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
743 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
745 r
= sd_dhcp_lease_get_router(lease
, &address
);
747 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
749 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
751 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
753 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
755 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
757 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
759 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
761 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
763 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
765 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
767 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
769 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
771 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
773 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
775 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
777 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
780 serialize_in_addrs(f
, addresses
, r
);
784 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
787 serialize_in_addrs(f
, addresses
, r
);
791 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
793 fprintf(f
, "DOMAINNAME=%s\n", string
);
795 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
797 fprintf(f
, "HOSTNAME=%s\n", string
);
799 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
801 fprintf(f
, "ROOT_PATH=%s\n", string
);
803 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
805 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
807 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
809 fprintf(f
, "TIMEZONE=%s\n", string
);
811 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
813 _cleanup_free_
char *client_id_hex
;
815 client_id_hex
= hexmem(client_id
, client_id_len
);
816 if (!client_id_hex
) {
820 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
823 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
825 _cleanup_free_
char *option_hex
= NULL
;
827 option_hex
= hexmem(data
, data_len
);
832 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
835 LIST_FOREACH(options
, option
, lease
->private_options
) {
836 char key
[strlen("OPTION_000")+1];
838 snprintf(key
, sizeof(key
), "OPTION_%"PRIu8
, option
->tag
);
839 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
844 r
= fflush_and_check(f
);
848 if (rename(temp_path
, lease_file
) < 0) {
857 (void) unlink(temp_path
);
859 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
862 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
864 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
869 *server_address
= NULL
,
876 *client_id_hex
= NULL
,
877 *vendor_specific_hex
= NULL
,
881 *options
[DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
888 r
= dhcp_lease_new(&lease
);
892 r
= parse_env_file(lease_file
, NEWLINE
,
896 "SERVER_IDENTIFIER", &server_address
,
897 "NEXT_SERVER", &next_server
,
898 "BROADCAST", &broadcast
,
902 "DOMAINNAME", &lease
->domainname
,
903 "HOSTNAME", &lease
->hostname
,
904 "ROOT_PATH", &lease
->root_path
,
906 "CLIENTID", &client_id_hex
,
907 "TIMEZONE", &lease
->timezone
,
908 "VENDOR_SPECIFIC", &vendor_specific_hex
,
909 "LIFETIME", &lifetime
,
912 "OPTION_224", &options
[0],
913 "OPTION_225", &options
[1],
914 "OPTION_226", &options
[2],
915 "OPTION_227", &options
[3],
916 "OPTION_228", &options
[4],
917 "OPTION_229", &options
[5],
918 "OPTION_230", &options
[6],
919 "OPTION_231", &options
[7],
920 "OPTION_232", &options
[8],
921 "OPTION_233", &options
[9],
922 "OPTION_234", &options
[10],
923 "OPTION_235", &options
[11],
924 "OPTION_236", &options
[12],
925 "OPTION_237", &options
[13],
926 "OPTION_238", &options
[14],
927 "OPTION_239", &options
[15],
928 "OPTION_240", &options
[16],
929 "OPTION_241", &options
[17],
930 "OPTION_242", &options
[18],
931 "OPTION_243", &options
[19],
932 "OPTION_244", &options
[20],
933 "OPTION_245", &options
[21],
934 "OPTION_246", &options
[22],
935 "OPTION_247", &options
[23],
936 "OPTION_248", &options
[24],
937 "OPTION_249", &options
[25],
938 "OPTION_250", &options
[26],
939 "OPTION_251", &options
[27],
940 "OPTION_252", &options
[28],
941 "OPTION_253", &options
[29],
942 "OPTION_254", &options
[30],
948 r
= inet_pton(AF_INET
, address
, &lease
->address
);
950 log_debug_errno(errno
, "Failed to parse address %s, ignoring: %m", address
);
954 r
= inet_pton(AF_INET
, router
, &lease
->router
);
956 log_debug_errno(errno
, "Failed to parse router %s, ignoring: %m", router
);
960 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
962 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", netmask
);
964 lease
->have_subnet_mask
= true;
967 if (server_address
) {
968 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
970 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", server_address
);
974 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
976 log_debug_errno(errno
, "Failed to parse next server %s, ignoring: %m", next_server
);
980 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
982 log_debug_errno(errno
, "Failed to parse broadcast address %s, ignoring: %m", broadcast
);
984 lease
->have_broadcast
= true;
988 r
= deserialize_in_addrs(&lease
->dns
, dns
);
990 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
996 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
998 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1000 lease
->ntp_size
= r
;
1004 r
= safe_atou16(mtu
, &lease
->mtu
);
1006 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1010 r
= deserialize_dhcp_routes(
1011 &lease
->static_route
,
1012 &lease
->static_route_size
,
1013 &lease
->static_route_allocated
,
1016 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1020 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1022 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1026 r
= safe_atou32(t1
, &lease
->t1
);
1028 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1032 r
= safe_atou32(t2
, &lease
->t2
);
1034 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1037 if (client_id_hex
) {
1038 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1040 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1043 if (vendor_specific_hex
) {
1044 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1046 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1049 for (i
= 0; i
<= DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
; i
++) {
1050 _cleanup_free_
void *data
= NULL
;
1056 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1058 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1062 r
= dhcp_lease_insert_private_option(lease
, DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1073 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1074 struct in_addr address
, mask
;
1079 if (lease
->address
== 0)
1082 address
.s_addr
= lease
->address
;
1084 /* fall back to the default subnet masks based on address class */
1085 r
= in_addr_default_subnet_mask(&address
, &mask
);
1089 lease
->subnet_mask
= mask
.s_addr
;
1090 lease
->have_subnet_mask
= true;
1095 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1096 assert_return(lease
, -EINVAL
);
1097 assert_return(client_id
, -EINVAL
);
1098 assert_return(client_id_len
, -EINVAL
);
1100 if (!lease
->client_id
)
1103 *client_id
= lease
->client_id
;
1104 *client_id_len
= lease
->client_id_len
;
1109 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1110 assert_return(lease
, -EINVAL
);
1111 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1113 if (client_id_len
<= 0)
1114 lease
->client_id
= mfree(lease
->client_id
);
1118 p
= memdup(client_id
, client_id_len
);
1122 free(lease
->client_id
);
1123 lease
->client_id
= p
;
1124 lease
->client_id_len
= client_id_len
;
1130 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1131 assert_return(lease
, -EINVAL
);
1132 assert_return(tz
, -EINVAL
);
1134 if (!lease
->timezone
)
1137 *tz
= lease
->timezone
;