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/>.
25 #include <arpa/inet.h>
28 #include "unaligned.h"
29 #include "in-addr-util.h"
30 #include "hostname-util.h"
31 #include "dns-domain.h"
32 #include "network-internal.h"
33 #include "dhcp-protocol.h"
34 #include "dhcp-lease-internal.h"
35 #include "sd-dhcp-lease.h"
37 int sd_dhcp_lease_get_address(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
38 assert_return(lease
, -EINVAL
);
39 assert_return(addr
, -EINVAL
);
41 if (lease
->address
== 0)
44 addr
->s_addr
= lease
->address
;
48 int sd_dhcp_lease_get_broadcast(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
49 assert_return(lease
, -EINVAL
);
50 assert_return(addr
, -EINVAL
);
52 if (!lease
->have_broadcast
)
55 addr
->s_addr
= lease
->broadcast
;
59 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease
*lease
, uint32_t *lifetime
) {
60 assert_return(lease
, -EINVAL
);
61 assert_return(lifetime
, -EINVAL
);
63 if (lease
->lifetime
<= 0)
66 *lifetime
= lease
->lifetime
;
70 int sd_dhcp_lease_get_t1(sd_dhcp_lease
*lease
, uint32_t *t1
) {
71 assert_return(lease
, -EINVAL
);
72 assert_return(t1
, -EINVAL
);
81 int sd_dhcp_lease_get_t2(sd_dhcp_lease
*lease
, uint32_t *t2
) {
82 assert_return(lease
, -EINVAL
);
83 assert_return(t2
, -EINVAL
);
92 int sd_dhcp_lease_get_mtu(sd_dhcp_lease
*lease
, uint16_t *mtu
) {
93 assert_return(lease
, -EINVAL
);
94 assert_return(mtu
, -EINVAL
);
103 int sd_dhcp_lease_get_dns(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
104 assert_return(lease
, -EINVAL
);
105 assert_return(addr
, -EINVAL
);
107 if (lease
->dns_size
<= 0)
111 return (int) lease
->dns_size
;
114 int sd_dhcp_lease_get_ntp(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
115 assert_return(lease
, -EINVAL
);
116 assert_return(addr
, -EINVAL
);
118 if (lease
->ntp_size
<= 0)
122 return (int) lease
->ntp_size
;
125 int sd_dhcp_lease_get_domainname(sd_dhcp_lease
*lease
, const char **domainname
) {
126 assert_return(lease
, -EINVAL
);
127 assert_return(domainname
, -EINVAL
);
129 if (!lease
->domainname
)
132 *domainname
= lease
->domainname
;
136 int sd_dhcp_lease_get_hostname(sd_dhcp_lease
*lease
, const char **hostname
) {
137 assert_return(lease
, -EINVAL
);
138 assert_return(hostname
, -EINVAL
);
140 if (!lease
->hostname
)
143 *hostname
= lease
->hostname
;
147 int sd_dhcp_lease_get_root_path(sd_dhcp_lease
*lease
, const char **root_path
) {
148 assert_return(lease
, -EINVAL
);
149 assert_return(root_path
, -EINVAL
);
151 if (!lease
->root_path
)
154 *root_path
= lease
->root_path
;
158 int sd_dhcp_lease_get_router(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
159 assert_return(lease
, -EINVAL
);
160 assert_return(addr
, -EINVAL
);
162 if (lease
->router
== 0)
165 addr
->s_addr
= lease
->router
;
169 int sd_dhcp_lease_get_netmask(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
170 assert_return(lease
, -EINVAL
);
171 assert_return(addr
, -EINVAL
);
173 if (!lease
->have_subnet_mask
)
176 addr
->s_addr
= lease
->subnet_mask
;
180 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
181 assert_return(lease
, -EINVAL
);
182 assert_return(addr
, -EINVAL
);
184 if (lease
->server_address
== 0)
187 addr
->s_addr
= lease
->server_address
;
191 int sd_dhcp_lease_get_next_server(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
192 assert_return(lease
, -EINVAL
);
193 assert_return(addr
, -EINVAL
);
195 if (lease
->next_server
== 0)
198 addr
->s_addr
= lease
->next_server
;
202 int sd_dhcp_lease_get_routes(sd_dhcp_lease
*lease
, struct sd_dhcp_route
**routes
) {
203 assert_return(lease
, -EINVAL
);
204 assert_return(routes
, -EINVAL
);
206 if (lease
->static_route_size
<= 0)
209 *routes
= lease
->static_route
;
210 return (int) lease
->static_route_size
;
213 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease
*lease
, const void **data
, size_t *data_len
) {
214 assert_return(lease
, -EINVAL
);
215 assert_return(data
, -EINVAL
);
216 assert_return(data_len
, -EINVAL
);
218 if (lease
->vendor_specific_len
<= 0)
221 *data
= lease
->vendor_specific
;
222 *data_len
= lease
->vendor_specific_len
;
226 sd_dhcp_lease
*sd_dhcp_lease_ref(sd_dhcp_lease
*lease
) {
231 assert(lease
->n_ref
>= 1);
237 sd_dhcp_lease
*sd_dhcp_lease_unref(sd_dhcp_lease
*lease
) {
242 assert(lease
->n_ref
>= 1);
245 if (lease
->n_ref
> 0)
248 while (lease
->private_options
) {
249 struct sd_dhcp_raw_option
*option
= lease
->private_options
;
251 LIST_REMOVE(options
, lease
->private_options
, option
);
257 free(lease
->hostname
);
258 free(lease
->domainname
);
261 free(lease
->static_route
);
262 free(lease
->client_id
);
263 free(lease
->vendor_specific
);
269 static int lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
276 *ret
= unaligned_read_be32((be32_t
*) option
);
283 static int lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
290 *ret
= unaligned_read_be16((be16_t
*) option
);
297 static int lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
304 memcpy(ret
, option
, 4);
308 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
317 if (memchr(option
, 0, len
))
320 string
= strndup((const char *)option
, len
);
331 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
341 struct in_addr
*addresses
;
346 n_addresses
= len
/ 4;
348 addresses
= newdup(struct in_addr
, option
, n_addresses
);
354 *n_ret
= n_addresses
;
360 static int lease_parse_routes(
361 const uint8_t *option
, size_t len
,
362 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
366 assert(option
|| len
<= 0);
369 assert(routes_allocated
);
377 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
381 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
384 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
386 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
390 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
391 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
394 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
404 /* parses RFC3442 Classless Static Route Option */
405 static int lease_parse_classless_routes(
406 const uint8_t *option
, size_t len
,
407 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
409 assert(option
|| len
<= 0);
412 assert(routes_allocated
);
417 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
421 struct sd_dhcp_route
*route
;
423 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
426 route
= *routes
+ *routes_size
;
428 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
429 route
->dst_prefixlen
= *option
;
433 /* can't have more than 4 octets in IPv4 */
434 if (dst_octets
> 4 || len
< dst_octets
)
437 route
->dst_addr
.s_addr
= 0;
438 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
439 option
+= dst_octets
;
445 lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
);
455 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
456 sd_dhcp_lease
*lease
= userdata
;
463 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
464 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
466 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
470 case DHCP_OPTION_SERVER_IDENTIFIER
:
471 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
473 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
477 case DHCP_OPTION_SUBNET_MASK
:
478 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
480 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
482 lease
->have_subnet_mask
= true;
485 case DHCP_OPTION_BROADCAST
:
486 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
488 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
490 lease
->have_broadcast
= true;
493 case DHCP_OPTION_ROUTER
:
495 r
= lease_parse_be32(option
, 4, &lease
->router
);
497 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
501 case DHCP_OPTION_DOMAIN_NAME_SERVER
:
502 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
504 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
507 case DHCP_OPTION_NTP_SERVER
:
508 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
510 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
513 case DHCP_OPTION_STATIC_ROUTE
:
514 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
516 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
519 case DHCP_OPTION_INTERFACE_MTU
:
520 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
522 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
525 case DHCP_OPTION_DOMAIN_NAME
: {
526 _cleanup_free_
char *domainname
= NULL
, *normalized
= NULL
;
528 r
= lease_parse_string(option
, len
, &domainname
);
530 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
534 r
= dns_name_normalize(domainname
, &normalized
);
536 log_debug_errno(r
, "Failed to normalize domain name '%s': %m", domainname
);
540 if (is_localhost(normalized
)) {
541 log_debug_errno(r
, "Detected 'localhost' as suggested domain name, ignoring.");
545 free(lease
->domainname
);
546 lease
->domainname
= normalized
;
552 case DHCP_OPTION_HOST_NAME
: {
553 _cleanup_free_
char *hostname
= NULL
, *normalized
= NULL
;
555 r
= lease_parse_string(option
, len
, &hostname
);
557 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
561 r
= dns_name_normalize(hostname
, &normalized
);
563 log_debug_errno(r
, "Failed to normalize host name '%s', ignoring: %m", hostname
);
567 if (is_localhost(normalized
)) {
568 log_debug_errno(r
, "Detected 'localhost' as suggested host name, ignoring.");
572 free(lease
->hostname
);
573 lease
->hostname
= normalized
;
579 case DHCP_OPTION_ROOT_PATH
:
580 r
= lease_parse_string(option
, len
, &lease
->root_path
);
582 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
585 case DHCP_OPTION_RENEWAL_T1_TIME
:
586 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
588 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
591 case DHCP_OPTION_REBINDING_T2_TIME
:
592 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
594 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
597 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
598 r
= lease_parse_classless_routes(
600 &lease
->static_route
,
601 &lease
->static_route_size
,
602 &lease
->static_route_allocated
);
604 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
607 case DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
608 _cleanup_free_
char *tz
= NULL
;
610 r
= lease_parse_string(option
, len
, &tz
);
612 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
616 if (!timezone_is_valid(tz
)) {
617 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
621 free(lease
->timezone
);
622 lease
->timezone
= tz
;
628 case DHCP_OPTION_VENDOR_SPECIFIC
:
631 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
635 p
= memdup(option
, len
);
639 free(lease
->vendor_specific
);
640 lease
->vendor_specific
= p
;
643 lease
->vendor_specific_len
= len
;
646 case DHCP_OPTION_PRIVATE_BASE
... DHCP_OPTION_PRIVATE_LAST
:
647 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
654 log_debug("Ignoring option DHCP option %i while parsing.", code
);
661 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
662 struct sd_dhcp_raw_option
*cur
, *option
;
666 LIST_FOREACH(options
, cur
, lease
->private_options
) {
669 if (tag
== cur
->tag
) {
670 log_debug("Ignoring duplicate option, tagged %i.", tag
);
675 option
= new(struct sd_dhcp_raw_option
, 1);
680 option
->length
= len
;
681 option
->data
= memdup(data
, len
);
687 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
691 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
692 sd_dhcp_lease
*lease
;
694 lease
= new0(sd_dhcp_lease
, 1);
698 lease
->router
= INADDR_ANY
;
705 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
706 _cleanup_free_
char *temp_path
= NULL
;
707 _cleanup_fclose_
FILE *f
= NULL
;
708 struct sd_dhcp_raw_option
*option
;
709 struct in_addr address
;
710 const struct in_addr
*addresses
;
711 const void *client_id
, *data
;
712 size_t client_id_len
, data_len
;
715 struct sd_dhcp_route
*routes
;
716 uint32_t t1
, t2
, lifetime
;
722 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
726 fchmod(fileno(f
), 0644);
729 "# This is private data. Do not parse.\n");
731 r
= sd_dhcp_lease_get_address(lease
, &address
);
733 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
735 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
737 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
739 r
= sd_dhcp_lease_get_router(lease
, &address
);
741 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
743 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
745 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
747 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
749 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
751 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
753 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
755 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
757 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
759 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
761 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
763 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
765 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
767 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
769 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
771 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
774 serialize_in_addrs(f
, addresses
, r
);
778 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
781 serialize_in_addrs(f
, addresses
, r
);
785 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
787 fprintf(f
, "DOMAINNAME=%s\n", string
);
789 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
791 fprintf(f
, "HOSTNAME=%s\n", string
);
793 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
795 fprintf(f
, "ROOT_PATH=%s\n", string
);
797 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
799 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
801 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
803 fprintf(f
, "TIMEZONE=%s\n", string
);
805 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
807 _cleanup_free_
char *client_id_hex
;
809 client_id_hex
= hexmem(client_id
, client_id_len
);
810 if (!client_id_hex
) {
814 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
817 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
819 _cleanup_free_
char *option_hex
= NULL
;
821 option_hex
= hexmem(data
, data_len
);
826 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
829 LIST_FOREACH(options
, option
, lease
->private_options
) {
830 char key
[strlen("OPTION_000")+1];
832 snprintf(key
, sizeof(key
), "OPTION_%"PRIu8
, option
->tag
);
833 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
838 r
= fflush_and_check(f
);
842 if (rename(temp_path
, lease_file
) < 0) {
851 (void) unlink(temp_path
);
853 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
856 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
858 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
863 *server_address
= NULL
,
870 *client_id_hex
= NULL
,
871 *vendor_specific_hex
= NULL
,
875 *options
[DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
882 r
= dhcp_lease_new(&lease
);
886 r
= parse_env_file(lease_file
, NEWLINE
,
890 "SERVER_IDENTIFIER", &server_address
,
891 "NEXT_SERVER", &next_server
,
892 "BROADCAST", &broadcast
,
896 "DOMAINNAME", &lease
->domainname
,
897 "HOSTNAME", &lease
->hostname
,
898 "ROOT_PATH", &lease
->root_path
,
900 "CLIENTID", &client_id_hex
,
901 "TIMEZONE", &lease
->timezone
,
902 "VENDOR_SPECIFIC", &vendor_specific_hex
,
903 "LIFETIME", &lifetime
,
906 "OPTION_224", &options
[0],
907 "OPTION_225", &options
[1],
908 "OPTION_226", &options
[2],
909 "OPTION_227", &options
[3],
910 "OPTION_228", &options
[4],
911 "OPTION_229", &options
[5],
912 "OPTION_230", &options
[6],
913 "OPTION_231", &options
[7],
914 "OPTION_232", &options
[8],
915 "OPTION_233", &options
[9],
916 "OPTION_234", &options
[10],
917 "OPTION_235", &options
[11],
918 "OPTION_236", &options
[12],
919 "OPTION_237", &options
[13],
920 "OPTION_238", &options
[14],
921 "OPTION_239", &options
[15],
922 "OPTION_240", &options
[16],
923 "OPTION_241", &options
[17],
924 "OPTION_242", &options
[18],
925 "OPTION_243", &options
[19],
926 "OPTION_244", &options
[20],
927 "OPTION_245", &options
[21],
928 "OPTION_246", &options
[22],
929 "OPTION_247", &options
[23],
930 "OPTION_248", &options
[24],
931 "OPTION_249", &options
[25],
932 "OPTION_250", &options
[26],
933 "OPTION_251", &options
[27],
934 "OPTION_252", &options
[28],
935 "OPTION_253", &options
[29],
936 "OPTION_254", &options
[30],
942 r
= inet_pton(AF_INET
, address
, &lease
->address
);
944 log_debug_errno(errno
, "Failed to parse address %s, ignoring: %m", address
);
948 r
= inet_pton(AF_INET
, router
, &lease
->router
);
950 log_debug_errno(errno
, "Failed to parse router %s, ignoring: %m", router
);
954 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
956 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", netmask
);
958 lease
->have_subnet_mask
= true;
961 if (server_address
) {
962 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
964 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", server_address
);
968 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
970 log_debug_errno(errno
, "Failed to parse next server %s, ignoring: %m", next_server
);
974 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
976 log_debug_errno(errno
, "Failed to parse broadcast address %s, ignoring: %m", broadcast
);
978 lease
->have_broadcast
= true;
982 r
= deserialize_in_addrs(&lease
->dns
, dns
);
984 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
990 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
992 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
998 r
= safe_atou16(mtu
, &lease
->mtu
);
1000 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1004 r
= deserialize_dhcp_routes(
1005 &lease
->static_route
,
1006 &lease
->static_route_size
,
1007 &lease
->static_route_allocated
,
1010 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1014 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1016 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1020 r
= safe_atou32(t1
, &lease
->t1
);
1022 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1026 r
= safe_atou32(t2
, &lease
->t2
);
1028 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1031 if (client_id_hex
) {
1032 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1034 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1037 if (vendor_specific_hex
) {
1038 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1040 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1043 for (i
= 0; i
<= DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
; i
++) {
1044 _cleanup_free_
void *data
= NULL
;
1050 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1052 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1056 r
= dhcp_lease_insert_private_option(lease
, DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1067 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1068 struct in_addr address
, mask
;
1073 if (lease
->address
== 0)
1076 address
.s_addr
= lease
->address
;
1078 /* fall back to the default subnet masks based on address class */
1079 r
= in_addr_default_subnet_mask(&address
, &mask
);
1083 lease
->subnet_mask
= mask
.s_addr
;
1084 lease
->have_subnet_mask
= true;
1089 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1090 assert_return(lease
, -EINVAL
);
1091 assert_return(client_id
, -EINVAL
);
1092 assert_return(client_id_len
, -EINVAL
);
1094 if (!lease
->client_id
)
1097 *client_id
= lease
->client_id
;
1098 *client_id_len
= lease
->client_id_len
;
1103 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1104 assert_return(lease
, -EINVAL
);
1105 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1107 if (client_id_len
<= 0)
1108 lease
->client_id
= mfree(lease
->client_id
);
1112 p
= memdup(client_id
, client_id_len
);
1116 free(lease
->client_id
);
1117 lease
->client_id
= p
;
1118 lease
->client_id_len
= client_id_len
;
1124 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **timezone
) {
1125 assert_return(lease
, -EINVAL
);
1126 assert_return(timezone
, -EINVAL
);
1128 if (!lease
->timezone
)
1131 *timezone
= lease
->timezone
;