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_search_domains(sd_dhcp_lease
*lease
, char ***domains
) {
237 assert_return(lease
, -EINVAL
);
238 assert_return(domains
, -EINVAL
);
240 r
= strv_length(lease
->search_domains
);
242 *domains
= lease
->search_domains
;
249 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease
*lease
, const void **data
, size_t *data_len
) {
250 assert_return(lease
, -EINVAL
);
251 assert_return(data
, -EINVAL
);
252 assert_return(data_len
, -EINVAL
);
254 if (lease
->vendor_specific_len
<= 0)
257 *data
= lease
->vendor_specific
;
258 *data_len
= lease
->vendor_specific_len
;
262 sd_dhcp_lease
*sd_dhcp_lease_ref(sd_dhcp_lease
*lease
) {
267 assert(lease
->n_ref
>= 1);
273 sd_dhcp_lease
*sd_dhcp_lease_unref(sd_dhcp_lease
*lease
) {
278 assert(lease
->n_ref
>= 1);
281 if (lease
->n_ref
> 0)
284 while (lease
->private_options
) {
285 struct sd_dhcp_raw_option
*option
= lease
->private_options
;
287 LIST_REMOVE(options
, lease
->private_options
, option
);
293 free(lease
->hostname
);
294 free(lease
->domainname
);
297 free(lease
->static_route
);
298 free(lease
->client_id
);
299 free(lease
->vendor_specific
);
300 strv_free(lease
->search_domains
);
304 static int lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
311 *ret
= unaligned_read_be32((be32_t
*) option
);
318 static int lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
325 *ret
= unaligned_read_be16((be16_t
*) option
);
332 static int lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
339 memcpy(ret
, option
, 4);
343 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
353 * One trailing NUL byte is OK, we don't mind. See:
354 * https://github.com/systemd/systemd/issues/1337
356 if (memchr(option
, 0, len
- 1))
359 string
= strndup((const char *) option
, len
);
370 static int lease_parse_domain(const uint8_t *option
, size_t len
, char **ret
) {
371 _cleanup_free_
char *name
= NULL
, *normalized
= NULL
;
377 r
= lease_parse_string(option
, len
, &name
);
385 r
= dns_name_normalize(name
, &normalized
);
389 if (is_localhost(normalized
))
392 if (dns_name_is_root(normalized
))
402 static void filter_bogus_addresses(struct in_addr
*addresses
, size_t *n
) {
405 /* Silently filter DNS/NTP servers supplied to us that do not make outside of the local scope. */
407 for (i
= 0, j
= 0; i
< *n
; i
++) {
409 if (in4_addr_is_null(addresses
+i
) ||
410 in4_addr_is_localhost(addresses
+i
))
413 addresses
[j
++] = addresses
[i
];
419 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *n_ret
) {
429 struct in_addr
*addresses
;
434 n_addresses
= len
/ 4;
436 addresses
= newdup(struct in_addr
, option
, n_addresses
);
440 filter_bogus_addresses(addresses
, &n_addresses
);
444 *n_ret
= n_addresses
;
450 static int lease_parse_routes(
451 const uint8_t *option
, size_t len
,
452 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
456 assert(option
|| len
<= 0);
459 assert(routes_allocated
);
467 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
471 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
474 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
476 log_debug("Failed to determine destination prefix length from class based IP, ignoring");
480 assert_se(lease_parse_be32(option
, 4, &addr
.s_addr
) >= 0);
481 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
484 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
494 /* parses RFC3442 Classless Static Route Option */
495 static int lease_parse_classless_routes(
496 const uint8_t *option
, size_t len
,
497 struct sd_dhcp_route
**routes
, size_t *routes_size
, size_t *routes_allocated
) {
499 assert(option
|| len
<= 0);
502 assert(routes_allocated
);
507 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
511 struct sd_dhcp_route
*route
;
513 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
516 route
= *routes
+ *routes_size
;
518 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
519 route
->dst_prefixlen
= *option
;
523 /* can't have more than 4 octets in IPv4 */
524 if (dst_octets
> 4 || len
< dst_octets
)
527 route
->dst_addr
.s_addr
= 0;
528 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
529 option
+= dst_octets
;
535 assert_se(lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
) >= 0);
545 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
546 sd_dhcp_lease
*lease
= userdata
;
553 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
554 r
= lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
556 log_debug_errno(r
, "Failed to parse lease time, ignoring: %m");
560 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
561 r
= lease_parse_be32(option
, len
, &lease
->server_address
);
563 log_debug_errno(r
, "Failed to parse server identifier, ignoring: %m");
567 case SD_DHCP_OPTION_SUBNET_MASK
:
568 r
= lease_parse_be32(option
, len
, &lease
->subnet_mask
);
570 log_debug_errno(r
, "Failed to parse subnet mask, ignoring: %m");
572 lease
->have_subnet_mask
= true;
575 case SD_DHCP_OPTION_BROADCAST
:
576 r
= lease_parse_be32(option
, len
, &lease
->broadcast
);
578 log_debug_errno(r
, "Failed to parse broadcast address, ignoring: %m");
580 lease
->have_broadcast
= true;
583 case SD_DHCP_OPTION_ROUTER
:
585 r
= lease_parse_be32(option
, 4, &lease
->router
);
587 log_debug_errno(r
, "Failed to parse router address, ignoring: %m");
591 case SD_DHCP_OPTION_DOMAIN_NAME_SERVER
:
592 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
594 log_debug_errno(r
, "Failed to parse DNS server, ignoring: %m");
597 case SD_DHCP_OPTION_NTP_SERVER
:
598 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
600 log_debug_errno(r
, "Failed to parse NTP server, ignoring: %m");
603 case SD_DHCP_OPTION_STATIC_ROUTE
:
604 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
, &lease
->static_route_allocated
);
606 log_debug_errno(r
, "Failed to parse static routes, ignoring: %m");
609 case SD_DHCP_OPTION_INTERFACE_MTU
:
610 r
= lease_parse_u16(option
, len
, &lease
->mtu
, 68);
612 log_debug_errno(r
, "Failed to parse MTU, ignoring: %m");
613 if (lease
->mtu
< DHCP_DEFAULT_MIN_SIZE
) {
614 log_debug("MTU value of %" PRIu16
" too small. Using default MTU value of %d instead.", lease
->mtu
, DHCP_DEFAULT_MIN_SIZE
);
615 lease
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
620 case SD_DHCP_OPTION_DOMAIN_NAME
:
621 r
= lease_parse_domain(option
, len
, &lease
->domainname
);
623 log_debug_errno(r
, "Failed to parse domain name, ignoring: %m");
629 case SD_DHCP_OPTION_DOMAIN_SEARCH_LIST
:
630 r
= dhcp_lease_parse_search_domains(option
, len
, &lease
->search_domains
);
632 log_debug_errno(r
, "Failed to parse Domain Search List, ignoring: %m");
635 case SD_DHCP_OPTION_HOST_NAME
:
636 r
= lease_parse_domain(option
, len
, &lease
->hostname
);
638 log_debug_errno(r
, "Failed to parse host name, ignoring: %m");
644 case SD_DHCP_OPTION_ROOT_PATH
:
645 r
= lease_parse_string(option
, len
, &lease
->root_path
);
647 log_debug_errno(r
, "Failed to parse root path, ignoring: %m");
650 case SD_DHCP_OPTION_RENEWAL_T1_TIME
:
651 r
= lease_parse_u32(option
, len
, &lease
->t1
, 1);
653 log_debug_errno(r
, "Failed to parse T1 time, ignoring: %m");
656 case SD_DHCP_OPTION_REBINDING_T2_TIME
:
657 r
= lease_parse_u32(option
, len
, &lease
->t2
, 1);
659 log_debug_errno(r
, "Failed to parse T2 time, ignoring: %m");
662 case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
663 r
= lease_parse_classless_routes(
665 &lease
->static_route
,
666 &lease
->static_route_size
,
667 &lease
->static_route_allocated
);
669 log_debug_errno(r
, "Failed to parse classless routes, ignoring: %m");
672 case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
: {
673 _cleanup_free_
char *tz
= NULL
;
675 r
= lease_parse_string(option
, len
, &tz
);
677 log_debug_errno(r
, "Failed to parse timezone option, ignoring: %m");
681 if (!timezone_is_valid(tz
)) {
682 log_debug_errno(r
, "Timezone is not valid, ignoring: %m");
686 free(lease
->timezone
);
687 lease
->timezone
= tz
;
693 case SD_DHCP_OPTION_VENDOR_SPECIFIC
:
696 lease
->vendor_specific
= mfree(lease
->vendor_specific
);
700 p
= memdup(option
, len
);
704 free(lease
->vendor_specific
);
705 lease
->vendor_specific
= p
;
708 lease
->vendor_specific_len
= len
;
711 case SD_DHCP_OPTION_PRIVATE_BASE
... SD_DHCP_OPTION_PRIVATE_LAST
:
712 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
719 log_debug("Ignoring option DHCP option %"PRIu8
" while parsing.", code
);
726 /* Parses compressed domain names. */
727 int dhcp_lease_parse_search_domains(const uint8_t *option
, size_t len
, char ***domains
) {
728 _cleanup_strv_free_
char **names
= NULL
;
729 size_t pos
= 0, cnt
= 0;
733 assert_return(option
&& len
> 0, -ENODATA
);
736 _cleanup_free_
char *name
= NULL
;
737 size_t n
= 0, allocated
= 0;
738 size_t jump_barrier
= pos
, next_chunk
= 0;
748 } else if (c
<= 63) {
752 label
= (const char*) (option
+ pos
);
757 if (!GREEDY_REALLOC(name
, allocated
, n
+ !first
+ DNS_LABEL_ESCAPED_MAX
))
765 r
= dns_label_escape(label
, c
, name
+ n
, DNS_LABEL_ESCAPED_MAX
);
770 } else if ((c
& 0xc0) == 0xc0) {
780 ptr
= (uint16_t) (c
& ~0xc0) << 8 | (uint16_t) d
;
782 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
783 if (ptr
>= jump_barrier
)
787 /* Save current location so we don't end up re-parsing what's parsed so far. */
796 if (!GREEDY_REALLOC(name
, allocated
, n
+ 1))
800 r
= strv_extend(&names
, name
);
816 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
, const void *data
, uint8_t len
) {
817 struct sd_dhcp_raw_option
*cur
, *option
;
821 LIST_FOREACH(options
, cur
, lease
->private_options
) {
824 if (tag
== cur
->tag
) {
825 log_debug("Ignoring duplicate option, tagged %i.", tag
);
830 option
= new(struct sd_dhcp_raw_option
, 1);
835 option
->length
= len
;
836 option
->data
= memdup(data
, len
);
842 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
846 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
847 sd_dhcp_lease
*lease
;
849 lease
= new0(sd_dhcp_lease
, 1);
853 lease
->router
= INADDR_ANY
;
860 int dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
861 _cleanup_free_
char *temp_path
= NULL
;
862 _cleanup_fclose_
FILE *f
= NULL
;
863 struct sd_dhcp_raw_option
*option
;
864 struct in_addr address
;
865 const struct in_addr
*addresses
;
866 const void *client_id
, *data
;
867 size_t client_id_len
, data_len
;
870 _cleanup_free_ sd_dhcp_route
**routes
= NULL
;
871 char **search_domains
= NULL
;
872 uint32_t t1
, t2
, lifetime
;
878 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
882 fchmod(fileno(f
), 0644);
885 "# This is private data. Do not parse.\n");
887 r
= sd_dhcp_lease_get_address(lease
, &address
);
889 fprintf(f
, "ADDRESS=%s\n", inet_ntoa(address
));
891 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
893 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
895 r
= sd_dhcp_lease_get_router(lease
, &address
);
897 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
899 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
901 fprintf(f
, "SERVER_ADDRESS=%s\n", inet_ntoa(address
));
903 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
905 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
907 r
= sd_dhcp_lease_get_broadcast(lease
, &address
);
909 fprintf(f
, "BROADCAST=%s\n", inet_ntoa(address
));
911 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
913 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
915 r
= sd_dhcp_lease_get_t1(lease
, &t1
);
917 fprintf(f
, "T1=%" PRIu32
"\n", t1
);
919 r
= sd_dhcp_lease_get_t2(lease
, &t2
);
921 fprintf(f
, "T2=%" PRIu32
"\n", t2
);
923 r
= sd_dhcp_lease_get_lifetime(lease
, &lifetime
);
925 fprintf(f
, "LIFETIME=%" PRIu32
"\n", lifetime
);
927 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
929 fputs_unlocked("DNS=", f
);
930 serialize_in_addrs(f
, addresses
, r
);
931 fputs_unlocked("\n", f
);
934 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
936 fputs_unlocked("NTP=", f
);
937 serialize_in_addrs(f
, addresses
, r
);
938 fputs_unlocked("\n", f
);
941 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
943 fprintf(f
, "DOMAINNAME=%s\n", string
);
945 r
= sd_dhcp_lease_get_search_domains(lease
, &search_domains
);
947 fputs_unlocked("DOMAIN_SEARCH_LIST=", f
);
948 fputstrv(f
, search_domains
, NULL
, NULL
);
949 fputs_unlocked("\n", f
);
952 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
954 fprintf(f
, "HOSTNAME=%s\n", string
);
956 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
958 fprintf(f
, "ROOT_PATH=%s\n", string
);
960 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
962 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
964 r
= sd_dhcp_lease_get_timezone(lease
, &string
);
966 fprintf(f
, "TIMEZONE=%s\n", string
);
968 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
970 _cleanup_free_
char *client_id_hex
= NULL
;
972 client_id_hex
= hexmem(client_id
, client_id_len
);
973 if (!client_id_hex
) {
977 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
980 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
982 _cleanup_free_
char *option_hex
= NULL
;
984 option_hex
= hexmem(data
, data_len
);
989 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
992 LIST_FOREACH(options
, option
, lease
->private_options
) {
993 char key
[strlen("OPTION_000")+1];
995 xsprintf(key
, "OPTION_%" PRIu8
, option
->tag
);
996 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
1001 r
= fflush_and_check(f
);
1005 if (rename(temp_path
, lease_file
) < 0) {
1014 (void) unlink(temp_path
);
1016 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
1019 int dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
1021 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1026 *server_address
= NULL
,
1027 *next_server
= NULL
,
1034 *client_id_hex
= NULL
,
1035 *vendor_specific_hex
= NULL
,
1039 *options
[SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
+ 1] = {};
1046 r
= dhcp_lease_new(&lease
);
1050 r
= parse_env_file(lease_file
, NEWLINE
,
1051 "ADDRESS", &address
,
1053 "NETMASK", &netmask
,
1054 "SERVER_IDENTIFIER", &server_address
,
1055 "NEXT_SERVER", &next_server
,
1056 "BROADCAST", &broadcast
,
1060 "DOMAINNAME", &lease
->domainname
,
1061 "HOSTNAME", &lease
->hostname
,
1062 "DOMAIN_SEARCH_LIST", &domains
,
1063 "ROOT_PATH", &lease
->root_path
,
1065 "CLIENTID", &client_id_hex
,
1066 "TIMEZONE", &lease
->timezone
,
1067 "VENDOR_SPECIFIC", &vendor_specific_hex
,
1068 "LIFETIME", &lifetime
,
1071 "OPTION_224", &options
[0],
1072 "OPTION_225", &options
[1],
1073 "OPTION_226", &options
[2],
1074 "OPTION_227", &options
[3],
1075 "OPTION_228", &options
[4],
1076 "OPTION_229", &options
[5],
1077 "OPTION_230", &options
[6],
1078 "OPTION_231", &options
[7],
1079 "OPTION_232", &options
[8],
1080 "OPTION_233", &options
[9],
1081 "OPTION_234", &options
[10],
1082 "OPTION_235", &options
[11],
1083 "OPTION_236", &options
[12],
1084 "OPTION_237", &options
[13],
1085 "OPTION_238", &options
[14],
1086 "OPTION_239", &options
[15],
1087 "OPTION_240", &options
[16],
1088 "OPTION_241", &options
[17],
1089 "OPTION_242", &options
[18],
1090 "OPTION_243", &options
[19],
1091 "OPTION_244", &options
[20],
1092 "OPTION_245", &options
[21],
1093 "OPTION_246", &options
[22],
1094 "OPTION_247", &options
[23],
1095 "OPTION_248", &options
[24],
1096 "OPTION_249", &options
[25],
1097 "OPTION_250", &options
[26],
1098 "OPTION_251", &options
[27],
1099 "OPTION_252", &options
[28],
1100 "OPTION_253", &options
[29],
1101 "OPTION_254", &options
[30],
1107 r
= inet_pton(AF_INET
, address
, &lease
->address
);
1109 log_debug("Failed to parse address %s, ignoring.", address
);
1113 r
= inet_pton(AF_INET
, router
, &lease
->router
);
1115 log_debug("Failed to parse router %s, ignoring.", router
);
1119 r
= inet_pton(AF_INET
, netmask
, &lease
->subnet_mask
);
1121 log_debug("Failed to parse netmask %s, ignoring.", netmask
);
1123 lease
->have_subnet_mask
= true;
1126 if (server_address
) {
1127 r
= inet_pton(AF_INET
, server_address
, &lease
->server_address
);
1129 log_debug("Failed to parse server address %s, ignoring.", server_address
);
1133 r
= inet_pton(AF_INET
, next_server
, &lease
->next_server
);
1135 log_debug("Failed to parse next server %s, ignoring.", next_server
);
1139 r
= inet_pton(AF_INET
, broadcast
, &lease
->broadcast
);
1141 log_debug("Failed to parse broadcast address %s, ignoring.", broadcast
);
1143 lease
->have_broadcast
= true;
1147 r
= deserialize_in_addrs(&lease
->dns
, dns
);
1149 log_debug_errno(r
, "Failed to deserialize DNS servers %s, ignoring: %m", dns
);
1151 lease
->dns_size
= r
;
1155 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
1157 log_debug_errno(r
, "Failed to deserialize NTP servers %s, ignoring: %m", ntp
);
1159 lease
->ntp_size
= r
;
1163 r
= safe_atou16(mtu
, &lease
->mtu
);
1165 log_debug_errno(r
, "Failed to parse MTU %s, ignoring: %m", mtu
);
1169 _cleanup_strv_free_
char **a
= NULL
;
1170 a
= strv_split(domains
, " ");
1174 if (!strv_isempty(a
)) {
1175 lease
->search_domains
= a
;
1181 r
= deserialize_dhcp_routes(
1182 &lease
->static_route
,
1183 &lease
->static_route_size
,
1184 &lease
->static_route_allocated
,
1187 log_debug_errno(r
, "Failed to parse DHCP routes %s, ignoring: %m", routes
);
1191 r
= safe_atou32(lifetime
, &lease
->lifetime
);
1193 log_debug_errno(r
, "Failed to parse lifetime %s, ignoring: %m", lifetime
);
1197 r
= safe_atou32(t1
, &lease
->t1
);
1199 log_debug_errno(r
, "Failed to parse T1 %s, ignoring: %m", t1
);
1203 r
= safe_atou32(t2
, &lease
->t2
);
1205 log_debug_errno(r
, "Failed to parse T2 %s, ignoring: %m", t2
);
1208 if (client_id_hex
) {
1209 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
1211 log_debug_errno(r
, "Failed to parse client ID %s, ignoring: %m", client_id_hex
);
1214 if (vendor_specific_hex
) {
1215 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
1217 log_debug_errno(r
, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex
);
1220 for (i
= 0; i
<= SD_DHCP_OPTION_PRIVATE_LAST
- SD_DHCP_OPTION_PRIVATE_BASE
; i
++) {
1221 _cleanup_free_
void *data
= NULL
;
1227 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
1229 log_debug_errno(r
, "Failed to parse private DHCP option %s, ignoring: %m", options
[i
]);
1233 r
= dhcp_lease_insert_private_option(lease
, SD_DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
1244 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
1245 struct in_addr address
, mask
;
1250 if (lease
->address
== 0)
1253 address
.s_addr
= lease
->address
;
1255 /* fall back to the default subnet masks based on address class */
1256 r
= in_addr_default_subnet_mask(&address
, &mask
);
1260 lease
->subnet_mask
= mask
.s_addr
;
1261 lease
->have_subnet_mask
= true;
1266 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const void **client_id
, size_t *client_id_len
) {
1267 assert_return(lease
, -EINVAL
);
1268 assert_return(client_id
, -EINVAL
);
1269 assert_return(client_id_len
, -EINVAL
);
1271 if (!lease
->client_id
)
1274 *client_id
= lease
->client_id
;
1275 *client_id_len
= lease
->client_id_len
;
1280 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const void *client_id
, size_t client_id_len
) {
1281 assert_return(lease
, -EINVAL
);
1282 assert_return(client_id
|| client_id_len
<= 0, -EINVAL
);
1284 if (client_id_len
<= 0)
1285 lease
->client_id
= mfree(lease
->client_id
);
1289 p
= memdup(client_id
, client_id_len
);
1293 free(lease
->client_id
);
1294 lease
->client_id
= p
;
1295 lease
->client_id_len
= client_id_len
;
1301 int sd_dhcp_lease_get_timezone(sd_dhcp_lease
*lease
, const char **tz
) {
1302 assert_return(lease
, -EINVAL
);
1303 assert_return(tz
, -EINVAL
);
1305 if (!lease
->timezone
)
1308 *tz
= lease
->timezone
;
1312 int sd_dhcp_route_get_destination(sd_dhcp_route
*route
, struct in_addr
*destination
) {
1313 assert_return(route
, -EINVAL
);
1314 assert_return(destination
, -EINVAL
);
1316 *destination
= route
->dst_addr
;
1320 int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route
*route
, uint8_t *length
) {
1321 assert_return(route
, -EINVAL
);
1322 assert_return(length
, -EINVAL
);
1324 *length
= route
->dst_prefixlen
;
1328 int sd_dhcp_route_get_gateway(sd_dhcp_route
*route
, struct in_addr
*gateway
) {
1329 assert_return(route
, -EINVAL
);
1330 assert_return(gateway
, -EINVAL
);
1332 *gateway
= route
->gw_addr
;