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
) {
318 * One trailing NUL byte is OK, we don't mind. See:
319 * https://github.com/systemd/systemd/issues/1337
321 if (memchr(option
, 0, len
- 1))
324 string
= strndup((const char *) option
, len
);
335 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
345 struct in_addr
*addresses
;
350 n_addresses
= len
/ 4;
352 addresses
= newdup(struct in_addr
, option
, n_addresses
);
358 *n_ret
= n_addresses
;
364 static int lease_parse_routes(
365 const uint8_t *option
, size_t len
,
366 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
370 assert(option
|| len
<= 0);
373 assert(routes_allocated
);
381 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
385 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
388 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
390 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
394 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
395 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
398 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
408 /* parses RFC3442 Classless Static Route Option */
409 static int lease_parse_classless_routes(
410 const uint8_t *option
, size_t len
,
411 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
413 assert(option
|| len
<= 0);
416 assert(routes_allocated
);
421 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
425 struct sd_dhcp_route
*route
;
427 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
430 route
= *routes
+ *routes_size
;
432 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
433 route
->dst_prefixlen
= *option
;
437 /* can't have more than 4 octets in IPv4 */
438 if (dst_octets
> 4 || len
< dst_octets
)
441 route
->dst_addr
.s_addr
= 0;
442 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
443 option
+= dst_octets
;
449 lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
);
459 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
460 sd_dhcp_lease
*lease
= userdata
;
467 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
468 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
470 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
474 case DHCP_OPTION_SERVER_IDENTIFIER
:
475 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
477 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
481 case DHCP_OPTION_SUBNET_MASK
:
482 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
484 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
486 lease
->have_subnet_mask
= true;
489 case DHCP_OPTION_BROADCAST
:
490 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
492 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
494 lease
->have_broadcast
= true;
497 case DHCP_OPTION_ROUTER
:
499 r
= lease_parse_be32(option
, 4, &lease
->router
);
501 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
505 case DHCP_OPTION_DOMAIN_NAME_SERVER
:
506 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
508 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
511 case DHCP_OPTION_NTP_SERVER
:
512 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
514 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
517 case DHCP_OPTION_STATIC_ROUTE
:
518 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
520 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
523 case DHCP_OPTION_INTERFACE_MTU
:
524 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
526 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
529 case DHCP_OPTION_DOMAIN_NAME
: {
530 _cleanup_free_
char *domainname
= NULL
, *normalized
= NULL
;
532 r
= lease_parse_string(option
, len
, &domainname
);
534 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
538 r
= dns_name_normalize(domainname
, &normalized
);
540 log_debug_errno(r
, "Failed to normalize domain name '%s': %m", domainname
);
544 if (is_localhost(normalized
)) {
545 log_debug_errno(r
, "Detected 'localhost' as suggested domain name, ignoring.");
549 free(lease
->domainname
);
550 lease
->domainname
= normalized
;
556 case DHCP_OPTION_HOST_NAME
: {
557 _cleanup_free_
char *hostname
= NULL
, *normalized
= NULL
;
559 r
= lease_parse_string(option
, len
, &hostname
);
561 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
565 r
= dns_name_normalize(hostname
, &normalized
);
567 log_debug_errno(r
, "Failed to normalize host name '%s', ignoring: %m", hostname
);
571 if (is_localhost(normalized
)) {
572 log_debug_errno(r
, "Detected 'localhost' as suggested host name, ignoring.");
576 free(lease
->hostname
);
577 lease
->hostname
= normalized
;
583 case DHCP_OPTION_ROOT_PATH
:
584 r
= lease_parse_string(option
, len
, &lease
->root_path
);
586 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
589 case DHCP_OPTION_RENEWAL_T1_TIME
:
590 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
592 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
595 case DHCP_OPTION_REBINDING_T2_TIME
:
596 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
598 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
601 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
602 r
= lease_parse_classless_routes(
604 &lease
->static_route
,
605 &lease
->static_route_size
,
606 &lease
->static_route_allocated
);
608 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
611 case DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
612 _cleanup_free_
char *tz
= NULL
;
614 r
= lease_parse_string(option
, len
, &tz
);
616 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
620 if (!timezone_is_valid(tz
)) {
621 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
625 free(lease
->timezone
);
626 lease
->timezone
= tz
;
632 case DHCP_OPTION_VENDOR_SPECIFIC
:
635 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
639 p
= memdup(option
, len
);
643 free(lease
->vendor_specific
);
644 lease
->vendor_specific
= p
;
647 lease
->vendor_specific_len
= len
;
650 case DHCP_OPTION_PRIVATE_BASE
... DHCP_OPTION_PRIVATE_LAST
:
651 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
658 log_debug("Ignoring option DHCP option %i while parsing.", code
);
665 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
666 struct sd_dhcp_raw_option
*cur
, *option
;
670 LIST_FOREACH(options
, cur
, lease
->private_options
) {
673 if (tag
== cur
->tag
) {
674 log_debug("Ignoring duplicate option, tagged %i.", tag
);
679 option
= new(struct sd_dhcp_raw_option
, 1);
684 option
->length
= len
;
685 option
->data
= memdup(data
, len
);
691 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
695 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
696 sd_dhcp_lease
*lease
;
698 lease
= new0(sd_dhcp_lease
, 1);
702 lease
->router
= INADDR_ANY
;
709 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
710 _cleanup_free_
char *temp_path
= NULL
;
711 _cleanup_fclose_
FILE *f
= NULL
;
712 struct sd_dhcp_raw_option
*option
;
713 struct in_addr address
;
714 const struct in_addr
*addresses
;
715 const void *client_id
, *data
;
716 size_t client_id_len
, data_len
;
719 struct sd_dhcp_route
*routes
;
720 uint32_t t1
, t2
, lifetime
;
726 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
730 fchmod(fileno(f
), 0644);
733 "# This is private data. Do not parse.\n");
735 r
= sd_dhcp_lease_get_address(lease
, &address
);
737 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
739 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
741 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
743 r
= sd_dhcp_lease_get_router(lease
, &address
);
745 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
747 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
749 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
751 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
753 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
755 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
757 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
759 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
761 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
763 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
765 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
767 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
769 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
771 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
773 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
775 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
778 serialize_in_addrs(f
, addresses
, r
);
782 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
785 serialize_in_addrs(f
, addresses
, r
);
789 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
791 fprintf(f
, "DOMAINNAME=%s\n", string
);
793 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
795 fprintf(f
, "HOSTNAME=%s\n", string
);
797 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
799 fprintf(f
, "ROOT_PATH=%s\n", string
);
801 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
803 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
805 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
807 fprintf(f
, "TIMEZONE=%s\n", string
);
809 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
811 _cleanup_free_
char *client_id_hex
;
813 client_id_hex
= hexmem(client_id
, client_id_len
);
814 if (!client_id_hex
) {
818 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
821 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
823 _cleanup_free_
char *option_hex
= NULL
;
825 option_hex
= hexmem(data
, data_len
);
830 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
833 LIST_FOREACH(options
, option
, lease
->private_options
) {
834 char key
[strlen("OPTION_000")+1];
836 snprintf(key
, sizeof(key
), "OPTION_%"PRIu8
, option
->tag
);
837 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
842 r
= fflush_and_check(f
);
846 if (rename(temp_path
, lease_file
) < 0) {
855 (void) unlink(temp_path
);
857 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
860 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
862 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
867 *server_address
= NULL
,
874 *client_id_hex
= NULL
,
875 *vendor_specific_hex
= NULL
,
879 *options
[DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
886 r
= dhcp_lease_new(&lease
);
890 r
= parse_env_file(lease_file
, NEWLINE
,
894 "SERVER_IDENTIFIER", &server_address
,
895 "NEXT_SERVER", &next_server
,
896 "BROADCAST", &broadcast
,
900 "DOMAINNAME", &lease
->domainname
,
901 "HOSTNAME", &lease
->hostname
,
902 "ROOT_PATH", &lease
->root_path
,
904 "CLIENTID", &client_id_hex
,
905 "TIMEZONE", &lease
->timezone
,
906 "VENDOR_SPECIFIC", &vendor_specific_hex
,
907 "LIFETIME", &lifetime
,
910 "OPTION_224", &options
[0],
911 "OPTION_225", &options
[1],
912 "OPTION_226", &options
[2],
913 "OPTION_227", &options
[3],
914 "OPTION_228", &options
[4],
915 "OPTION_229", &options
[5],
916 "OPTION_230", &options
[6],
917 "OPTION_231", &options
[7],
918 "OPTION_232", &options
[8],
919 "OPTION_233", &options
[9],
920 "OPTION_234", &options
[10],
921 "OPTION_235", &options
[11],
922 "OPTION_236", &options
[12],
923 "OPTION_237", &options
[13],
924 "OPTION_238", &options
[14],
925 "OPTION_239", &options
[15],
926 "OPTION_240", &options
[16],
927 "OPTION_241", &options
[17],
928 "OPTION_242", &options
[18],
929 "OPTION_243", &options
[19],
930 "OPTION_244", &options
[20],
931 "OPTION_245", &options
[21],
932 "OPTION_246", &options
[22],
933 "OPTION_247", &options
[23],
934 "OPTION_248", &options
[24],
935 "OPTION_249", &options
[25],
936 "OPTION_250", &options
[26],
937 "OPTION_251", &options
[27],
938 "OPTION_252", &options
[28],
939 "OPTION_253", &options
[29],
940 "OPTION_254", &options
[30],
946 r
= inet_pton(AF_INET
, address
, &lease
->address
);
948 log_debug_errno(errno
, "Failed to parse address %s, ignoring: %m", address
);
952 r
= inet_pton(AF_INET
, router
, &lease
->router
);
954 log_debug_errno(errno
, "Failed to parse router %s, ignoring: %m", router
);
958 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
960 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", netmask
);
962 lease
->have_subnet_mask
= true;
965 if (server_address
) {
966 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
968 log_debug_errno(errno
, "Failed to parse netmask %s, ignoring: %m", server_address
);
972 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
974 log_debug_errno(errno
, "Failed to parse next server %s, ignoring: %m", next_server
);
978 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
980 log_debug_errno(errno
, "Failed to parse broadcast address %s, ignoring: %m", broadcast
);
982 lease
->have_broadcast
= true;
986 r
= deserialize_in_addrs(&lease
->dns
, dns
);
988 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
994 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
996 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1002 r
= safe_atou16(mtu
, &lease
->mtu
);
1004 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1008 r
= deserialize_dhcp_routes(
1009 &lease
->static_route
,
1010 &lease
->static_route_size
,
1011 &lease
->static_route_allocated
,
1014 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1018 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1020 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1024 r
= safe_atou32(t1
, &lease
->t1
);
1026 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1030 r
= safe_atou32(t2
, &lease
->t2
);
1032 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1035 if (client_id_hex
) {
1036 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1038 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1041 if (vendor_specific_hex
) {
1042 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1044 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1047 for (i
= 0; i
<= DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
; i
++) {
1048 _cleanup_free_
void *data
= NULL
;
1054 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1056 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1060 r
= dhcp_lease_insert_private_option(lease
, DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1071 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1072 struct in_addr address
, mask
;
1077 if (lease
->address
== 0)
1080 address
.s_addr
= lease
->address
;
1082 /* fall back to the default subnet masks based on address class */
1083 r
= in_addr_default_subnet_mask(&address
, &mask
);
1087 lease
->subnet_mask
= mask
.s_addr
;
1088 lease
->have_subnet_mask
= true;
1093 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1094 assert_return(lease
, -EINVAL
);
1095 assert_return(client_id
, -EINVAL
);
1096 assert_return(client_id_len
, -EINVAL
);
1098 if (!lease
->client_id
)
1101 *client_id
= lease
->client_id
;
1102 *client_id_len
= lease
->client_id_len
;
1107 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1108 assert_return(lease
, -EINVAL
);
1109 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1111 if (client_id_len
<= 0)
1112 lease
->client_id
= mfree(lease
->client_id
);
1116 p
= memdup(client_id
, client_id_len
);
1120 free(lease
->client_id
);
1121 lease
->client_id
= p
;
1122 lease
->client_id_len
= client_id_len
;
1128 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1129 assert_return(lease
, -EINVAL
);
1130 assert_return(tz
, -EINVAL
);
1132 if (!lease
->timezone
)
1135 *tz
= lease
->timezone
;