1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2013 Intel Corporation. All rights reserved.
7 #include <net/ethernet.h>
8 #include <net/if_arp.h>
11 #include <sys/ioctl.h>
12 #include <linux/if_infiniband.h>
14 #include "sd-dhcp-client.h"
16 #include "alloc-util.h"
17 #include "dhcp-identifier.h"
18 #include "dhcp-internal.h"
19 #include "dhcp-lease-internal.h"
20 #include "dhcp-protocol.h"
21 #include "dns-domain.h"
22 #include "event-util.h"
24 #include "hostname-util.h"
26 #include "memory-util.h"
27 #include "network-common.h"
28 #include "random-util.h"
30 #include "sort-util.h"
31 #include "string-util.h"
33 #include "time-util.h"
37 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
38 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
40 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
41 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
43 #define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
44 * transient failure. */
46 typedef struct sd_dhcp_client_id
{
50 /* 0: Generic (non-LL) (RFC 2132) */
51 uint8_t data
[MAX_CLIENT_ID_LEN
];
54 /* 1: Ethernet Link-Layer (RFC 2132) */
55 uint8_t haddr
[ETH_ALEN
];
58 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
62 /* 255: Node-specific (RFC 4361) */
67 uint8_t data
[MAX_CLIENT_ID_LEN
];
70 } _packed_ sd_dhcp_client_id
;
72 struct sd_dhcp_client
{
78 sd_event_source
*timeout_resend
;
83 union sockaddr_union link
;
84 sd_event_source
*receive_message
;
85 bool request_broadcast
;
89 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
91 uint8_t bcast_addr
[MAX_MAC_ADDR_LEN
];
92 size_t bcast_addr_len
;
94 sd_dhcp_client_id client_id
;
97 char *vendor_class_identifier
;
101 uint32_t fallback_lease_lifetime
;
108 uint64_t max_attempts
;
109 OrderedHashmap
*extra_options
;
110 OrderedHashmap
*vendor_options
;
112 sd_event_source
*timeout_t1
;
113 sd_event_source
*timeout_t2
;
114 sd_event_source
*timeout_expire
;
115 sd_dhcp_client_callback_t callback
;
117 sd_dhcp_lease
*lease
;
121 /* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
125 static const uint8_t default_req_opts
[] = {
126 SD_DHCP_OPTION_SUBNET_MASK
,
127 SD_DHCP_OPTION_ROUTER
,
128 SD_DHCP_OPTION_HOST_NAME
,
129 SD_DHCP_OPTION_DOMAIN_NAME
,
130 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
133 /* RFC7844 section 3:
134 MAY contain the Parameter Request List option.
136 The client intending to protect its privacy SHOULD only request a
137 minimal number of options in the PRL and SHOULD also randomly shuffle
138 the ordering of option codes in the PRL. If this random ordering
139 cannot be implemented, the client MAY order the option codes in the
140 PRL by option code number (lowest to highest).
142 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
143 static const uint8_t default_req_opts_anonymize
[] = {
144 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
145 SD_DHCP_OPTION_ROUTER
, /* 3 */
146 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
147 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
148 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
149 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
150 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
151 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
152 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
153 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
154 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
155 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
156 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
159 static int client_receive_message_raw(
164 static int client_receive_message_udp(
169 static void client_stop(sd_dhcp_client
*client
, int error
);
171 int sd_dhcp_client_id_to_string(const void *data
, size_t len
, char **ret
) {
172 const sd_dhcp_client_id
*client_id
= data
;
173 _cleanup_free_
char *t
= NULL
;
176 assert_return(data
, -EINVAL
);
177 assert_return(len
>= 1, -EINVAL
);
178 assert_return(ret
, -EINVAL
);
181 if (len
> MAX_CLIENT_ID_LEN
)
184 switch (client_id
->type
) {
186 if (utf8_is_printable((char *) client_id
->gen
.data
, len
))
187 r
= asprintf(&t
, "%.*s", (int) len
, client_id
->gen
.data
);
189 r
= asprintf(&t
, "DATA");
192 if (len
!= sizeof_field(sd_dhcp_client_id
, eth
))
195 r
= asprintf(&t
, "%x:%x:%x:%x:%x:%x",
196 client_id
->eth
.haddr
[0],
197 client_id
->eth
.haddr
[1],
198 client_id
->eth
.haddr
[2],
199 client_id
->eth
.haddr
[3],
200 client_id
->eth
.haddr
[4],
201 client_id
->eth
.haddr
[5]);
204 r
= asprintf(&t
, "ARP/LL");
210 uint32_t iaid
= be32toh(client_id
->ns
.iaid
);
211 uint16_t duid_type
= be16toh(client_id
->ns
.duid
.type
);
212 if (dhcp_validate_duid_len(duid_type
, len
- 6, true) < 0)
215 r
= asprintf(&t
, "IAID:0x%x/DUID", iaid
);
225 int sd_dhcp_client_set_callback(
226 sd_dhcp_client
*client
,
227 sd_dhcp_client_callback_t cb
,
230 assert_return(client
, -EINVAL
);
232 client
->callback
= cb
;
233 client
->userdata
= userdata
;
238 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
239 assert_return(client
, -EINVAL
);
241 client
->request_broadcast
= !!broadcast
;
246 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
247 assert_return(client
, -EINVAL
);
248 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
252 case SD_DHCP_OPTION_PAD
:
253 case SD_DHCP_OPTION_OVERLOAD
:
254 case SD_DHCP_OPTION_MESSAGE_TYPE
:
255 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
256 case SD_DHCP_OPTION_END
:
263 return set_ensure_put(&client
->req_opts
, NULL
, UINT8_TO_PTR(option
));
266 int sd_dhcp_client_set_request_address(
267 sd_dhcp_client
*client
,
268 const struct in_addr
*last_addr
) {
270 assert_return(client
, -EINVAL
);
271 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
274 client
->last_addr
= last_addr
->s_addr
;
276 client
->last_addr
= INADDR_ANY
;
281 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
282 assert_return(client
, -EINVAL
);
283 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
284 assert_return(ifindex
> 0, -EINVAL
);
286 client
->ifindex
= ifindex
;
290 int sd_dhcp_client_set_ifname(sd_dhcp_client
*client
, const char *ifname
) {
291 assert_return(client
, -EINVAL
);
292 assert_return(ifname
, -EINVAL
);
294 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
297 return free_and_strdup(&client
->ifname
, ifname
);
300 const char *sd_dhcp_client_get_ifname(sd_dhcp_client
*client
) {
304 return get_ifname(client
->ifindex
, &client
->ifname
);
307 int sd_dhcp_client_set_mac(
308 sd_dhcp_client
*client
,
310 const uint8_t *bcast_addr
,
314 DHCP_CLIENT_DONT_DESTROY(client
);
315 bool need_restart
= false;
318 assert_return(client
, -EINVAL
);
319 assert_return(addr
, -EINVAL
);
320 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
321 assert_return(arp_type
> 0, -EINVAL
);
323 if (arp_type
== ARPHRD_ETHER
)
324 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
325 else if (arp_type
== ARPHRD_INFINIBAND
)
326 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
330 if (client
->mac_addr_len
== addr_len
&&
331 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0 &&
332 (client
->bcast_addr_len
> 0) == !!bcast_addr
&&
333 (!bcast_addr
|| memcmp(&client
->bcast_addr
, bcast_addr
, addr_len
) == 0))
336 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
337 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
339 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
342 memcpy(&client
->mac_addr
, addr
, addr_len
);
343 client
->mac_addr_len
= addr_len
;
344 client
->arp_type
= arp_type
;
345 client
->bcast_addr_len
= 0;
348 memcpy(&client
->bcast_addr
, bcast_addr
, addr_len
);
349 client
->bcast_addr_len
= addr_len
;
352 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
353 r
= sd_dhcp_client_start(client
);
355 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
361 int sd_dhcp_client_get_client_id(
362 sd_dhcp_client
*client
,
364 const uint8_t **data
,
367 assert_return(client
, -EINVAL
);
368 assert_return(type
, -EINVAL
);
369 assert_return(data
, -EINVAL
);
370 assert_return(data_len
, -EINVAL
);
372 if (client
->client_id_len
) {
373 *type
= client
->client_id
.type
;
374 *data
= client
->client_id
.raw
.data
;
375 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
385 int sd_dhcp_client_set_client_id(
386 sd_dhcp_client
*client
,
391 DHCP_CLIENT_DONT_DESTROY(client
);
392 bool need_restart
= false;
395 assert_return(client
, -EINVAL
);
396 assert_return(data
, -EINVAL
);
397 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
399 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
400 client
->client_id
.type
== type
&&
401 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
404 /* For hardware types, log debug message about unexpected data length.
406 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
407 * the last 8 bytes of the address are stable and suitable to put into
408 * the client-id. The caller is advised to account for that. */
409 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
410 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
411 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
412 "unexpected address length %zu",
415 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
416 log_dhcp_client(client
, "Changing client ID on running DHCP "
417 "client, restarting");
419 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
422 client
->client_id
.type
= type
;
423 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
424 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
426 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
427 r
= sd_dhcp_client_start(client
);
429 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
436 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
437 * without further modification. Otherwise, if duid_type is supported, DUID
438 * is set based on that type. Otherwise, an error is returned.
440 static int dhcp_client_set_iaid_duid_internal(
441 sd_dhcp_client
*client
,
450 DHCP_CLIENT_DONT_DESTROY(client
);
454 assert_return(client
, -EINVAL
);
455 assert_return(duid_len
== 0 || duid
, -EINVAL
);
458 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
460 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
463 zero(client
->client_id
);
464 client
->client_id
.type
= 255;
468 client
->client_id
.ns
.iaid
= htobe32(iaid
);
470 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
471 client
->mac_addr_len
,
472 /* legacy_unstable_byteorder = */ true,
473 /* use_mac = */ client
->test_mode
,
474 &client
->client_id
.ns
.iaid
);
476 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
481 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
482 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
483 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
487 if (client
->mac_addr_len
== 0)
488 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
490 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
492 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
495 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
497 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
500 if (client
->mac_addr_len
== 0)
501 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
503 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
505 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
508 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
510 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
513 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
516 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
517 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
519 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
520 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
521 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
522 r
= sd_dhcp_client_start(client
);
524 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
530 int sd_dhcp_client_set_iaid_duid(
531 sd_dhcp_client
*client
,
537 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
540 int sd_dhcp_client_set_iaid_duid_llt(
541 sd_dhcp_client
*client
,
545 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
548 int sd_dhcp_client_set_duid(
549 sd_dhcp_client
*client
,
553 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
556 int sd_dhcp_client_set_duid_llt(
557 sd_dhcp_client
*client
,
559 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
562 void dhcp_client_set_test_mode(sd_dhcp_client
*client
, bool test_mode
) {
565 client
->test_mode
= test_mode
;
568 int sd_dhcp_client_set_hostname(
569 sd_dhcp_client
*client
,
570 const char *hostname
) {
572 assert_return(client
, -EINVAL
);
574 /* Make sure hostnames qualify as DNS and as Linux hostnames */
576 !(hostname_is_valid(hostname
, 0) && dns_name_is_valid(hostname
) > 0))
579 return free_and_strdup(&client
->hostname
, hostname
);
582 int sd_dhcp_client_set_vendor_class_identifier(
583 sd_dhcp_client
*client
,
586 assert_return(client
, -EINVAL
);
588 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
591 int sd_dhcp_client_set_mud_url(
592 sd_dhcp_client
*client
,
593 const char *mudurl
) {
595 assert_return(client
, -EINVAL
);
596 assert_return(mudurl
, -EINVAL
);
597 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
598 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
600 return free_and_strdup(&client
->mudurl
, mudurl
);
603 int sd_dhcp_client_set_user_class(
604 sd_dhcp_client
*client
,
605 char * const *user_class
) {
610 assert_return(client
, -EINVAL
);
611 assert_return(!strv_isempty(user_class
), -EINVAL
);
613 STRV_FOREACH(p
, user_class
) {
614 size_t n
= strlen(*p
);
616 if (n
> 255 || n
== 0)
620 s
= strv_copy(user_class
);
624 return strv_free_and_replace(client
->user_class
, s
);
627 int sd_dhcp_client_set_client_port(
628 sd_dhcp_client
*client
,
631 assert_return(client
, -EINVAL
);
638 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
639 assert_return(client
, -EINVAL
);
640 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
647 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
648 assert_return(client
, -EINVAL
);
650 client
->max_attempts
= max_attempts
;
655 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
658 assert_return(client
, -EINVAL
);
659 assert_return(v
, -EINVAL
);
661 r
= ordered_hashmap_ensure_put(&client
->extra_options
, &dhcp_option_hash_ops
, UINT_TO_PTR(v
->option
), v
);
665 sd_dhcp_option_ref(v
);
669 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
672 assert_return(client
, -EINVAL
);
673 assert_return(v
, -EINVAL
);
675 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
679 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
683 sd_dhcp_option_ref(v
);
688 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
689 assert_return(client
, -EINVAL
);
691 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
692 return -EADDRNOTAVAIL
;
695 *ret
= client
->lease
;
700 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
701 assert_return(client
, -EINVAL
);
703 client
->ip_service_type
= type
;
708 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint32_t fallback_lease_lifetime
) {
709 assert_return(client
, -EINVAL
);
710 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
712 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
717 static int client_notify(sd_dhcp_client
*client
, int event
) {
720 if (client
->callback
)
721 return client
->callback(client
, event
, client
->userdata
);
726 static int client_initialize(sd_dhcp_client
*client
) {
727 assert_return(client
, -EINVAL
);
729 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
731 client
->fd
= safe_close(client
->fd
);
733 (void) event_source_disable(client
->timeout_resend
);
734 (void) event_source_disable(client
->timeout_t1
);
735 (void) event_source_disable(client
->timeout_t2
);
736 (void) event_source_disable(client
->timeout_expire
);
740 client
->state
= DHCP_STATE_INIT
;
743 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
748 static void client_stop(sd_dhcp_client
*client
, int error
) {
752 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
753 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
754 log_dhcp_client(client
, "STOPPED");
756 log_dhcp_client(client
, "STOPPED: Unknown event");
758 client_notify(client
, error
);
760 client_initialize(client
);
763 /* RFC2131 section 4.1:
764 * retransmission delays should include -1 to +1 sec of random 'fuzz'. */
765 #define RFC2131_RANDOM_FUZZ \
766 ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
768 /* RFC2131 section 4.1:
769 * for retransmission delays, timeout should start at 4s then double
770 * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
771 * This assumes the first call will be using attempt 1. */
772 static usec_t
client_compute_request_timeout(usec_t now
, uint64_t attempt
) {
773 usec_t timeout
= (UINT64_C(1) << MIN(attempt
+ 1, UINT64_C(6))) * USEC_PER_SEC
;
775 return usec_sub_signed(usec_add(now
, timeout
), RFC2131_RANDOM_FUZZ
);
778 /* RFC2131 section 4.4.5:
779 * T1 defaults to (0.5 * duration_of_lease).
780 * T2 defaults to (0.875 * duration_of_lease). */
781 #define T1_DEFAULT(lifetime) ((lifetime) / 2)
782 #define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
784 /* RFC2131 section 4.4.5:
785 * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
786 * and one-half of the remaining lease time (in REBINDING state), down to a minimum
788 * Note that while the default T1/T2 initial times do have random 'fuzz' applied,
789 * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
790 static usec_t
client_compute_reacquisition_timeout(usec_t now
, usec_t expire
) {
791 return now
+ MAX(usec_sub_unsigned(expire
, now
) / 2, 60 * USEC_PER_SEC
);
794 static int cmp_uint8(const uint8_t *a
, const uint8_t *b
) {
798 static int client_message_init(
799 sd_dhcp_client
*client
,
803 size_t *_optoffset
) {
805 _cleanup_free_ DHCPPacket
*packet
= NULL
;
806 size_t optlen
, optoffset
, size
;
813 assert(client
->start_time
);
817 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
819 optlen
= DHCP_MIN_OPTIONS_SIZE
;
820 size
= sizeof(DHCPPacket
) + optlen
;
822 packet
= malloc0(size
);
826 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
827 client
->arp_type
, optlen
, &optoffset
);
831 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
832 refuse to issue an DHCP lease if 'secs' is set to zero */
833 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
836 assert(time_now
>= client
->start_time
);
838 /* seconds between sending first and last DISCOVER
839 * must always be strictly positive to deal with broken servers */
840 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
841 packet
->dhcp
.secs
= htobe16(secs
);
843 /* RFC2132 section 4.1
844 A client that cannot receive unicast IP datagrams until its protocol
845 software has been configured with an IP address SHOULD set the
846 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
847 DHCPREQUEST messages that client sends. The BROADCAST bit will
848 provide a hint to the DHCP server and BOOTP relay agent to broadcast
849 any messages to the client on the client's subnet.
851 Note: some interfaces needs this to be enabled, but some networks
852 needs this to be disabled as broadcasts are filteretd, so this
853 needs to be configurable */
854 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
855 packet
->dhcp
.flags
= htobe16(0x8000);
857 /* RFC2132 section 4.1.1:
858 The client MUST include its hardware address in the ’chaddr’ field, if
859 necessary for delivery of DHCP reply messages. Non-Ethernet
860 interfaces will leave 'chaddr' empty and use the client identifier
861 instead (eg, RFC 4390 section 2.1).
863 if (client
->arp_type
== ARPHRD_ETHER
)
864 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
866 /* If no client identifier exists, construct an RFC 4361-compliant one */
867 if (client
->client_id_len
== 0) {
870 client
->client_id
.type
= 255;
872 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
873 /* legacy_unstable_byteorder = */ true,
874 /* use_mac = */ client
->test_mode
,
875 &client
->client_id
.ns
.iaid
);
879 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
883 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
886 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
887 Identifier option is not set */
888 if (client
->client_id_len
) {
889 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
890 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
891 client
->client_id_len
,
897 /* RFC2131 section 3.5:
898 in its initial DHCPDISCOVER or DHCPREQUEST message, a
899 client may provide the server with a list of specific
900 parameters the client is interested in. If the client
901 includes a list of parameters in a DHCPDISCOVER message,
902 it MUST include that list in any subsequent DHCPREQUEST
906 /* RFC7844 section 3:
907 MAY contain the Parameter Request List option. */
908 /* NOTE: in case that there would be an option to do not send
909 * any PRL at all, the size should be checked before sending */
910 if (!set_isempty(client
->req_opts
) && type
!= DHCP_RELEASE
) {
911 _cleanup_free_
uint8_t *opts
= NULL
;
912 size_t n_opts
, i
= 0;
915 n_opts
= set_size(client
->req_opts
);
916 opts
= new(uint8_t, n_opts
);
920 SET_FOREACH(val
, client
->req_opts
)
921 opts
[i
++] = PTR_TO_UINT8(val
);
924 /* For anonymizing the request, let's sort the options. */
925 typesafe_qsort(opts
, n_opts
, cmp_uint8
);
927 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
928 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
934 /* RFC2131 section 3.5:
935 The client SHOULD include the ’maximum DHCP message size’ option to
936 let the server know how large the server may make its DHCP messages.
938 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
939 than the defined default size unless the Maximum Message Size option
942 RFC3442 "Requirements to Avoid Sizing Constraints":
943 Because a full routing table can be quite large, the standard 576
944 octet maximum size for a DHCP message may be too short to contain
945 some legitimate Classless Static Route options. Because of this,
946 clients implementing the Classless Static Route option SHOULD send a
947 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
948 stack is capable of receiving larger IP datagrams. In this case, the
949 client SHOULD set the value of this option to at least the MTU of the
950 interface that the client is configuring. The client MAY set the
951 value of this option higher, up to the size of the largest UDP packet
952 it is prepared to accept. (Note that the value specified in the
953 Maximum DHCP Message Size option is the total maximum packet size,
954 including IP and UDP headers.)
956 /* RFC7844 section 3:
957 SHOULD NOT contain any other option. */
958 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
959 max_size
= htobe16(size
);
960 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
961 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
968 *_optoffset
= optoffset
;
969 *ret
= TAKE_PTR(packet
);
974 static int client_append_fqdn_option(
975 DHCPMessage
*message
,
980 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
983 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
984 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
985 buffer
[1] = 0; /* RCODE1 (deprecated) */
986 buffer
[2] = 0; /* RCODE2 (deprecated) */
988 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
990 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
991 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
996 static int dhcp_client_send_raw(
997 sd_dhcp_client
*client
,
1001 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
1002 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
1004 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
1008 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
1014 if (client
->hostname
) {
1015 /* According to RFC 4702 "clients that send the Client FQDN option in
1016 their messages MUST NOT also send the Host Name option". Just send
1017 one of the two depending on the hostname type.
1019 if (dns_name_is_single_label(client
->hostname
)) {
1020 /* it is unclear from RFC 2131 if client should send hostname in
1021 DHCPDISCOVER but dhclient does and so we do as well
1023 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1024 SD_DHCP_OPTION_HOST_NAME
,
1025 strlen(client
->hostname
), client
->hostname
);
1027 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
1033 if (client
->vendor_class_identifier
) {
1034 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1035 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1036 strlen(client
->vendor_class_identifier
),
1037 client
->vendor_class_identifier
);
1042 if (client
->mudurl
) {
1043 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1044 SD_DHCP_OPTION_MUD_URL
,
1045 strlen(client
->mudurl
),
1051 if (client
->user_class
) {
1052 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1053 SD_DHCP_OPTION_USER_CLASS
,
1054 strv_length(client
->user_class
),
1055 client
->user_class
);
1060 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
) {
1061 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1062 j
->option
, j
->length
, j
->data
);
1067 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
1068 r
= dhcp_option_append(
1069 &packet
->dhcp
, optlen
, optoffset
, 0,
1070 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
1071 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
1080 static int client_send_discover(sd_dhcp_client
*client
) {
1081 _cleanup_free_ DHCPPacket
*discover
= NULL
;
1082 size_t optoffset
, optlen
;
1086 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
1088 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
1089 &optlen
, &optoffset
);
1093 /* the client may suggest values for the network address
1094 and lease time in the DHCPDISCOVER message. The client may include
1095 the ’requested IP address’ option to suggest that a particular IP
1096 address be assigned, and may include the ’IP address lease time’
1097 option to suggest the lease time it would like.
1099 /* RFC7844 section 3:
1100 SHOULD NOT contain any other option. */
1101 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
1102 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1103 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1104 4, &client
->last_addr
);
1109 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
1113 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1114 SD_DHCP_OPTION_END
, 0, NULL
);
1118 /* We currently ignore:
1119 The client SHOULD wait a random time between one and ten seconds to
1120 desynchronize the use of DHCP at startup.
1122 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1126 log_dhcp_client(client
, "DISCOVER");
1131 static int client_send_request(sd_dhcp_client
*client
) {
1132 _cleanup_free_ DHCPPacket
*request
= NULL
;
1133 size_t optoffset
, optlen
;
1138 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
1142 switch (client
->state
) {
1143 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1144 SELECTING should be REQUESTING)
1147 case DHCP_STATE_REQUESTING
:
1148 /* Client inserts the address of the selected server in ’server
1149 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1150 filled in with the yiaddr value from the chosen DHCPOFFER.
1153 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1154 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1155 4, &client
->lease
->server_address
);
1159 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1160 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1161 4, &client
->lease
->address
);
1167 case DHCP_STATE_INIT_REBOOT
:
1168 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1169 option MUST be filled in with client’s notion of its previously
1170 assigned address. ’ciaddr’ MUST be zero.
1172 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1173 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1174 4, &client
->last_addr
);
1179 case DHCP_STATE_RENEWING
:
1180 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1181 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1182 client’s IP address.
1185 case DHCP_STATE_REBINDING
:
1186 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1187 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1188 client’s IP address.
1190 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1192 request
->dhcp
.ciaddr
= client
->lease
->address
;
1196 case DHCP_STATE_INIT
:
1197 case DHCP_STATE_SELECTING
:
1198 case DHCP_STATE_REBOOTING
:
1199 case DHCP_STATE_BOUND
:
1200 case DHCP_STATE_STOPPED
:
1204 r
= client_append_common_discover_request_options(client
, request
, &optoffset
, optlen
);
1208 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1209 SD_DHCP_OPTION_END
, 0, NULL
);
1213 if (client
->state
== DHCP_STATE_RENEWING
)
1214 r
= dhcp_network_send_udp_socket(client
->fd
,
1215 client
->lease
->server_address
,
1218 sizeof(DHCPMessage
) + optoffset
);
1220 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1224 switch (client
->state
) {
1226 case DHCP_STATE_REQUESTING
:
1227 log_dhcp_client(client
, "REQUEST (requesting)");
1230 case DHCP_STATE_INIT_REBOOT
:
1231 log_dhcp_client(client
, "REQUEST (init-reboot)");
1234 case DHCP_STATE_RENEWING
:
1235 log_dhcp_client(client
, "REQUEST (renewing)");
1238 case DHCP_STATE_REBINDING
:
1239 log_dhcp_client(client
, "REQUEST (rebinding)");
1243 log_dhcp_client(client
, "REQUEST (invalid)");
1250 static int client_start(sd_dhcp_client
*client
);
1252 static int client_timeout_resend(
1257 sd_dhcp_client
*client
= userdata
;
1258 DHCP_CLIENT_DONT_DESTROY(client
);
1259 usec_t next_timeout
;
1265 assert(client
->event
);
1267 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1271 switch (client
->state
) {
1273 case DHCP_STATE_RENEWING
:
1274 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->t2_time
);
1277 case DHCP_STATE_REBINDING
:
1278 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->expire_time
);
1281 case DHCP_STATE_REBOOTING
:
1282 /* start over as we did not receive a timely ack or nak */
1283 r
= client_initialize(client
);
1287 r
= client_start(client
);
1291 log_dhcp_client(client
, "REBOOTED");
1294 case DHCP_STATE_INIT
:
1295 case DHCP_STATE_INIT_REBOOT
:
1296 case DHCP_STATE_SELECTING
:
1297 case DHCP_STATE_REQUESTING
:
1298 case DHCP_STATE_BOUND
:
1299 if (client
->attempt
>= client
->max_attempts
)
1303 next_timeout
= client_compute_request_timeout(time_now
, client
->attempt
);
1306 case DHCP_STATE_STOPPED
:
1311 assert_not_reached("Unhandled choice");
1314 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1315 clock_boottime_or_monotonic(),
1316 next_timeout
, 10 * USEC_PER_MSEC
,
1317 client_timeout_resend
, client
,
1318 client
->event_priority
, "dhcp4-resend-timer", true);
1322 switch (client
->state
) {
1323 case DHCP_STATE_INIT
:
1324 r
= client_send_discover(client
);
1326 client
->state
= DHCP_STATE_SELECTING
;
1327 client
->attempt
= 0;
1328 } else if (client
->attempt
>= client
->max_attempts
)
1333 case DHCP_STATE_SELECTING
:
1334 r
= client_send_discover(client
);
1335 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1340 case DHCP_STATE_INIT_REBOOT
:
1341 case DHCP_STATE_REQUESTING
:
1342 case DHCP_STATE_RENEWING
:
1343 case DHCP_STATE_REBINDING
:
1344 r
= client_send_request(client
);
1345 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1348 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1349 client
->state
= DHCP_STATE_REBOOTING
;
1351 client
->request_sent
= time_now
;
1354 case DHCP_STATE_REBOOTING
:
1355 case DHCP_STATE_BOUND
:
1358 case DHCP_STATE_STOPPED
:
1363 if (client
->attempt
>= TRANSIENT_FAILURE_ATTEMPTS
)
1364 client_notify(client
, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE
);
1369 client_stop(client
, r
);
1371 /* Errors were dealt with when stopping the client, don't spill
1372 errors into the event loop handler */
1376 static int client_initialize_io_events(
1377 sd_dhcp_client
*client
,
1378 sd_event_io_handler_t io_callback
) {
1383 assert(client
->event
);
1385 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1386 client
->fd
, EPOLLIN
, io_callback
,
1391 r
= sd_event_source_set_priority(client
->receive_message
,
1392 client
->event_priority
);
1396 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1402 client_stop(client
, r
);
1407 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1412 assert(client
->event
);
1414 if (client
->start_delay
> 0) {
1415 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1416 usec
+= client
->start_delay
;
1419 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1420 clock_boottime_or_monotonic(),
1422 client_timeout_resend
, client
,
1423 client
->event_priority
, "dhcp4-resend-timer", true);
1425 client_stop(client
, r
);
1431 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1432 client_initialize_io_events(client
, io_callback
);
1433 client_initialize_time_events(client
);
1438 static int client_start_delayed(sd_dhcp_client
*client
) {
1441 assert_return(client
, -EINVAL
);
1442 assert_return(client
->event
, -EINVAL
);
1443 assert_return(client
->ifindex
> 0, -EINVAL
);
1444 assert_return(client
->fd
< 0, -EBUSY
);
1445 assert_return(client
->xid
== 0, -EINVAL
);
1446 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1448 client
->xid
= random_u32();
1450 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1451 client
->mac_addr
, client
->mac_addr_len
,
1452 client
->bcast_addr
, client
->bcast_addr_len
,
1453 client
->arp_type
, client
->port
);
1455 client_stop(client
, r
);
1460 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1461 client
->start_time
= now(clock_boottime_or_monotonic());
1463 return client_initialize_events(client
, client_receive_message_raw
);
1466 static int client_start(sd_dhcp_client
*client
) {
1467 client
->start_delay
= 0;
1468 return client_start_delayed(client
);
1471 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1472 sd_dhcp_client
*client
= userdata
;
1473 DHCP_CLIENT_DONT_DESTROY(client
);
1475 log_dhcp_client(client
, "EXPIRED");
1477 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1479 /* lease was lost, start over if not freed or stopped in callback */
1480 if (client
->state
!= DHCP_STATE_STOPPED
) {
1481 client_initialize(client
);
1482 client_start(client
);
1488 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1489 sd_dhcp_client
*client
= userdata
;
1490 DHCP_CLIENT_DONT_DESTROY(client
);
1495 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1496 client
->fd
= safe_close(client
->fd
);
1498 client
->state
= DHCP_STATE_REBINDING
;
1499 client
->attempt
= 0;
1501 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1502 client
->mac_addr
, client
->mac_addr_len
,
1503 client
->bcast_addr
, client
->bcast_addr_len
,
1504 client
->arp_type
, client
->port
);
1506 client_stop(client
, r
);
1511 return client_initialize_events(client
, client_receive_message_raw
);
1514 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1515 sd_dhcp_client
*client
= userdata
;
1516 DHCP_CLIENT_DONT_DESTROY(client
);
1519 client
->state
= DHCP_STATE_RENEWING
;
1520 else if (client
->state
!= DHCP_STATE_INIT
)
1521 client
->state
= DHCP_STATE_INIT_REBOOT
;
1522 client
->attempt
= 0;
1524 return client_initialize_time_events(client
);
1527 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1528 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1531 r
= dhcp_lease_new(&lease
);
1535 if (client
->client_id_len
) {
1536 r
= dhcp_lease_set_client_id(lease
,
1537 (uint8_t *) &client
->client_id
,
1538 client
->client_id_len
);
1543 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1544 if (r
!= DHCP_OFFER
) {
1545 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1549 lease
->next_server
= offer
->siaddr
;
1550 lease
->address
= offer
->yiaddr
;
1552 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1553 lease
->lifetime
= client
->fallback_lease_lifetime
;
1555 if (lease
->address
== 0 ||
1556 lease
->server_address
== 0 ||
1557 lease
->lifetime
== 0) {
1558 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1562 if (!lease
->have_subnet_mask
) {
1563 r
= dhcp_lease_set_default_subnet_mask(lease
);
1565 log_dhcp_client(client
,
1566 "received lease lacks subnet mask, "
1567 "and a fallback one cannot be generated, ignoring");
1572 sd_dhcp_lease_unref(client
->lease
);
1573 client
->lease
= TAKE_PTR(lease
);
1575 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1578 log_dhcp_client(client
, "OFFER");
1583 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1586 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1587 if (r
!= DHCP_FORCERENEW
)
1591 log_dhcp_client(client
, "FORCERENEW");
1595 /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP
1596 * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW
1597 * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */
1598 log_dhcp_client(client
, "Received FORCERENEW, ignoring.");
1603 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1604 if (a
->address
!= b
->address
)
1607 if (a
->subnet_mask
!= b
->subnet_mask
)
1610 if (a
->router_size
!= b
->router_size
)
1613 for (size_t i
= 0; i
< a
->router_size
; i
++)
1614 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1620 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1621 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1622 _cleanup_free_
char *error_message
= NULL
;
1625 r
= dhcp_lease_new(&lease
);
1629 if (client
->client_id_len
) {
1630 r
= dhcp_lease_set_client_id(lease
,
1631 (uint8_t *) &client
->client_id
,
1632 client
->client_id_len
);
1637 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1638 if (r
== DHCP_NAK
) {
1639 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1640 return -EADDRNOTAVAIL
;
1643 if (r
!= DHCP_ACK
) {
1644 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1648 lease
->next_server
= ack
->siaddr
;
1650 lease
->address
= ack
->yiaddr
;
1652 if (lease
->address
== INADDR_ANY
||
1653 lease
->server_address
== INADDR_ANY
||
1654 lease
->lifetime
== 0) {
1655 log_dhcp_client(client
, "received lease lacks address, server "
1656 "address or lease lifetime, ignoring");
1660 if (lease
->subnet_mask
== INADDR_ANY
) {
1661 r
= dhcp_lease_set_default_subnet_mask(lease
);
1663 log_dhcp_client(client
,
1664 "received lease lacks subnet mask, "
1665 "and a fallback one cannot be generated, ignoring");
1670 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1671 if (client
->lease
) {
1672 if (lease_equal(client
->lease
, lease
))
1673 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1675 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1677 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1680 client
->lease
= TAKE_PTR(lease
);
1682 log_dhcp_client(client
, "ACK");
1687 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1692 assert(client
->event
);
1693 assert(client
->lease
);
1694 assert(client
->lease
->lifetime
);
1696 /* don't set timers for infinite leases */
1697 if (client
->lease
->lifetime
== 0xffffffff) {
1698 (void) event_source_disable(client
->timeout_t1
);
1699 (void) event_source_disable(client
->timeout_t2
);
1700 (void) event_source_disable(client
->timeout_expire
);
1705 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1708 assert(client
->request_sent
<= time_now
);
1710 /* verify that 0 < t2 < lifetime */
1711 if (client
->lease
->t2
== 0 || client
->lease
->t2
>= client
->lease
->lifetime
)
1712 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1713 /* verify that 0 < t1 < lifetime */
1714 if (client
->lease
->t1
== 0 || client
->lease
->t1
>= client
->lease
->t2
)
1715 client
->lease
->t1
= T1_DEFAULT(client
->lease
->lifetime
);
1716 /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
1717 * could not evalate to false if t1 >= t2; so setting t2 to T2_DEFAULT
1718 * guarantees t1 < t2. */
1719 if (client
->lease
->t1
>= client
->lease
->t2
)
1720 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1722 client
->expire_time
= client
->request_sent
+ client
->lease
->lifetime
* USEC_PER_SEC
;
1723 client
->t1_time
= client
->request_sent
+ client
->lease
->t1
* USEC_PER_SEC
;
1724 client
->t2_time
= client
->request_sent
+ client
->lease
->t2
* USEC_PER_SEC
;
1726 /* RFC2131 section 4.4.5:
1727 * Times T1 and T2 SHOULD be chosen with some random "fuzz".
1728 * Since the RFC doesn't specify here the exact 'fuzz' to use,
1729 * we use the range from section 4.1: -1 to +1 sec. */
1730 client
->t1_time
= usec_sub_signed(client
->t1_time
, RFC2131_RANDOM_FUZZ
);
1731 client
->t2_time
= usec_sub_signed(client
->t2_time
, RFC2131_RANDOM_FUZZ
);
1733 /* after fuzzing, ensure t2 is still >= t1 */
1734 client
->t2_time
= MAX(client
->t1_time
, client
->t2_time
);
1736 /* arm lifetime timeout */
1737 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1738 clock_boottime_or_monotonic(),
1739 client
->expire_time
, 10 * USEC_PER_MSEC
,
1740 client_timeout_expire
, client
,
1741 client
->event_priority
, "dhcp4-lifetime", true);
1745 /* don't arm earlier timeouts if this has already expired */
1746 if (client
->expire_time
<= time_now
)
1749 log_dhcp_client(client
, "lease expires in %s",
1750 FORMAT_TIMESPAN(client
->expire_time
- time_now
, USEC_PER_SEC
));
1752 /* arm T2 timeout */
1753 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1754 clock_boottime_or_monotonic(),
1755 client
->t2_time
, 10 * USEC_PER_MSEC
,
1756 client_timeout_t2
, client
,
1757 client
->event_priority
, "dhcp4-t2-timeout", true);
1761 /* don't arm earlier timeout if this has already expired */
1762 if (client
->t2_time
<= time_now
)
1765 log_dhcp_client(client
, "T2 expires in %s",
1766 FORMAT_TIMESPAN(client
->t2_time
- time_now
, USEC_PER_SEC
));
1768 /* arm T1 timeout */
1769 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1770 clock_boottime_or_monotonic(),
1771 client
->t1_time
, 10 * USEC_PER_MSEC
,
1772 client_timeout_t1
, client
,
1773 client
->event_priority
, "dhcp4-t1-timer", true);
1777 if (client
->t1_time
> time_now
)
1778 log_dhcp_client(client
, "T1 expires in %s",
1779 FORMAT_TIMESPAN(client
->t1_time
- time_now
, USEC_PER_SEC
));
1784 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1785 DHCP_CLIENT_DONT_DESTROY(client
);
1786 int r
, notify_event
;
1789 assert(client
->event
);
1792 switch (client
->state
) {
1793 case DHCP_STATE_SELECTING
:
1795 r
= client_handle_offer(client
, message
, len
);
1797 return 0; /* invalid message, let's ignore it */
1801 client
->state
= DHCP_STATE_REQUESTING
;
1802 client
->attempt
= 0;
1804 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1805 clock_boottime_or_monotonic(),
1807 client_timeout_resend
, client
,
1808 client
->event_priority
, "dhcp4-resend-timer", true);
1811 case DHCP_STATE_REBOOTING
:
1812 case DHCP_STATE_REQUESTING
:
1813 case DHCP_STATE_RENEWING
:
1814 case DHCP_STATE_REBINDING
:
1816 r
= client_handle_ack(client
, message
, len
);
1818 return 0; /* invalid message, let's ignore it */
1819 if (r
== -EADDRNOTAVAIL
) {
1820 /* got a NAK, let's restart the client */
1821 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1823 r
= client_initialize(client
);
1827 r
= client_start_delayed(client
);
1831 log_dhcp_client(client
, "REBOOT in %s", FORMAT_TIMESPAN(client
->start_delay
, USEC_PER_SEC
));
1833 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1834 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1840 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
, DHCP_STATE_REBOOTING
))
1841 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1845 client
->start_delay
= 0;
1846 (void) event_source_disable(client
->timeout_resend
);
1847 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1848 client
->fd
= safe_close(client
->fd
);
1850 client
->state
= DHCP_STATE_BOUND
;
1851 client
->attempt
= 0;
1853 client
->last_addr
= client
->lease
->address
;
1855 r
= client_set_lease_timeouts(client
);
1857 log_dhcp_client(client
, "could not set lease timeouts");
1861 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1863 log_dhcp_client(client
, "could not bind UDP socket");
1869 client_initialize_io_events(client
, client_receive_message_udp
);
1871 if (IN_SET(client
->state
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
) &&
1872 notify_event
== SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1873 /* FIXME: hmm, maybe this is a bug... */
1874 log_dhcp_client(client
, "client_handle_ack() returned SD_DHCP_CLIENT_EVENT_IP_ACQUIRE while DHCP client is %s the address, skipping callback.",
1875 client
->state
== DHCP_STATE_RENEWING
? "renewing" : "rebinding");
1877 client_notify(client
, notify_event
);
1880 case DHCP_STATE_BOUND
:
1881 r
= client_handle_forcerenew(client
, message
, len
);
1883 return 0; /* invalid message, let's ignore it */
1887 r
= client_timeout_t1(NULL
, 0, client
);
1890 case DHCP_STATE_INIT
:
1891 case DHCP_STATE_INIT_REBOOT
:
1895 case DHCP_STATE_STOPPED
:
1899 assert_not_reached("invalid state");
1904 client_stop(client
, r
);
1909 static int client_receive_message_udp(
1915 sd_dhcp_client
*client
= userdata
;
1916 _cleanup_free_ DHCPMessage
*message
= NULL
;
1917 const uint8_t *expected_chaddr
= NULL
;
1918 uint8_t expected_hlen
= 0;
1919 ssize_t len
, buflen
;
1924 buflen
= next_datagram_size_fd(fd
);
1925 if (buflen
== -ENETDOWN
)
1926 /* the link is down. Don't return an error or the I/O event
1927 source will be disconnected and we won't be able to receive
1928 packets again when the link comes back. */
1933 message
= malloc0(buflen
);
1937 len
= recv(fd
, message
, buflen
, 0);
1939 /* see comment above for why we shouldn't error out on ENETDOWN. */
1940 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1943 return log_dhcp_client_errno(client
, errno
,
1944 "Could not receive message from UDP socket: %m");
1946 if ((size_t) len
< sizeof(DHCPMessage
)) {
1947 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1951 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1952 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1956 if (message
->op
!= BOOTREPLY
) {
1957 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1961 if (message
->htype
!= client
->arp_type
) {
1962 log_dhcp_client(client
, "Packet type does not match client type");
1966 if (client
->arp_type
== ARPHRD_ETHER
) {
1967 expected_hlen
= ETH_ALEN
;
1968 expected_chaddr
= &client
->mac_addr
[0];
1971 if (message
->hlen
!= expected_hlen
) {
1972 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1976 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1977 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1981 if (client
->state
!= DHCP_STATE_BOUND
&&
1982 be32toh(message
->xid
) != client
->xid
) {
1983 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1984 so ignore the xid in this case */
1985 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1986 be32toh(message
->xid
), client
->xid
);
1990 return client_handle_message(client
, message
, len
);
1993 static int client_receive_message_raw(
1999 sd_dhcp_client
*client
= userdata
;
2000 _cleanup_free_ DHCPPacket
*packet
= NULL
;
2001 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
;
2002 struct iovec iov
= {};
2003 struct msghdr msg
= {
2006 .msg_control
= &control
,
2007 .msg_controllen
= sizeof(control
),
2009 struct cmsghdr
*cmsg
;
2010 bool checksum
= true;
2011 ssize_t buflen
, len
;
2017 buflen
= next_datagram_size_fd(fd
);
2018 if (buflen
== -ENETDOWN
)
2023 packet
= malloc0(buflen
);
2027 iov
= IOVEC_MAKE(packet
, buflen
);
2029 len
= recvmsg_safe(fd
, &msg
, 0);
2030 if (IN_SET(len
, -EAGAIN
, -EINTR
, -ENETDOWN
))
2033 return log_dhcp_client_errno(client
, len
,
2034 "Could not receive message from raw socket: %m");
2036 if ((size_t) len
< sizeof(DHCPPacket
))
2039 cmsg
= cmsg_find(&msg
, SOL_PACKET
, PACKET_AUXDATA
, CMSG_LEN(sizeof(struct tpacket_auxdata
)));
2041 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*) CMSG_DATA(cmsg
);
2042 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2045 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
2049 len
-= DHCP_IP_UDP_SIZE
;
2051 return client_handle_message(client
, &packet
->dhcp
, len
);
2054 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2055 assert_return(client
, -EINVAL
);
2056 assert_return(client
->fd
>= 0, -EINVAL
);
2061 client
->start_delay
= 0;
2062 client
->attempt
= 1;
2063 client
->state
= DHCP_STATE_RENEWING
;
2065 return client_initialize_time_events(client
);
2068 int sd_dhcp_client_is_running(sd_dhcp_client
*client
) {
2072 return !IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
);
2075 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2078 assert_return(client
, -EINVAL
);
2080 r
= client_initialize(client
);
2084 /* RFC7844 section 3.3:
2085 SHOULD perform a complete four-way handshake, starting with a
2086 DHCPDISCOVER, to obtain a new address lease. If the client can
2087 ascertain that this is exactly the same network to which it was
2088 previously connected, and if the link-layer address did not change,
2089 the client MAY issue a DHCPREQUEST to try to reclaim the current
2091 if (client
->last_addr
&& !client
->anonymize
)
2092 client
->state
= DHCP_STATE_INIT_REBOOT
;
2094 r
= client_start(client
);
2096 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2101 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2102 assert_return(client
, -EINVAL
);
2103 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2104 assert_return(client
->lease
, -EUNATCH
);
2106 _cleanup_free_ DHCPPacket
*release
= NULL
;
2107 size_t optoffset
, optlen
;
2110 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2114 /* Fill up release IP and MAC */
2115 release
->dhcp
.ciaddr
= client
->lease
->address
;
2116 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2118 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2119 SD_DHCP_OPTION_END
, 0, NULL
);
2123 r
= dhcp_network_send_udp_socket(client
->fd
,
2124 client
->lease
->server_address
,
2127 sizeof(DHCPMessage
) + optoffset
);
2131 log_dhcp_client(client
, "RELEASE");
2136 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2137 assert_return(client
, -EINVAL
);
2138 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2139 assert_return(client
->lease
, -EUNATCH
);
2141 _cleanup_free_ DHCPPacket
*release
= NULL
;
2142 size_t optoffset
, optlen
;
2145 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2149 release
->dhcp
.ciaddr
= client
->lease
->address
;
2150 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2152 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2153 SD_DHCP_OPTION_END
, 0, NULL
);
2157 r
= dhcp_network_send_udp_socket(client
->fd
,
2158 client
->lease
->server_address
,
2161 sizeof(DHCPMessage
) + optoffset
);
2165 log_dhcp_client(client
, "DECLINE");
2167 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2169 if (client
->state
!= DHCP_STATE_STOPPED
) {
2170 r
= sd_dhcp_client_start(client
);
2178 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2182 DHCP_CLIENT_DONT_DESTROY(client
);
2184 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2185 client
->state
= DHCP_STATE_STOPPED
;
2190 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2193 assert_return(client
, -EINVAL
);
2194 assert_return(!client
->event
, -EBUSY
);
2197 client
->event
= sd_event_ref(event
);
2199 r
= sd_event_default(&client
->event
);
2204 client
->event_priority
= priority
;
2209 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2210 assert_return(client
, -EINVAL
);
2212 client
->event
= sd_event_unref(client
->event
);
2217 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2218 assert_return(client
, NULL
);
2220 return client
->event
;
2223 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2227 log_dhcp_client(client
, "FREE");
2229 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2230 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2231 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2232 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2234 client_initialize(client
);
2236 sd_dhcp_client_detach_event(client
);
2238 sd_dhcp_lease_unref(client
->lease
);
2240 set_free(client
->req_opts
);
2241 free(client
->hostname
);
2242 free(client
->vendor_class_identifier
);
2243 free(client
->mudurl
);
2244 client
->user_class
= strv_free(client
->user_class
);
2245 ordered_hashmap_free(client
->extra_options
);
2246 ordered_hashmap_free(client
->vendor_options
);
2247 free(client
->ifname
);
2248 return mfree(client
);
2251 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2253 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2254 const uint8_t *opts
;
2258 assert_return(ret
, -EINVAL
);
2260 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2264 *client
= (sd_dhcp_client
) {
2266 .state
= DHCP_STATE_INIT
,
2269 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2270 .port
= DHCP_PORT_CLIENT
,
2271 .anonymize
= !!anonymize
,
2272 .max_attempts
= UINT64_MAX
,
2273 .ip_service_type
= -1,
2275 /* NOTE: this could be moved to a function. */
2277 n_opts
= ELEMENTSOF(default_req_opts_anonymize
);
2278 opts
= default_req_opts_anonymize
;
2280 n_opts
= ELEMENTSOF(default_req_opts
);
2281 opts
= default_req_opts
;
2284 for (size_t i
= 0; i
< n_opts
; i
++) {
2285 r
= sd_dhcp_client_set_request_option(client
, opts
[i
]);
2290 *ret
= TAKE_PTR(client
);