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 "dhcp-protocol.h"
32 #include "dhcp-lease-internal.h"
33 #include "sd-dhcp-lease.h"
34 #include "network-internal.h"
35 #include "dns-domain.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 addr
->s_addr
= lease
->address
;
46 int sd_dhcp_lease_get_lifetime(sd_dhcp_lease
*lease
, uint32_t *lifetime
) {
47 assert_return(lease
, -EINVAL
);
48 assert_return(lifetime
, -EINVAL
);
50 *lifetime
= lease
->lifetime
;
55 int sd_dhcp_lease_get_mtu(sd_dhcp_lease
*lease
, uint16_t *mtu
) {
56 assert_return(lease
, -EINVAL
);
57 assert_return(mtu
, -EINVAL
);
67 int sd_dhcp_lease_get_dns(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
68 assert_return(lease
, -EINVAL
);
69 assert_return(addr
, -EINVAL
);
71 if (lease
->dns_size
) {
73 return lease
->dns_size
;
80 int sd_dhcp_lease_get_ntp(sd_dhcp_lease
*lease
, const struct in_addr
**addr
) {
81 assert_return(lease
, -EINVAL
);
82 assert_return(addr
, -EINVAL
);
84 if (lease
->ntp_size
) {
86 return lease
->ntp_size
;
93 int sd_dhcp_lease_get_domainname(sd_dhcp_lease
*lease
, const char **domainname
) {
94 assert_return(lease
, -EINVAL
);
95 assert_return(domainname
, -EINVAL
);
97 if (lease
->domainname
)
98 *domainname
= lease
->domainname
;
105 int sd_dhcp_lease_get_hostname(sd_dhcp_lease
*lease
, const char **hostname
) {
106 assert_return(lease
, -EINVAL
);
107 assert_return(hostname
, -EINVAL
);
110 *hostname
= lease
->hostname
;
117 int sd_dhcp_lease_get_root_path(sd_dhcp_lease
*lease
, const char **root_path
) {
118 assert_return(lease
, -EINVAL
);
119 assert_return(root_path
, -EINVAL
);
121 if (lease
->root_path
)
122 *root_path
= lease
->root_path
;
129 int sd_dhcp_lease_get_router(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
130 assert_return(lease
, -EINVAL
);
131 assert_return(addr
, -EINVAL
);
133 if (lease
->router
!= INADDR_ANY
)
134 addr
->s_addr
= lease
->router
;
141 int sd_dhcp_lease_get_netmask(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
142 assert_return(lease
, -EINVAL
);
143 assert_return(addr
, -EINVAL
);
145 addr
->s_addr
= lease
->subnet_mask
;
150 int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
151 assert_return(lease
, -EINVAL
);
152 assert_return(addr
, -EINVAL
);
154 addr
->s_addr
= lease
->server_address
;
159 int sd_dhcp_lease_get_next_server(sd_dhcp_lease
*lease
, struct in_addr
*addr
) {
160 assert_return(lease
, -EINVAL
);
161 assert_return(addr
, -EINVAL
);
163 addr
->s_addr
= lease
->next_server
;
168 int sd_dhcp_lease_get_routes(sd_dhcp_lease
*lease
, struct sd_dhcp_route
**routes
) {
170 assert_return(lease
, -EINVAL
);
171 assert_return(routes
, -EINVAL
);
173 if (lease
->static_route_size
) {
174 *routes
= lease
->static_route
;
175 return lease
->static_route_size
;
182 int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease
*lease
, const uint8_t **data
,
184 assert_return(lease
, -EINVAL
);
185 assert_return(data
, -EINVAL
);
186 assert_return(data_len
, -EINVAL
);
188 if (!lease
->vendor_specific
)
191 *data
= lease
->vendor_specific
;
192 *data_len
= lease
->vendor_specific_len
;
197 sd_dhcp_lease
*sd_dhcp_lease_ref(sd_dhcp_lease
*lease
) {
199 assert_se(REFCNT_INC(lease
->n_ref
) >= 2);
204 sd_dhcp_lease
*sd_dhcp_lease_unref(sd_dhcp_lease
*lease
) {
205 if (lease
&& REFCNT_DEC(lease
->n_ref
) == 0) {
206 while (lease
->private_options
) {
207 struct sd_dhcp_raw_option
*option
= lease
->private_options
;
209 LIST_REMOVE(options
, lease
->private_options
, option
);
214 free(lease
->hostname
);
215 free(lease
->domainname
);
218 free(lease
->static_route
);
219 free(lease
->client_id
);
220 free(lease
->vendor_specific
);
227 static void lease_parse_u32(const uint8_t *option
, size_t len
, uint32_t *ret
, uint32_t min
) {
232 *ret
= unaligned_read_be32((be32_t
*) option
);
239 static void lease_parse_s32(const uint8_t *option
, size_t len
, int32_t *ret
) {
240 lease_parse_u32(option
, len
, (uint32_t *)ret
, 0);
243 static void lease_parse_u16(const uint8_t *option
, size_t len
, uint16_t *ret
, uint16_t min
) {
248 *ret
= unaligned_read_be16((be16_t
*) option
);
255 static void lease_parse_be32(const uint8_t *option
, size_t len
, be32_t
*ret
) {
260 memcpy(ret
, option
, 4);
263 static void lease_parse_bool(const uint8_t *option
, size_t len
, bool *ret
) {
271 static void lease_parse_u8(const uint8_t *option
, size_t len
, uint8_t *ret
, uint8_t min
) {
283 static int lease_parse_string(const uint8_t *option
, size_t len
, char **ret
) {
290 string
= strndup((const char *)option
, len
);
301 static int lease_parse_in_addrs_aux(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *ret_size
, size_t mult
) {
306 if (len
&& !(len
% (4 * mult
))) {
308 struct in_addr
*addresses
;
312 addresses
= newdup(struct in_addr
, option
, size
);
324 static int lease_parse_in_addrs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *ret_size
) {
325 return lease_parse_in_addrs_aux(option
, len
, ret
, ret_size
, 1);
328 static int lease_parse_in_addrs_pairs(const uint8_t *option
, size_t len
, struct in_addr
**ret
, size_t *ret_size
) {
329 return lease_parse_in_addrs_aux(option
, len
, ret
, ret_size
, 2);
332 static int lease_parse_routes(const uint8_t *option
, size_t len
, struct sd_dhcp_route
**routes
,
333 size_t *routes_size
, size_t *routes_allocated
) {
340 assert(routes_allocated
);
348 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ (len
/ 8)))
352 struct sd_dhcp_route
*route
= *routes
+ *routes_size
;
355 r
= in_addr_default_prefixlen((struct in_addr
*) option
, &route
->dst_prefixlen
);
357 log_error("Failed to determine destination prefix length from class based IP, ignoring");
361 lease_parse_be32(option
, 4, &addr
.s_addr
);
362 route
->dst_addr
= inet_makeaddr(inet_netof(addr
), 0);
365 lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
);
375 /* parses RFC3442 Classless Static Route Option */
376 static int lease_parse_classless_routes(const uint8_t *option
, size_t len
, struct sd_dhcp_route
**routes
,
377 size_t *routes_size
, size_t *routes_allocated
) {
382 assert(routes_allocated
);
384 /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
388 struct sd_dhcp_route
*route
;
390 if (!GREEDY_REALLOC(*routes
, *routes_allocated
, *routes_size
+ 1))
393 route
= *routes
+ *routes_size
;
395 dst_octets
= (*option
== 0 ? 0 : ((*option
- 1) / 8) + 1);
396 route
->dst_prefixlen
= *option
;
400 /* can't have more than 4 octets in IPv4 */
401 if (dst_octets
> 4 || len
< dst_octets
)
404 route
->dst_addr
.s_addr
= 0;
405 memcpy(&route
->dst_addr
.s_addr
, option
, dst_octets
);
406 option
+= dst_octets
;
412 lease_parse_be32(option
, 4, &route
->gw_addr
.s_addr
);
422 int dhcp_lease_parse_options(uint8_t code
, uint8_t len
, const uint8_t *option
,
424 sd_dhcp_lease
*lease
= user_data
;
431 case DHCP_OPTION_TIME_OFFSET
:
432 lease_parse_s32(option
, len
, &lease
->time_offset
);
436 case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT
:
437 lease_parse_u32(option
, len
, &lease
->mtu_aging_timeout
, 0);
441 case DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
442 lease_parse_u32(option
, len
, &lease
->lifetime
, 1);
446 case DHCP_OPTION_SERVER_IDENTIFIER
:
447 lease_parse_be32(option
, len
, &lease
->server_address
);
451 case DHCP_OPTION_SUBNET_MASK
:
452 lease_parse_be32(option
, len
, &lease
->subnet_mask
);
456 case DHCP_OPTION_BROADCAST
:
457 lease_parse_be32(option
, len
, &lease
->broadcast
);
461 case DHCP_OPTION_ROUTER
:
463 lease_parse_be32(option
, 4, &lease
->router
);
467 case DHCP_OPTION_DOMAIN_NAME_SERVER
:
468 r
= lease_parse_in_addrs(option
, len
, &lease
->dns
, &lease
->dns_size
);
474 case DHCP_OPTION_NTP_SERVER
:
475 r
= lease_parse_in_addrs(option
, len
, &lease
->ntp
, &lease
->ntp_size
);
481 case DHCP_OPTION_POLICY_FILTER
:
482 r
= lease_parse_in_addrs_pairs(option
, len
, &lease
->policy_filter
, &lease
->policy_filter_size
);
488 case DHCP_OPTION_STATIC_ROUTE
:
489 r
= lease_parse_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
,
490 &lease
->static_route_allocated
);
496 case DHCP_OPTION_INTERFACE_MTU
:
497 lease_parse_u16(option
, len
, &lease
->mtu
, 68);
501 case DHCP_OPTION_INTERFACE_MDR
:
502 lease_parse_u16(option
, len
, &lease
->mdr
, 576);
506 case DHCP_OPTION_INTERFACE_TTL
:
507 lease_parse_u8(option
, len
, &lease
->ttl
, 1);
511 case DHCP_OPTION_BOOT_FILE_SIZE
:
512 lease_parse_u16(option
, len
, &lease
->boot_file_size
, 0);
516 case DHCP_OPTION_DOMAIN_NAME
:
518 _cleanup_free_
char *domainname
= NULL
;
521 r
= lease_parse_string(option
, len
, &domainname
);
525 /* Chop off trailing dot of domain name that some DHCP
526 * servers send us back. Internally we want to store
527 * host names without trailing dots and
528 * host_name_is_valid() doesn't accept them. */
529 e
= endswith(domainname
, ".");
533 if (is_localhost(domainname
))
536 r
= dns_name_is_valid(domainname
);
539 log_error_errno(r
, "Failed to validate domain name: %s: %m", domainname
);
541 log_warning("Domain name is not valid, ignoring: %s", domainname
);
545 free(lease
->domainname
);
546 lease
->domainname
= domainname
;
551 case DHCP_OPTION_HOST_NAME
:
553 _cleanup_free_
char *hostname
= NULL
;
556 r
= lease_parse_string(option
, len
, &hostname
);
560 e
= endswith(hostname
, ".");
564 if (!hostname_is_valid(hostname
, false) || is_localhost(hostname
))
567 free_and_replace(&lease
->hostname
, hostname
);
572 case DHCP_OPTION_ROOT_PATH
:
573 r
= lease_parse_string(option
, len
, &lease
->root_path
);
579 case DHCP_OPTION_RENEWAL_T1_TIME
:
580 lease_parse_u32(option
, len
, &lease
->t1
, 1);
584 case DHCP_OPTION_REBINDING_T2_TIME
:
585 lease_parse_u32(option
, len
, &lease
->t2
, 1);
589 case DHCP_OPTION_ENABLE_IP_FORWARDING
:
590 lease_parse_bool(option
, len
, &lease
->ip_forward
);
594 case DHCP_OPTION_ENABLE_IP_FORWARDING_NL
:
595 lease_parse_bool(option
, len
, &lease
->ip_forward_non_local
);
599 case DHCP_OPTION_CLASSLESS_STATIC_ROUTE
:
600 r
= lease_parse_classless_routes(option
, len
, &lease
->static_route
, &lease
->static_route_size
,
601 &lease
->static_route_allocated
);
607 case DHCP_OPTION_VENDOR_SPECIFIC
:
609 free(lease
->vendor_specific
);
610 lease
->vendor_specific
= memdup(option
, len
);
611 if (!lease
->vendor_specific
)
613 lease
->vendor_specific_len
= len
;
619 if (code
< DHCP_OPTION_PRIVATE_BASE
|| code
> DHCP_OPTION_PRIVATE_LAST
)
622 r
= dhcp_lease_insert_private_option(lease
, code
, option
, len
);
630 int dhcp_lease_insert_private_option(sd_dhcp_lease
*lease
, uint8_t tag
,
631 const uint8_t *data
, uint8_t len
) {
632 struct sd_dhcp_raw_option
*cur
, *option
;
634 LIST_FOREACH(options
, cur
, lease
->private_options
) {
637 else if (tag
== cur
->tag
) {
638 log_error("Ignoring duplicate option, tagged %d.", tag
);
643 option
= new(struct sd_dhcp_raw_option
, 1);
648 option
->length
= len
;
649 option
->data
= memdup(data
, len
);
655 LIST_INSERT_BEFORE(options
, lease
->private_options
, cur
, option
);
660 int dhcp_lease_new(sd_dhcp_lease
**ret
) {
661 sd_dhcp_lease
*lease
;
663 lease
= new0(sd_dhcp_lease
, 1);
667 lease
->router
= INADDR_ANY
;
668 lease
->n_ref
= REFCNT_INIT
;
669 LIST_HEAD_INIT(lease
->private_options
);
675 int sd_dhcp_lease_save(sd_dhcp_lease
*lease
, const char *lease_file
) {
676 _cleanup_free_
char *temp_path
= NULL
;
677 _cleanup_fclose_
FILE *f
= NULL
;
678 struct sd_dhcp_raw_option
*option
;
679 struct in_addr address
;
680 const struct in_addr
*addresses
;
681 const uint8_t *client_id
, *data
;
682 size_t client_id_len
, data_len
;
685 struct sd_dhcp_route
*routes
;
691 r
= fopen_temporary(lease_file
, &f
, &temp_path
);
695 fchmod(fileno(f
), 0644);
697 r
= sd_dhcp_lease_get_address(lease
, &address
);
702 "# This is private data. Do not parse.\n"
703 "ADDRESS=%s\n", inet_ntoa(address
));
705 r
= sd_dhcp_lease_get_netmask(lease
, &address
);
709 fprintf(f
, "NETMASK=%s\n", inet_ntoa(address
));
711 r
= sd_dhcp_lease_get_router(lease
, &address
);
713 fprintf(f
, "ROUTER=%s\n", inet_ntoa(address
));
715 r
= sd_dhcp_lease_get_server_identifier(lease
, &address
);
717 fprintf(f
, "SERVER_ADDRESS=%s\n",
720 r
= sd_dhcp_lease_get_next_server(lease
, &address
);
722 fprintf(f
, "NEXT_SERVER=%s\n", inet_ntoa(address
));
724 r
= sd_dhcp_lease_get_mtu(lease
, &mtu
);
726 fprintf(f
, "MTU=%" PRIu16
"\n", mtu
);
729 r
= sd_dhcp_lease_get_dns(lease
, &addresses
);
731 serialize_in_addrs(f
, addresses
, r
);
735 r
= sd_dhcp_lease_get_ntp(lease
, &addresses
);
737 serialize_in_addrs(f
, addresses
, r
);
740 r
= sd_dhcp_lease_get_domainname(lease
, &string
);
742 fprintf(f
, "DOMAINNAME=%s\n", string
);
744 r
= sd_dhcp_lease_get_hostname(lease
, &string
);
746 fprintf(f
, "HOSTNAME=%s\n", string
);
748 r
= sd_dhcp_lease_get_root_path(lease
, &string
);
750 fprintf(f
, "ROOT_PATH=%s\n", string
);
752 r
= sd_dhcp_lease_get_routes(lease
, &routes
);
754 serialize_dhcp_routes(f
, "ROUTES", routes
, r
);
756 r
= sd_dhcp_lease_get_client_id(lease
, &client_id
, &client_id_len
);
758 _cleanup_free_
char *client_id_hex
;
760 client_id_hex
= hexmem(client_id
, client_id_len
);
761 if (!client_id_hex
) {
765 fprintf(f
, "CLIENTID=%s\n", client_id_hex
);
768 r
= sd_dhcp_lease_get_vendor_specific(lease
, &data
, &data_len
);
770 _cleanup_free_
char *option_hex
= NULL
;
772 option_hex
= hexmem(data
, data_len
);
777 fprintf(f
, "VENDOR_SPECIFIC=%s\n", option_hex
);
780 LIST_FOREACH(options
, option
, lease
->private_options
) {
781 char key
[strlen("OPTION_000")+1];
782 snprintf(key
, sizeof(key
), "OPTION_%"PRIu8
, option
->tag
);
783 r
= serialize_dhcp_option(f
, key
, option
->data
, option
->length
);
788 r
= fflush_and_check(f
);
792 if (rename(temp_path
, lease_file
) < 0) {
801 (void) unlink(temp_path
);
803 return log_error_errno(r
, "Failed to save lease data %s: %m", lease_file
);
806 int sd_dhcp_lease_load(sd_dhcp_lease
**ret
, const char *lease_file
) {
807 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
808 _cleanup_free_
char *address
= NULL
, *router
= NULL
, *netmask
= NULL
,
809 *server_address
= NULL
, *next_server
= NULL
,
810 *dns
= NULL
, *ntp
= NULL
, *mtu
= NULL
,
811 *routes
= NULL
, *client_id_hex
= NULL
,
812 *vendor_specific_hex
= NULL
,
813 *options
[DHCP_OPTION_PRIVATE_LAST
-
814 DHCP_OPTION_PRIVATE_BASE
+ 1] = { NULL
};
821 r
= dhcp_lease_new(&lease
);
825 r
= parse_env_file(lease_file
, NEWLINE
,
829 "SERVER_IDENTIFIER", &server_address
,
830 "NEXT_SERVER", &next_server
,
834 "DOMAINNAME", &lease
->domainname
,
835 "HOSTNAME", &lease
->hostname
,
836 "ROOT_PATH", &lease
->root_path
,
838 "CLIENTID", &client_id_hex
,
839 "VENDOR_SPECIFIC", &vendor_specific_hex
,
840 "OPTION_224", &options
[0],
841 "OPTION_225", &options
[1],
842 "OPTION_226", &options
[2],
843 "OPTION_227", &options
[3],
844 "OPTION_228", &options
[4],
845 "OPTION_229", &options
[5],
846 "OPTION_230", &options
[6],
847 "OPTION_231", &options
[7],
848 "OPTION_232", &options
[8],
849 "OPTION_233", &options
[9],
850 "OPTION_234", &options
[10],
851 "OPTION_235", &options
[11],
852 "OPTION_236", &options
[12],
853 "OPTION_237", &options
[13],
854 "OPTION_238", &options
[14],
855 "OPTION_239", &options
[15],
856 "OPTION_240", &options
[16],
857 "OPTION_241", &options
[17],
858 "OPTION_242", &options
[18],
859 "OPTION_243", &options
[19],
860 "OPTION_244", &options
[20],
861 "OPTION_245", &options
[21],
862 "OPTION_246", &options
[22],
863 "OPTION_247", &options
[23],
864 "OPTION_248", &options
[24],
865 "OPTION_249", &options
[25],
866 "OPTION_250", &options
[26],
867 "OPTION_251", &options
[27],
868 "OPTION_252", &options
[28],
869 "OPTION_253", &options
[29],
870 "OPTION_254", &options
[30],
876 return log_error_errno(r
, "Failed to read %s: %m", lease_file
);
879 r
= inet_pton(AF_INET
, address
, &addr
);
883 lease
->address
= addr
.s_addr
;
886 r
= inet_pton(AF_INET
, router
, &addr
);
890 lease
->router
= addr
.s_addr
;
893 r
= inet_pton(AF_INET
, netmask
, &addr
);
897 lease
->subnet_mask
= addr
.s_addr
;
899 if (server_address
) {
900 r
= inet_pton(AF_INET
, server_address
, &addr
);
904 lease
->server_address
= addr
.s_addr
;
908 r
= inet_pton(AF_INET
, next_server
, &addr
);
912 lease
->next_server
= addr
.s_addr
;
916 r
= deserialize_in_addrs(&lease
->dns
, dns
);
924 r
= deserialize_in_addrs(&lease
->ntp
, ntp
);
933 if (sscanf(mtu
, "%" SCNu16
, &u
) > 0)
938 r
= deserialize_dhcp_routes(&lease
->static_route
, &lease
->static_route_size
,
939 &lease
->static_route_allocated
, routes
);
945 r
= deserialize_dhcp_option(&lease
->client_id
, &lease
->client_id_len
, client_id_hex
);
950 if (vendor_specific_hex
) {
951 r
= deserialize_dhcp_option(&lease
->vendor_specific
, &lease
->vendor_specific_len
, vendor_specific_hex
);
956 for (i
= 0; i
<= DHCP_OPTION_PRIVATE_LAST
- DHCP_OPTION_PRIVATE_BASE
; i
++) {
957 _cleanup_free_
uint8_t *data
= NULL
;
963 r
= deserialize_dhcp_option(&data
, &len
, options
[i
]);
967 r
= dhcp_lease_insert_private_option(lease
, DHCP_OPTION_PRIVATE_BASE
+ i
, data
, len
);
978 int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease
*lease
) {
979 struct in_addr address
;
985 address
.s_addr
= lease
->address
;
987 /* fall back to the default subnet masks based on address class */
988 r
= in_addr_default_subnet_mask(&address
, &mask
);
992 lease
->subnet_mask
= mask
.s_addr
;
997 int sd_dhcp_lease_get_client_id(sd_dhcp_lease
*lease
, const uint8_t **client_id
,
998 size_t *client_id_len
) {
999 assert_return(lease
, -EINVAL
);
1000 assert_return(client_id
, -EINVAL
);
1001 assert_return(client_id_len
, -EINVAL
);
1003 *client_id
= lease
->client_id
;
1004 *client_id_len
= lease
->client_id_len
;
1008 int dhcp_lease_set_client_id(sd_dhcp_lease
*lease
, const uint8_t *client_id
,
1009 size_t client_id_len
) {
1010 assert_return(lease
, -EINVAL
);
1011 assert_return((!client_id
&& !client_id_len
) ||
1012 (client_id
&& client_id_len
), -EINVAL
);
1014 free (lease
->client_id
);
1015 lease
->client_id
= NULL
;
1016 lease
->client_id_len
= 0;
1019 lease
->client_id
= memdup (client_id
, client_id_len
);
1020 lease
->client_id_len
= client_id_len
;