1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2013 Intel Corporation. All rights reserved.
6 #include <linux/if_infiniband.h>
7 #include <net/if_arp.h>
10 #include "sd-dhcp-client.h"
12 #include "alloc-util.h"
13 #include "device-util.h"
14 #include "dhcp-client-id-internal.h"
15 #include "dhcp-client-internal.h"
16 #include "dhcp-lease-internal.h"
17 #include "dhcp-network.h"
18 #include "dhcp-option.h"
19 #include "dhcp-packet.h"
20 #include "dns-domain.h"
21 #include "errno-util.h"
22 #include "ether-addr-util.h"
23 #include "event-util.h"
25 #include "hostname-util.h"
26 #include "iovec-util.h"
27 #include "memory-util.h"
28 #include "network-common.h"
29 #include "random-util.h"
31 #include "socket-util.h"
32 #include "sort-util.h"
33 #include "string-table.h"
34 #include "string-util.h"
36 #include "time-util.h"
39 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
41 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
42 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
44 #define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
45 * transient failure. */
47 struct sd_dhcp_client
{
53 sd_event_source
*timeout_resend
;
63 union sockaddr_union link
;
64 sd_event_source
*receive_message
;
65 bool request_broadcast
;
70 struct hw_addr_data hw_addr
;
71 struct hw_addr_data bcast_addr
;
73 sd_dhcp_client_id client_id
;
75 char *vendor_class_identifier
;
79 usec_t fallback_lease_lifetime
;
85 uint64_t discover_attempt
;
86 uint64_t request_attempt
;
87 uint64_t max_discover_attempts
;
88 uint64_t max_request_attempts
;
89 OrderedHashmap
*extra_options
;
90 OrderedHashmap
*vendor_options
;
91 sd_event_source
*timeout_t1
;
92 sd_event_source
*timeout_t2
;
93 sd_event_source
*timeout_expire
;
94 sd_event_source
*timeout_ipv6_only_mode
;
95 sd_dhcp_client_callback_t callback
;
97 sd_dhcp_client_callback_t state_callback
;
103 bool socket_priority_set
;
108 static const uint8_t default_req_opts
[] = {
109 SD_DHCP_OPTION_SUBNET_MASK
,
110 SD_DHCP_OPTION_ROUTER
,
111 SD_DHCP_OPTION_HOST_NAME
,
112 SD_DHCP_OPTION_DOMAIN_NAME
,
113 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
116 /* RFC7844 section 3:
117 MAY contain the Parameter Request List option.
119 The client intending to protect its privacy SHOULD only request a
120 minimal number of options in the PRL and SHOULD also randomly shuffle
121 the ordering of option codes in the PRL. If this random ordering
122 cannot be implemented, the client MAY order the option codes in the
123 PRL by option code number (lowest to highest).
125 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
126 static const uint8_t default_req_opts_anonymize
[] = {
127 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
128 SD_DHCP_OPTION_ROUTER
, /* 3 */
129 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
130 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
131 SD_DHCP_OPTION_ROUTER_DISCOVERY
, /* 31 */
132 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
133 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
134 SD_DHCP_OPTION_NETBIOS_NAME_SERVER
, /* 44 */
135 SD_DHCP_OPTION_NETBIOS_NODE_TYPE
, /* 46 */
136 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
137 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
138 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
139 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
142 static int client_receive_message_raw(
147 static int client_receive_message_udp(
152 static void client_stop(sd_dhcp_client
*client
, int error
);
153 static int client_restart(sd_dhcp_client
*client
);
155 int dhcp_client_set_state_callback(
156 sd_dhcp_client
*client
,
157 sd_dhcp_client_callback_t cb
,
160 assert_return(client
, -EINVAL
);
162 client
->state_callback
= cb
;
163 client
->state_userdata
= userdata
;
168 int sd_dhcp_client_set_callback(
169 sd_dhcp_client
*client
,
170 sd_dhcp_client_callback_t cb
,
173 assert_return(client
, -EINVAL
);
175 client
->callback
= cb
;
176 client
->userdata
= userdata
;
181 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
182 assert_return(client
, -EINVAL
);
183 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
185 client
->request_broadcast
= broadcast
;
190 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
191 assert_return(client
, -EINVAL
);
192 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
196 case SD_DHCP_OPTION_PAD
:
197 case SD_DHCP_OPTION_OVERLOAD
:
198 case SD_DHCP_OPTION_MESSAGE_TYPE
:
199 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
200 case SD_DHCP_OPTION_END
:
207 return set_ensure_put(&client
->req_opts
, NULL
, UINT8_TO_PTR(option
));
210 static int client_request_contains(sd_dhcp_client
*client
, uint8_t option
) {
213 return set_contains(client
->req_opts
, UINT8_TO_PTR(option
));
216 int sd_dhcp_client_set_request_address(
217 sd_dhcp_client
*client
,
218 const struct in_addr
*last_addr
) {
220 assert_return(client
, -EINVAL
);
221 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
224 client
->last_addr
= last_addr
->s_addr
;
226 client
->last_addr
= INADDR_ANY
;
231 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
232 assert_return(client
, -EINVAL
);
233 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
234 assert_return(ifindex
> 0, -EINVAL
);
236 client
->ifindex
= ifindex
;
240 int sd_dhcp_client_set_ifname(sd_dhcp_client
*client
, const char *ifname
) {
241 assert_return(client
, -EINVAL
);
242 assert_return(ifname
, -EINVAL
);
244 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
247 return free_and_strdup(&client
->ifname
, ifname
);
250 int sd_dhcp_client_get_ifname(sd_dhcp_client
*client
, const char **ret
) {
253 assert_return(client
, -EINVAL
);
255 r
= get_ifname(client
->ifindex
, &client
->ifname
);
260 *ret
= client
->ifname
;
265 int sd_dhcp_client_set_mac(
266 sd_dhcp_client
*client
,
267 const uint8_t *hw_addr
,
268 const uint8_t *bcast_addr
,
272 assert_return(client
, -EINVAL
);
273 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
274 assert_return(IN_SET(arp_type
, ARPHRD_ETHER
, ARPHRD_INFINIBAND
, ARPHRD_RAWIP
, ARPHRD_NONE
), -EINVAL
);
276 static const uint8_t default_eth_bcast
[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
277 default_eth_hwaddr
[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
282 /* Linux cellular modem drivers (e.g. qmi_wwan) present a
283 * network interface of type ARPHRD_RAWIP(519) or
284 * ARPHRD_NONE(65534) when in point-to-point mode, but these
285 * are not valid DHCP hardware-type values.
287 * Apparently, it's best to just pretend that these are ethernet
288 * devices. Other approaches have been tried, but resulted in
289 * incompatibilities with some server software. See
290 * https://lore.kernel.org/netdev/cover.1228948072.git.inaky@linux.intel.com/
292 arp_type
= ARPHRD_ETHER
;
294 assert_cc(sizeof(default_eth_hwaddr
) == ETH_ALEN
);
295 assert_cc(sizeof(default_eth_bcast
) == ETH_ALEN
);
296 hw_addr
= default_eth_hwaddr
;
297 bcast_addr
= default_eth_bcast
;
303 assert_return(IN_SET(arp_type
, ARPHRD_ETHER
, ARPHRD_INFINIBAND
), -EINVAL
);
304 assert_return(hw_addr
, -EINVAL
);
305 assert_return(addr_len
== (arp_type
== ARPHRD_ETHER
? ETH_ALEN
: INFINIBAND_ALEN
), -EINVAL
);
307 client
->arp_type
= arp_type
;
308 hw_addr_set(&client
->hw_addr
, hw_addr
, addr_len
);
309 hw_addr_set(&client
->bcast_addr
, bcast_addr
, bcast_addr
? addr_len
: 0);
314 int sd_dhcp_client_get_client_id(sd_dhcp_client
*client
, const sd_dhcp_client_id
**ret
) {
315 assert_return(client
, -EINVAL
);
316 assert_return(ret
, -EINVAL
);
318 if (!sd_dhcp_client_id_is_set(&client
->client_id
))
321 *ret
= &client
->client_id
;
325 int sd_dhcp_client_set_client_id(
326 sd_dhcp_client
*client
,
331 assert_return(client
, -EINVAL
);
332 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
333 assert_return(data
, -EINVAL
);
334 assert_return(client_id_data_size_is_valid(data_len
), -EINVAL
);
336 /* For hardware types, log debug message about unexpected data length.
338 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
339 * the last 8 bytes of the address are stable and suitable to put into
340 * the client-id. The caller is advised to account for that. */
341 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
342 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
343 log_dhcp_client(client
,
344 "Changing client ID to hardware type %u with unexpected address length %zu",
347 return sd_dhcp_client_id_set(&client
->client_id
, type
, data
, data_len
);
350 static int dhcp_client_set_iaid_duid(
351 sd_dhcp_client
*client
,
354 sd_dhcp_duid
*duid
) {
359 r
= dhcp_identifier_set_iaid(client
->dev
, &client
->hw_addr
,
360 /* legacy_unstable_byteorder = */ true,
365 iaid
= be32toh(iaid
);
368 return sd_dhcp_client_id_set_iaid_duid(&client
->client_id
, iaid
, duid
);
371 int sd_dhcp_client_set_iaid_duid_llt(
372 sd_dhcp_client
*client
,
380 assert_return(client
, -EINVAL
);
381 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
383 r
= sd_dhcp_duid_set_llt(&duid
, client
->hw_addr
.bytes
, client
->hw_addr
.length
, client
->arp_type
, llt_time
);
387 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
390 int sd_dhcp_client_set_iaid_duid_ll(
391 sd_dhcp_client
*client
,
398 assert_return(client
, -EINVAL
);
399 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
401 r
= sd_dhcp_duid_set_ll(&duid
, client
->hw_addr
.bytes
, client
->hw_addr
.length
, client
->arp_type
);
405 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
408 int sd_dhcp_client_set_iaid_duid_en(
409 sd_dhcp_client
*client
,
416 assert_return(client
, -EINVAL
);
417 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
419 r
= sd_dhcp_duid_set_en(&duid
);
423 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
426 int sd_dhcp_client_set_iaid_duid_uuid(
427 sd_dhcp_client
*client
,
434 assert_return(client
, -EINVAL
);
435 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
437 r
= sd_dhcp_duid_set_uuid(&duid
);
441 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
444 int sd_dhcp_client_set_iaid_duid_raw(
445 sd_dhcp_client
*client
,
449 const uint8_t *duid_data
,
450 size_t duid_data_len
) {
455 assert_return(client
, -EINVAL
);
456 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
457 assert_return(duid_data
|| duid_data_len
== 0, -EINVAL
);
459 r
= sd_dhcp_duid_set(&duid
, duid_type
, duid_data
, duid_data_len
);
463 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
466 int sd_dhcp_client_set_rapid_commit(sd_dhcp_client
*client
, bool rapid_commit
) {
467 assert_return(client
, -EINVAL
);
469 client
->rapid_commit
= !client
->anonymize
&& rapid_commit
;
473 int sd_dhcp_client_set_hostname(
474 sd_dhcp_client
*client
,
475 const char *hostname
) {
477 assert_return(client
, -EINVAL
);
478 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
480 /* Make sure hostnames qualify as DNS and as Linux hostnames */
482 !(hostname_is_valid(hostname
, 0) && dns_name_is_valid(hostname
) > 0))
485 return free_and_strdup(&client
->hostname
, hostname
);
488 int sd_dhcp_client_set_vendor_class_identifier(
489 sd_dhcp_client
*client
,
492 assert_return(client
, -EINVAL
);
493 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
495 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
498 int sd_dhcp_client_set_mud_url(
499 sd_dhcp_client
*client
,
500 const char *mudurl
) {
502 assert_return(client
, -EINVAL
);
503 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
504 assert_return(mudurl
, -EINVAL
);
505 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
506 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
508 return free_and_strdup(&client
->mudurl
, mudurl
);
511 int sd_dhcp_client_set_user_class(
512 sd_dhcp_client
*client
,
513 char * const *user_class
) {
517 assert_return(client
, -EINVAL
);
518 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
519 assert_return(!strv_isempty(user_class
), -EINVAL
);
521 STRV_FOREACH(p
, user_class
) {
522 size_t n
= strlen(*p
);
524 if (n
> 255 || n
== 0)
528 s
= strv_copy(user_class
);
532 return strv_free_and_replace(client
->user_class
, s
);
535 int sd_dhcp_client_set_client_port(
536 sd_dhcp_client
*client
,
539 assert_return(client
, -EINVAL
);
540 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
547 int sd_dhcp_client_set_port(
548 sd_dhcp_client
*client
,
551 assert_return(client
, -EINVAL
);
552 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
554 client
->server_port
= port
;
559 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
560 assert_return(client
, -EINVAL
);
561 assert_return(mtu
>= DHCP_MIN_PACKET_SIZE
, -ERANGE
);
563 /* MTU may be changed by the acquired lease. Hence, we cannot require that the client is stopped here.
564 * Please do not add assertion for !sd_dhcp_client_is_running(client) here. */
571 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
572 assert_return(client
, -EINVAL
);
573 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
575 client
->max_discover_attempts
= max_attempts
;
580 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
583 assert_return(client
, -EINVAL
);
584 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
585 assert_return(v
, -EINVAL
);
587 r
= ordered_hashmap_ensure_put(&client
->extra_options
, &dhcp_option_hash_ops
, UINT_TO_PTR(v
->option
), v
);
591 sd_dhcp_option_ref(v
);
595 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
598 assert_return(client
, -EINVAL
);
599 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
600 assert_return(v
, -EINVAL
);
602 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
606 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
610 sd_dhcp_option_ref(v
);
615 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
616 assert_return(client
, -EINVAL
);
619 return -EADDRNOTAVAIL
;
622 *ret
= client
->lease
;
627 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
628 assert_return(client
, -EINVAL
);
629 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
631 client
->ip_service_type
= type
;
636 int sd_dhcp_client_set_socket_priority(sd_dhcp_client
*client
, int socket_priority
) {
637 assert_return(client
, -EINVAL
);
638 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
640 client
->socket_priority_set
= true;
641 client
->socket_priority
= socket_priority
;
646 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint64_t fallback_lease_lifetime
) {
647 assert_return(client
, -EINVAL
);
648 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
649 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
651 assert_cc(sizeof(usec_t
) == sizeof(uint64_t));
652 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
657 int sd_dhcp_client_set_bootp(sd_dhcp_client
*client
, int bootp
) {
658 assert_return(client
, -EINVAL
);
659 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
661 client
->bootp
= bootp
;
666 static void client_set_state(sd_dhcp_client
*client
, DHCPState state
) {
669 if (client
->state
== state
)
672 log_dhcp_client(client
, "State changed: %s -> %s",
673 dhcp_state_to_string(client
->state
), dhcp_state_to_string(state
));
675 client
->state
= state
;
677 if (client
->state_callback
)
678 client
->state_callback(client
, state
, client
->state_userdata
);
681 int dhcp_client_get_state(sd_dhcp_client
*client
) {
682 assert_return(client
, -EINVAL
);
684 return client
->state
;
687 static int client_notify(sd_dhcp_client
*client
, int event
) {
690 if (client
->callback
)
691 return client
->callback(client
, event
, client
->userdata
);
696 static int client_initialize(sd_dhcp_client
*client
) {
697 assert_return(client
, -EINVAL
);
699 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
701 client
->fd
= safe_close(client
->fd
);
703 (void) event_source_disable(client
->timeout_resend
);
704 (void) event_source_disable(client
->timeout_t1
);
705 (void) event_source_disable(client
->timeout_t2
);
706 (void) event_source_disable(client
->timeout_expire
);
707 (void) event_source_disable(client
->timeout_ipv6_only_mode
);
709 client
->discover_attempt
= 0;
710 client
->request_attempt
= 0;
712 client_set_state(client
, DHCP_STATE_STOPPED
);
715 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
720 static void client_stop(sd_dhcp_client
*client
, int error
) {
722 DHCP_CLIENT_DONT_DESTROY(client
);
724 if (sd_dhcp_client_is_running(client
)) {
726 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
727 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
728 log_dhcp_client(client
, "STOPPED");
730 log_dhcp_client(client
, "STOPPED: Unknown event");
732 client_notify(client
, error
);
733 } else if (error
< 0) {
734 log_dhcp_client_errno(client
, error
, "FAILED: %m");
735 client_notify(client
, error
);
738 client_initialize(client
);
741 /* RFC2131 section 4.1:
742 * retransmission delays should include -1 to +1 sec of random 'fuzz'. */
743 #define RFC2131_RANDOM_FUZZ \
744 ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
746 /* RFC2131 section 4.1:
747 * for retransmission delays, timeout should start at 4s then double
748 * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
749 * This assumes the first call will be using attempt 1. */
750 static usec_t
client_compute_request_timeout(uint64_t attempt
) {
751 usec_t timeout
= (UINT64_C(1) << MIN(attempt
+ 1, UINT64_C(6))) * USEC_PER_SEC
;
752 return usec_sub_signed(timeout
, RFC2131_RANDOM_FUZZ
);
755 /* RFC2131 section 4.4.5:
756 * T1 defaults to (0.5 * duration_of_lease).
757 * T2 defaults to (0.875 * duration_of_lease). */
758 #define T1_DEFAULT(lifetime) ((lifetime) / 2)
759 #define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
761 /* RFC2131 section 4.4.5:
762 * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
763 * and one-half of the remaining lease time (in REBINDING state), down to a minimum
765 * Note that while the default T1/T2 initial times do have random 'fuzz' applied,
766 * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
767 static usec_t
client_compute_reacquisition_timeout(usec_t now_usec
, usec_t expire
) {
768 return MAX(usec_sub_unsigned(expire
, now_usec
) / 2, 60 * USEC_PER_SEC
);
771 static int cmp_uint8(const uint8_t *a
, const uint8_t *b
) {
775 static int client_message_init(
776 sd_dhcp_client
*client
,
778 DHCPPacket
**ret_packet
,
780 size_t *ret_optoffset
) {
782 _cleanup_free_ DHCPPacket
*packet
= NULL
;
783 size_t optlen
, optoffset
, size
;
789 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
792 assert(ret_optoffset
);
794 optlen
= DHCP_MIN_OPTIONS_SIZE
;
795 size
= sizeof(DHCPPacket
) + optlen
;
797 packet
= malloc0(size
);
801 /* BOOTP supports options, but only DHCP_OPTION_END is used. The rest of the 64-byte buffer
802 * is set to zero, per RFC1542. Allow for this by initialaizing optoffset to 0. */
804 r
= bootp_message_init(
805 &packet
->dhcp
, BOOTREQUEST
, client
->xid
, client
->arp_type
,
806 client
->hw_addr
.length
, client
->hw_addr
.bytes
);
808 r
= dhcp_message_init(
809 &packet
->dhcp
, BOOTREQUEST
, client
->xid
, client
->arp_type
,
810 client
->hw_addr
.length
, client
->hw_addr
.bytes
,
811 type
, optlen
, &optoffset
);
815 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
816 refuse to issue an DHCP lease if 'secs' is set to zero */
817 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
820 assert(time_now
>= client
->start_time
);
822 /* seconds between sending first and last DISCOVER
823 * must always be strictly positive to deal with broken servers */
824 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ?: 1;
825 packet
->dhcp
.secs
= htobe16(secs
);
827 /* RFC2131 section 4.1
828 A client that cannot receive unicast IP datagrams until its protocol
829 software has been configured with an IP address SHOULD set the
830 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
831 DHCPREQUEST messages that client sends. The BROADCAST bit will
832 provide a hint to the DHCP server and BOOTP relay agent to broadcast
833 any messages to the client on the client's subnet.
835 Note: some interfaces needs this to be enabled, but some networks
836 needs this to be disabled as broadcasts are filteretd, so this
837 needs to be configurable */
838 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
839 packet
->dhcp
.flags
= htobe16(0x8000);
842 *ret_optlen
= optlen
;
843 *ret_optoffset
= optoffset
;
844 *ret_packet
= TAKE_PTR(packet
);
848 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
849 Identifier option is not set */
850 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
851 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
852 client
->client_id
.size
,
853 client
->client_id
.raw
);
857 /* RFC2131 section 3.5:
858 in its initial DHCPDISCOVER or DHCPREQUEST message, a
859 client may provide the server with a list of specific
860 parameters the client is interested in. If the client
861 includes a list of parameters in a DHCPDISCOVER message,
862 it MUST include that list in any subsequent DHCPREQUEST
866 /* RFC7844 section 3:
867 MAY contain the Parameter Request List option. */
868 /* NOTE: in case that there would be an option to do not send
869 * any PRL at all, the size should be checked before sending */
870 if (!set_isempty(client
->req_opts
) && type
!= DHCP_RELEASE
) {
871 _cleanup_free_
uint8_t *opts
= NULL
;
872 size_t n_opts
, i
= 0;
875 n_opts
= set_size(client
->req_opts
);
876 opts
= new(uint8_t, n_opts
);
880 SET_FOREACH(val
, client
->req_opts
)
881 opts
[i
++] = PTR_TO_UINT8(val
);
884 /* For anonymizing the request, let's sort the options. */
885 typesafe_qsort(opts
, n_opts
, cmp_uint8
);
887 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
888 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
894 /* RFC2131 section 3.5:
895 The client SHOULD include the ’maximum DHCP message size’ option to
896 let the server know how large the server may make its DHCP messages.
898 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
899 than the defined default size unless the Maximum Message Size option
902 RFC3442 "Requirements to Avoid Sizing Constraints":
903 Because a full routing table can be quite large, the standard 576
904 octet maximum size for a DHCP message may be too short to contain
905 some legitimate Classless Static Route options. Because of this,
906 clients implementing the Classless Static Route option SHOULD send a
907 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
908 stack is capable of receiving larger IP datagrams. In this case, the
909 client SHOULD set the value of this option to at least the MTU of the
910 interface that the client is configuring. The client MAY set the
911 value of this option higher, up to the size of the largest UDP packet
912 it is prepared to accept. (Note that the value specified in the
913 Maximum DHCP Message Size option is the total maximum packet size,
914 including IP and UDP headers.)
916 /* RFC7844 section 3:
917 SHOULD NOT contain any other option. */
918 if (!client
->anonymize
&& IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
)) {
919 be16_t max_size
= htobe16(MIN(client
->mtu
- DHCP_IP_UDP_SIZE
, (uint32_t) UINT16_MAX
));
920 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
921 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
927 *ret_optlen
= optlen
;
928 *ret_optoffset
= optoffset
;
929 *ret_packet
= TAKE_PTR(packet
);
934 static int client_append_fqdn_option(
935 DHCPMessage
*message
,
940 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
943 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
944 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
945 buffer
[1] = 0; /* RCODE1 (deprecated) */
946 buffer
[2] = 0; /* RCODE2 (deprecated) */
948 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
950 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
951 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
956 static int dhcp_client_send_raw(
957 sd_dhcp_client
*client
,
961 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
962 INADDR_BROADCAST
, client
->server_port
, len
, client
->ip_service_type
);
964 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
968 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
974 if (client
->hostname
) {
975 /* According to RFC 4702 "clients that send the Client FQDN option in
976 their messages MUST NOT also send the Host Name option". Just send
977 one of the two depending on the hostname type.
979 if (dns_name_is_single_label(client
->hostname
)) {
980 /* it is unclear from RFC 2131 if client should send hostname in
981 DHCPDISCOVER but dhclient does and so we do as well
983 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
984 SD_DHCP_OPTION_HOST_NAME
,
985 strlen(client
->hostname
), client
->hostname
);
987 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
993 if (client
->vendor_class_identifier
) {
994 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
995 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
996 strlen(client
->vendor_class_identifier
),
997 client
->vendor_class_identifier
);
1002 if (client
->mudurl
) {
1003 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1004 SD_DHCP_OPTION_MUD_URL
,
1005 strlen(client
->mudurl
),
1011 if (client
->user_class
) {
1012 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1013 SD_DHCP_OPTION_USER_CLASS
,
1014 strv_length(client
->user_class
),
1015 client
->user_class
);
1020 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
) {
1021 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1022 j
->option
, j
->length
, j
->data
);
1027 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
1028 r
= dhcp_option_append(
1029 &packet
->dhcp
, optlen
, optoffset
, 0,
1030 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
1031 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
1039 static int client_send_dhcp_discover(sd_dhcp_client
*client
) {
1040 _cleanup_free_ DHCPPacket
*discover
= NULL
;
1041 size_t optoffset
, optlen
;
1045 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
1047 r
= client_message_init(client
, DHCP_DISCOVER
, &discover
, &optlen
, &optoffset
);
1051 /* the client may suggest values for the network address
1052 and lease time in the DHCPDISCOVER message. The client may include
1053 the ’requested IP address’ option to suggest that a particular IP
1054 address be assigned, and may include the ’IP address lease time’
1055 option to suggest the lease time it would like.
1057 /* RFC7844 section 3:
1058 SHOULD NOT contain any other option. */
1059 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
1060 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1061 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1062 4, &client
->last_addr
);
1067 if (client
->rapid_commit
) {
1068 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1069 SD_DHCP_OPTION_RAPID_COMMIT
, 0, NULL
);
1074 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
1078 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1079 SD_DHCP_OPTION_END
, 0, NULL
);
1083 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1087 log_dhcp_client(client
, "DISCOVER");
1092 static int client_send_bootp_discover(sd_dhcp_client
*client
) {
1093 _cleanup_free_ DHCPPacket
*discover
= NULL
;
1094 size_t optoffset
, optlen
;
1098 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
1100 r
= client_message_init(client
, DHCP_DISCOVER
, &discover
, &optlen
, &optoffset
);
1104 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
1108 /* RFC1542 section 3.5:
1109 * if the client has no information to communicate to the server, the octet immediately following the
1110 * magic cookie SHOULD be set to the "End" tag (255) and the remaining octets of the 'vend' field
1111 * SHOULD be set to zero.
1113 * Use this RFC, along with the fact that some BOOTP servers require a 64-byte vend field, to suggest
1114 * that we always zero and send 64 bytes in the options field. The first four bites are the "magic"
1115 * field, so this only needs to add 60 bytes. */
1116 if (optoffset
< 60 && optlen
>= 60) {
1117 memzero(&discover
->dhcp
.options
[optoffset
], optlen
- optoffset
);
1121 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1125 log_dhcp_client(client
, "DISCOVER");
1129 static int client_send_request(sd_dhcp_client
*client
) {
1130 _cleanup_free_ DHCPPacket
*request
= NULL
;
1131 size_t optoffset
, optlen
;
1135 assert(!client
->bootp
);
1137 r
= client_message_init(client
, DHCP_REQUEST
, &request
, &optlen
, &optoffset
);
1141 switch (client
->state
) {
1142 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1143 SELECTING should be REQUESTING)
1146 case DHCP_STATE_REQUESTING
:
1147 /* Client inserts the address of the selected server in ’server
1148 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1149 filled in with the yiaddr value from the chosen DHCPOFFER.
1152 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1153 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1154 4, &client
->lease
->server_address
);
1158 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1159 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1160 4, &client
->lease
->address
);
1166 case DHCP_STATE_INIT_REBOOT
:
1167 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1168 option MUST be filled in with client’s notion of its previously
1169 assigned address. ’ciaddr’ MUST be zero.
1171 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1172 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1173 4, &client
->last_addr
);
1178 case DHCP_STATE_RENEWING
:
1179 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1180 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1181 client’s IP address.
1184 case DHCP_STATE_REBINDING
:
1185 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1186 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1187 client’s IP address.
1189 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1191 request
->dhcp
.ciaddr
= client
->lease
->address
;
1195 case DHCP_STATE_INIT
:
1196 case DHCP_STATE_SELECTING
:
1197 case DHCP_STATE_REBOOTING
:
1198 case DHCP_STATE_BOUND
:
1199 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
,
1216 client
->server_port
,
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)");
1249 static int client_start(sd_dhcp_client
*client
);
1251 static int client_timeout_resend(
1256 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1257 DHCP_CLIENT_DONT_DESTROY(client
);
1258 usec_t time_now
, next_timeout
;
1262 assert(client
->event
);
1264 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
1268 switch (client
->state
) {
1270 case DHCP_STATE_RENEWING
:
1271 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->t2_time
);
1274 case DHCP_STATE_REBINDING
:
1275 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->expire_time
);
1278 case DHCP_STATE_REBOOTING
:
1279 /* start over as we did not receive a timely ack or nak */
1280 r
= client_initialize(client
);
1284 r
= client_start(client
);
1288 log_dhcp_client(client
, "REBOOTED");
1291 case DHCP_STATE_INIT
:
1292 case DHCP_STATE_INIT_REBOOT
:
1293 case DHCP_STATE_SELECTING
:
1294 if (client
->discover_attempt
>= client
->max_discover_attempts
)
1297 client
->discover_attempt
++;
1298 next_timeout
= client_compute_request_timeout(client
->discover_attempt
);
1300 case DHCP_STATE_REQUESTING
:
1301 case DHCP_STATE_BOUND
:
1302 if (client
->request_attempt
>= client
->max_request_attempts
)
1305 client
->request_attempt
++;
1306 next_timeout
= client_compute_request_timeout(client
->request_attempt
);
1309 case DHCP_STATE_STOPPED
:
1314 assert_not_reached();
1317 r
= event_reset_time_relative(
1318 client
->event
, &client
->timeout_resend
,
1319 CLOCK_BOOTTIME
, next_timeout
, 10 * USEC_PER_MSEC
,
1320 client_timeout_resend
, client
,
1321 client
->event_priority
, "dhcp4-resend-timer", true);
1325 switch (client
->state
) {
1326 case DHCP_STATE_INIT
:
1328 r
= client_send_bootp_discover(client
);
1330 r
= client_send_dhcp_discover(client
);
1332 client_set_state(client
, DHCP_STATE_SELECTING
);
1333 client
->discover_attempt
= 0;
1334 } else if (client
->discover_attempt
>= client
->max_discover_attempts
)
1338 case DHCP_STATE_SELECTING
:
1340 r
= client_send_bootp_discover(client
);
1342 r
= client_send_dhcp_discover(client
);
1343 if (r
< 0 && client
->discover_attempt
>= client
->max_discover_attempts
)
1347 case DHCP_STATE_INIT_REBOOT
:
1348 case DHCP_STATE_REQUESTING
:
1349 case DHCP_STATE_RENEWING
:
1350 case DHCP_STATE_REBINDING
:
1351 r
= client_send_request(client
);
1352 if (r
< 0 && client
->request_attempt
>= client
->max_request_attempts
)
1355 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1356 client_set_state(client
, DHCP_STATE_REBOOTING
);
1359 case DHCP_STATE_REBOOTING
:
1360 case DHCP_STATE_BOUND
:
1363 case DHCP_STATE_STOPPED
:
1369 if (client
->discover_attempt
>= TRANSIENT_FAILURE_ATTEMPTS
)
1370 client_notify(client
, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE
);
1375 /* Avoid REQUEST infinite loop. Per RFC 2131 section 3.1.5: if the client receives
1376 neither a DHCPACK or a DHCPNAK message after employing the retransmission algorithm,
1377 the client reverts to INIT state and restarts the initialization process */
1378 if (client
->request_attempt
>= client
->max_request_attempts
) {
1379 log_dhcp_client(client
, "Max REQUEST attempts reached. Restarting...");
1380 client_restart(client
);
1383 client_stop(client
, r
);
1385 /* Errors were dealt with when stopping the client, don't spill
1386 errors into the event loop handler */
1390 static int client_initialize_io_events(
1391 sd_dhcp_client
*client
,
1392 sd_event_io_handler_t io_callback
) {
1397 assert(client
->event
);
1399 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1400 client
->fd
, EPOLLIN
, io_callback
,
1405 r
= sd_event_source_set_priority(client
->receive_message
,
1406 client
->event_priority
);
1410 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1416 client_stop(client
, r
);
1421 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1426 assert(client
->event
);
1428 (void) event_source_disable(client
->timeout_ipv6_only_mode
);
1430 if (client
->start_delay
> 0) {
1431 assert_se(sd_event_now(client
->event
, CLOCK_BOOTTIME
, &usec
) >= 0);
1432 usec
= usec_add(usec
, client
->start_delay
);
1435 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1438 client_timeout_resend
, client
,
1439 client
->event_priority
, "dhcp4-resend-timer", true);
1441 client_stop(client
, r
);
1446 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1447 client_initialize_io_events(client
, io_callback
);
1448 client_initialize_time_events(client
);
1453 static int client_start_delayed(sd_dhcp_client
*client
) {
1456 assert_return(client
, -EINVAL
);
1457 assert_return(client
->event
, -EINVAL
);
1458 assert_return(client
->ifindex
> 0, -EINVAL
);
1459 assert_return(client
->fd
< 0, -EBUSY
);
1460 assert_return(client
->xid
== 0, -EINVAL
);
1461 assert_return(IN_SET(client
->state
, DHCP_STATE_STOPPED
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1463 client
->xid
= random_u32();
1465 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1466 &client
->hw_addr
, &client
->bcast_addr
,
1467 client
->arp_type
, client
->port
,
1468 client
->socket_priority_set
, client
->socket_priority
);
1470 client_stop(client
, r
);
1475 client
->start_time
= now(CLOCK_BOOTTIME
);
1477 if (client
->state
== DHCP_STATE_STOPPED
)
1478 client
->state
= DHCP_STATE_INIT
;
1480 return client_initialize_events(client
, client_receive_message_raw
);
1483 static int client_start(sd_dhcp_client
*client
) {
1484 client
->start_delay
= 0;
1485 return client_start_delayed(client
);
1488 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1489 sd_dhcp_client
*client
= userdata
;
1490 DHCP_CLIENT_DONT_DESTROY(client
);
1492 log_dhcp_client(client
, "EXPIRED");
1494 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1496 /* lease was lost, start over if not freed or stopped in callback */
1497 if (client
->state
!= DHCP_STATE_STOPPED
) {
1498 client_initialize(client
);
1499 client_start(client
);
1505 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1506 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1507 DHCP_CLIENT_DONT_DESTROY(client
);
1510 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
1511 client
->fd
= safe_close(client
->fd
);
1513 client_set_state(client
, DHCP_STATE_REBINDING
);
1514 client
->discover_attempt
= 0;
1515 client
->request_attempt
= 0;
1517 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1518 &client
->hw_addr
, &client
->bcast_addr
,
1519 client
->arp_type
, client
->port
,
1520 client
->socket_priority_set
, client
->socket_priority
);
1522 client_stop(client
, r
);
1527 return client_initialize_events(client
, client_receive_message_raw
);
1530 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1531 sd_dhcp_client
*client
= userdata
;
1532 DHCP_CLIENT_DONT_DESTROY(client
);
1535 client_set_state(client
, DHCP_STATE_RENEWING
);
1536 else if (client
->state
!= DHCP_STATE_INIT
)
1537 client_set_state(client
, DHCP_STATE_INIT_REBOOT
);
1538 client
->discover_attempt
= 0;
1539 client
->request_attempt
= 0;
1541 return client_initialize_time_events(client
);
1544 static int dhcp_option_parse_and_verify(
1545 sd_dhcp_client
*client
,
1546 DHCPMessage
*message
,
1548 sd_dhcp_lease
*lease
) {
1550 _cleanup_free_
char *error_message
= NULL
;
1557 r
= dhcp_option_parse(message
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1559 return log_dhcp_client_errno(client
, r
, "Failed to parse DHCP options, ignoring: %m");
1561 switch (client
->state
) {
1562 case DHCP_STATE_SELECTING
:
1563 if (r
== DHCP_ACK
) {
1564 if (!client
->rapid_commit
)
1565 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1566 "received unexpected ACK, ignoring.");
1567 if (!lease
->rapid_commit
)
1568 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1569 "received rapid ACK without Rapid Commit option, ignoring.");
1570 } else if (r
== DHCP_OFFER
) {
1571 if (lease
->rapid_commit
) {
1572 /* Some RFC incompliant servers provides an OFFER with a rapid commit option.
1573 * See https://github.com/systemd/systemd/issues/29904.
1574 * Let's support such servers gracefully. */
1575 log_dhcp_client(client
, "received OFFER with Rapid Commit option, ignoring.");
1576 lease
->rapid_commit
= false;
1578 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1579 lease
->lifetime
= client
->fallback_lease_lifetime
;
1581 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1582 "received unexpected message, ignoring.");
1586 case DHCP_STATE_REBOOTING
:
1587 case DHCP_STATE_REQUESTING
:
1588 case DHCP_STATE_RENEWING
:
1589 case DHCP_STATE_REBINDING
:
1590 if (r
== DHCP_NAK
) {
1591 if (client
->lease
&& client
->lease
->server_address
!= lease
->server_address
)
1592 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1593 "NAK from unexpected server, ignoring: %s",
1594 strna(error_message
));
1595 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EADDRNOTAVAIL
),
1596 "NAK: %s", strna(error_message
));
1599 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1600 "received message was not an ACK, ignoring.");
1604 assert_not_reached();
1607 lease
->next_server
= message
->siaddr
;
1608 lease
->address
= message
->yiaddr
;
1610 if (lease
->address
== 0 ||
1611 lease
->server_address
== 0 ||
1612 lease
->lifetime
== 0)
1613 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1614 "received lease lacks address, server address or lease lifetime, ignoring.");
1619 static int bootp_option_parse_and_verify(
1620 sd_dhcp_client
*client
,
1621 DHCPMessage
*message
,
1623 sd_dhcp_lease
*lease
) {
1631 r
= dhcp_option_parse(message
, len
, dhcp_lease_parse_options
, lease
, /* ret_error_message = */ NULL
);
1633 r
= DHCP_ACK
; /* BOOTP messages don't have a DHCP message type option */
1635 return log_dhcp_client_errno(client
, r
, "Failed to parse BOOTP options, ignoring: %m");
1637 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
), "Received unexpected message, ignoring.");
1639 log_dhcp_client(client
, "BOOTP identified, using infinite lease. BOOTP siaddr=(%#x), DHCP Server Identifier=(%#x)",
1640 message
->siaddr
, lease
->server_address
);
1642 lease
->lifetime
= USEC_INFINITY
;
1643 lease
->address
= message
->yiaddr
;
1644 if (lease
->server_address
== 0)
1645 lease
->server_address
= message
->siaddr
;
1647 /* BOOTP protocol does not have any OFFER and REQUEST process. Hence, it is mostly equivalent to
1648 * Rapid Commit process in DHCP. */
1649 lease
->rapid_commit
= true;
1651 if (lease
->address
== 0)
1652 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
), "received lease lacks address, ignoring.");
1657 static int client_parse_message(
1658 sd_dhcp_client
*client
,
1659 DHCPMessage
*message
,
1661 sd_dhcp_lease
**ret
) {
1663 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1670 r
= dhcp_lease_new(&lease
);
1674 if (sd_dhcp_client_id_is_set(&client
->client_id
)) {
1675 r
= dhcp_lease_set_client_id(lease
, &client
->client_id
);
1681 r
= bootp_option_parse_and_verify(client
, message
, len
, lease
);
1683 r
= dhcp_option_parse_and_verify(client
, message
, len
, lease
);
1687 r
= dhcp_lease_set_default_subnet_mask(lease
);
1689 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1690 "received lease lacks subnet mask, and a fallback one cannot be generated, ignoring.");
1692 /* RFC 8925 section 3.2
1693 * If the client did not include the IPv6-Only Preferred option code in the Parameter Request List in
1694 * the DHCPDISCOVER or DHCPREQUEST message, it MUST ignore the IPv6-Only Preferred option in any
1695 * messages received from the server. */
1696 if (lease
->ipv6_only_preferred_usec
> 0 &&
1697 !client_request_contains(client
, SD_DHCP_OPTION_IPV6_ONLY_PREFERRED
)) {
1698 log_dhcp_client(client
, "Received message with unrequested IPv6-only preferred option, ignoring the option.");
1699 lease
->ipv6_only_preferred_usec
= 0;
1702 *ret
= TAKE_PTR(lease
);
1706 static int client_handle_offer_or_rapid_ack(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
, const triple_timestamp
*timestamp
) {
1707 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1713 r
= client_parse_message(client
, message
, len
, &lease
);
1717 dhcp_lease_set_timestamp(lease
, timestamp
);
1719 dhcp_lease_unref_and_replace(client
->lease
, lease
);
1721 if (client
->lease
->rapid_commit
) {
1722 log_dhcp_client(client
, "ACK");
1723 return SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1726 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1729 log_dhcp_client(client
, "OFFER");
1733 static int client_enter_requesting_now(sd_dhcp_client
*client
) {
1736 client_set_state(client
, DHCP_STATE_REQUESTING
);
1737 client
->discover_attempt
= 0;
1738 client
->request_attempt
= 0;
1740 return event_reset_time(client
->event
, &client
->timeout_resend
,
1741 CLOCK_BOOTTIME
, 0, 0,
1742 client_timeout_resend
, client
,
1743 client
->event_priority
, "dhcp4-resend-timer",
1744 /* force_reset = */ true);
1747 static int client_enter_requesting_delayed(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1748 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1749 DHCP_CLIENT_DONT_DESTROY(client
);
1752 r
= client_enter_requesting_now(client
);
1754 client_stop(client
, r
);
1759 static int client_enter_requesting(sd_dhcp_client
*client
) {
1761 assert(client
->lease
);
1763 (void) event_source_disable(client
->timeout_resend
);
1765 if (client
->lease
->ipv6_only_preferred_usec
> 0) {
1766 if (client
->ipv6_acquired
) {
1767 log_dhcp_client(client
,
1768 "Received an OFFER with IPv6-only preferred option, and the host already acquired IPv6 connectivity, stopping DHCPv4 client.");
1769 return sd_dhcp_client_stop(client
);
1772 log_dhcp_client(client
,
1773 "Received an OFFER with IPv6-only preferred option, delaying to send REQUEST with %s.",
1774 FORMAT_TIMESPAN(client
->lease
->ipv6_only_preferred_usec
, USEC_PER_SEC
));
1776 return event_reset_time_relative(client
->event
, &client
->timeout_ipv6_only_mode
,
1778 client
->lease
->ipv6_only_preferred_usec
, 0,
1779 client_enter_requesting_delayed
, client
,
1780 client
->event_priority
, "dhcp4-ipv6-only-mode-timer",
1781 /* force_reset = */ true);
1784 return client_enter_requesting_now(client
);
1787 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1790 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1791 if (r
!= DHCP_FORCERENEW
)
1795 log_dhcp_client(client
, "FORCERENEW");
1798 /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP
1799 * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW
1800 * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */
1801 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1802 "Received FORCERENEW, ignoring.");
1806 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1807 if (a
->address
!= b
->address
)
1810 if (a
->subnet_mask
!= b
->subnet_mask
)
1813 if (a
->router_size
!= b
->router_size
)
1816 for (size_t i
= 0; i
< a
->router_size
; i
++)
1817 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1823 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
, const triple_timestamp
*timestamp
) {
1824 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1830 r
= client_parse_message(client
, message
, len
, &lease
);
1834 dhcp_lease_set_timestamp(lease
, timestamp
);
1837 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1838 else if (lease_equal(client
->lease
, lease
))
1839 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1841 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1843 dhcp_lease_unref_and_replace(client
->lease
, lease
);
1845 log_dhcp_client(client
, "ACK");
1849 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1854 assert(client
->event
);
1855 assert(client
->lease
);
1856 assert(client
->lease
->lifetime
> 0);
1857 assert(triple_timestamp_is_set(&client
->lease
->timestamp
));
1859 /* don't set timers for infinite leases */
1860 if (client
->lease
->lifetime
== USEC_INFINITY
) {
1861 (void) event_source_disable(client
->timeout_t1
);
1862 (void) event_source_disable(client
->timeout_t2
);
1863 (void) event_source_disable(client
->timeout_expire
);
1868 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
1872 /* verify that 0 < t2 < lifetime */
1873 if (client
->lease
->t2
== 0 || client
->lease
->t2
>= client
->lease
->lifetime
)
1874 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1875 /* verify that 0 < t1 < lifetime */
1876 if (client
->lease
->t1
== 0 || client
->lease
->t1
>= client
->lease
->t2
)
1877 client
->lease
->t1
= T1_DEFAULT(client
->lease
->lifetime
);
1878 /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
1879 * could not evaluate to false if t1 >= t2; so setting t2 to T2_DEFAULT
1880 * guarantees t1 < t2. */
1881 if (client
->lease
->t1
>= client
->lease
->t2
)
1882 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1884 assert(client
->lease
->t1
> 0);
1885 assert(client
->lease
->t1
< client
->lease
->t2
);
1886 assert(client
->lease
->t2
< client
->lease
->lifetime
);
1888 r
= sd_dhcp_lease_get_lifetime_timestamp(client
->lease
, CLOCK_BOOTTIME
, &client
->expire_time
);
1891 r
= sd_dhcp_lease_get_t1_timestamp(client
->lease
, CLOCK_BOOTTIME
, &client
->t1_time
);
1894 r
= sd_dhcp_lease_get_t2_timestamp(client
->lease
, CLOCK_BOOTTIME
, &client
->t2_time
);
1898 /* RFC2131 section 4.4.5:
1899 * Times T1 and T2 SHOULD be chosen with some random "fuzz".
1900 * Since the RFC doesn't specify here the exact 'fuzz' to use,
1901 * we use the range from section 4.1: -1 to +1 sec. */
1902 client
->t1_time
= usec_sub_signed(client
->t1_time
, RFC2131_RANDOM_FUZZ
);
1903 client
->t2_time
= usec_sub_signed(client
->t2_time
, RFC2131_RANDOM_FUZZ
);
1905 /* after fuzzing, ensure t2 is still >= t1 */
1906 client
->t2_time
= MAX(client
->t1_time
, client
->t2_time
);
1908 /* arm lifetime timeout */
1909 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1911 client
->expire_time
, 10 * USEC_PER_MSEC
,
1912 client_timeout_expire
, client
,
1913 client
->event_priority
, "dhcp4-lifetime", true);
1917 /* don't arm earlier timeouts if this has already expired */
1918 if (client
->expire_time
<= time_now
)
1921 log_dhcp_client(client
, "lease expires in %s",
1922 FORMAT_TIMESPAN(client
->expire_time
- time_now
, USEC_PER_SEC
));
1924 /* arm T2 timeout */
1925 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1927 client
->t2_time
, 10 * USEC_PER_MSEC
,
1928 client_timeout_t2
, client
,
1929 client
->event_priority
, "dhcp4-t2-timeout", true);
1933 /* don't arm earlier timeout if this has already expired */
1934 if (client
->t2_time
<= time_now
)
1937 log_dhcp_client(client
, "T2 expires in %s",
1938 FORMAT_TIMESPAN(client
->t2_time
- time_now
, USEC_PER_SEC
));
1940 /* arm T1 timeout */
1941 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1943 client
->t1_time
, 10 * USEC_PER_MSEC
,
1944 client_timeout_t1
, client
,
1945 client
->event_priority
, "dhcp4-t1-timer", true);
1949 if (client
->t1_time
> time_now
)
1950 log_dhcp_client(client
, "T1 expires in %s",
1951 FORMAT_TIMESPAN(client
->t1_time
- time_now
, USEC_PER_SEC
));
1956 static int client_enter_bound_now(sd_dhcp_client
*client
, int notify_event
) {
1961 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
, DHCP_STATE_REBOOTING
))
1962 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1964 client_set_state(client
, DHCP_STATE_BOUND
);
1965 client
->discover_attempt
= 0;
1966 client
->request_attempt
= 0;
1968 client
->last_addr
= client
->lease
->address
;
1970 r
= client_set_lease_timeouts(client
);
1972 log_dhcp_client_errno(client
, r
, "could not set lease timeouts: %m");
1974 if (client
->bootp
) {
1975 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
1976 client
->fd
= safe_close(client
->fd
);
1978 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1980 return log_dhcp_client_errno(client
, r
, "could not bind UDP socket: %m");
1982 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
1983 close_and_replace(client
->fd
, r
);
1984 client_initialize_io_events(client
, client_receive_message_udp
);
1987 client_notify(client
, notify_event
);
1992 static int client_enter_bound_delayed(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1993 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1994 DHCP_CLIENT_DONT_DESTROY(client
);
1997 r
= client_enter_bound_now(client
, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
);
1999 client_stop(client
, r
);
2004 static int client_enter_bound(sd_dhcp_client
*client
, int notify_event
) {
2006 assert(client
->lease
);
2008 client
->start_delay
= 0;
2009 (void) event_source_disable(client
->timeout_resend
);
2011 /* RFC 8925 section 3.2
2012 * If the client is in the INIT-REBOOT state, it SHOULD stop the DHCPv4 configuration process or
2013 * disable the IPv4 stack completely for V6ONLY_WAIT seconds or until the network attachment event,
2014 * whichever happens first.
2016 * In the below, the condition uses REBOOTING, instead of INIT-REBOOT, as the client state has
2017 * already transitioned from INIT-REBOOT to REBOOTING after sending a DHCPREQUEST message. */
2018 if (client
->state
== DHCP_STATE_REBOOTING
&& client
->lease
->ipv6_only_preferred_usec
> 0) {
2019 if (client
->ipv6_acquired
) {
2020 log_dhcp_client(client
,
2021 "Received an ACK with IPv6-only preferred option, and the host already acquired IPv6 connectivity, stopping DHCPv4 client.");
2022 return sd_dhcp_client_stop(client
);
2025 log_dhcp_client(client
,
2026 "Received an ACK with IPv6-only preferred option, delaying to enter bound state with %s.",
2027 FORMAT_TIMESPAN(client
->lease
->ipv6_only_preferred_usec
, USEC_PER_SEC
));
2029 return event_reset_time_relative(client
->event
, &client
->timeout_ipv6_only_mode
,
2031 client
->lease
->ipv6_only_preferred_usec
, 0,
2032 client_enter_bound_delayed
, client
,
2033 client
->event_priority
, "dhcp4-ipv6-only-mode",
2034 /* force_reset = */ true);
2037 return client_enter_bound_now(client
, notify_event
);
2040 static int client_restart(sd_dhcp_client
*client
) {
2044 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
2046 r
= client_initialize(client
);
2050 r
= client_start_delayed(client
);
2054 log_dhcp_client(client
, "REBOOT in %s", FORMAT_TIMESPAN(client
->start_delay
, USEC_PER_SEC
));
2056 client
->start_delay
= CLAMP(client
->start_delay
* 2,
2057 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
2061 static int client_verify_message_header(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
) {
2062 const uint8_t *expected_chaddr
= NULL
;
2063 uint8_t expected_hlen
= 0;
2068 if (len
< sizeof(DHCPMessage
))
2069 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
2070 "Too small to be a DHCP message, ignoring.");
2072 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
)
2073 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
2074 "Not a DHCP message, ignoring.");
2076 if (message
->op
!= BOOTREPLY
)
2077 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
2078 "Not a BOOTREPLY message, ignoring.");
2080 if (message
->htype
!= client
->arp_type
)
2081 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
2082 "Packet type does not match client type, ignoring.");
2084 if (client
->arp_type
== ARPHRD_ETHER
) {
2085 expected_hlen
= ETH_ALEN
;
2086 expected_chaddr
= client
->hw_addr
.bytes
;
2089 if (message
->hlen
!= expected_hlen
)
2090 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
2091 "Received packet hlen (%u) does not match expected (%u), ignoring.",
2092 message
->hlen
, expected_hlen
);
2094 if (memcmp_safe(message
->chaddr
, expected_chaddr
, expected_hlen
))
2095 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
2096 "Received chaddr does not match expected, ignoring.");
2098 if (client
->state
!= DHCP_STATE_BOUND
&&
2099 be32toh(message
->xid
) != client
->xid
)
2100 /* in BOUND state, we may receive FORCERENEW with xid set by server,
2101 so ignore the xid in this case */
2102 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
2103 "Received xid (%u) does not match expected (%u), ignoring.",
2104 be32toh(message
->xid
), client
->xid
);
2109 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
, const triple_timestamp
*timestamp
) {
2110 DHCP_CLIENT_DONT_DESTROY(client
);
2117 if (client_verify_message_header(client
, message
, len
) < 0)
2120 switch (client
->state
) {
2121 case DHCP_STATE_SELECTING
:
2123 r
= client_handle_offer_or_rapid_ack(client
, message
, len
, timestamp
);
2124 if (ERRNO_IS_NEG_RESOURCE(r
))
2126 if (r
== -EADDRNOTAVAIL
)
2127 /* got a rapid NAK, let's restart the client */
2128 return client_restart(client
);
2130 return 0; /* invalid message, let's ignore it */
2132 if (client
->lease
->rapid_commit
)
2133 /* got a successful rapid commit */
2134 return client_enter_bound(client
, r
);
2136 return client_enter_requesting(client
);
2138 case DHCP_STATE_REBOOTING
:
2139 case DHCP_STATE_REQUESTING
:
2140 case DHCP_STATE_RENEWING
:
2141 case DHCP_STATE_REBINDING
:
2143 r
= client_handle_ack(client
, message
, len
, timestamp
);
2144 if (ERRNO_IS_NEG_RESOURCE(r
))
2146 if (r
== -EADDRNOTAVAIL
)
2147 /* got a NAK, let's restart the client */
2148 return client_restart(client
);
2150 return 0; /* invalid message, let's ignore it */
2152 return client_enter_bound(client
, r
);
2154 case DHCP_STATE_BOUND
:
2155 r
= client_handle_forcerenew(client
, message
, len
);
2156 if (ERRNO_IS_NEG_RESOURCE(r
))
2159 return 0; /* invalid message, let's ignore it */
2161 return client_timeout_t1(NULL
, 0, client
);
2163 case DHCP_STATE_INIT
:
2164 case DHCP_STATE_INIT_REBOOT
:
2165 log_dhcp_client(client
, "Unexpectedly receive message without sending any requests, ignoring.");
2169 assert_not_reached();
2175 static int client_receive_message_udp(
2181 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
2182 _cleanup_free_ DHCPMessage
*message
= NULL
;
2183 ssize_t len
, buflen
;
2184 /* This needs to be initialized with zero. See #20741.
2185 * The issue is fixed on glibc-2.35 (8fba672472ae0055387e9315fc2eddfa6775ca79). */
2186 CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL
) control
= {};
2188 struct msghdr msg
= {
2191 .msg_control
= &control
,
2192 .msg_controllen
= sizeof(control
),
2198 buflen
= next_datagram_size_fd(fd
);
2199 if (ERRNO_IS_NEG_TRANSIENT(buflen
) || ERRNO_IS_NEG_DISCONNECT(buflen
))
2202 log_dhcp_client_errno(client
, buflen
, "Failed to determine datagram size to read, ignoring: %m");
2206 message
= malloc0(buflen
);
2210 iov
= IOVEC_MAKE(message
, buflen
);
2212 len
= recvmsg_safe(fd
, &msg
, MSG_DONTWAIT
);
2213 if (ERRNO_IS_NEG_TRANSIENT(len
) || ERRNO_IS_NEG_DISCONNECT(len
))
2216 log_dhcp_client_errno(client
, len
, "Could not receive message from UDP socket, ignoring: %m");
2220 log_dhcp_client(client
, "Received message from UDP socket, processing.");
2221 r
= client_handle_message(client
, message
, len
, TRIPLE_TIMESTAMP_FROM_CMSG(&msg
));
2223 client_stop(client
, r
);
2228 static int client_receive_message_raw(
2234 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
2235 _cleanup_free_ DHCPPacket
*packet
= NULL
;
2236 /* This needs to be initialized with zero. See #20741.
2237 * The issue is fixed on glibc-2.35 (8fba672472ae0055387e9315fc2eddfa6775ca79). */
2238 CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL
+
2239 CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
= {};
2240 struct iovec iov
= {};
2241 struct msghdr msg
= {
2244 .msg_control
= &control
,
2245 .msg_controllen
= sizeof(control
),
2247 bool checksum
= true;
2248 ssize_t buflen
, len
;
2253 buflen
= next_datagram_size_fd(fd
);
2254 if (ERRNO_IS_NEG_TRANSIENT(buflen
) || ERRNO_IS_NEG_DISCONNECT(buflen
))
2257 log_dhcp_client_errno(client
, buflen
, "Failed to determine datagram size to read, ignoring: %m");
2261 packet
= malloc0(buflen
);
2265 iov
= IOVEC_MAKE(packet
, buflen
);
2267 len
= recvmsg_safe(fd
, &msg
, 0);
2268 if (ERRNO_IS_NEG_TRANSIENT(len
) || ERRNO_IS_NEG_DISCONNECT(len
))
2271 log_dhcp_client_errno(client
, len
, "Could not receive message from raw socket, ignoring: %m");
2275 struct tpacket_auxdata
*aux
= CMSG_FIND_DATA(&msg
, SOL_PACKET
, PACKET_AUXDATA
, struct tpacket_auxdata
);
2277 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2279 if (dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
) < 0)
2282 len
-= DHCP_IP_UDP_SIZE
;
2284 log_dhcp_client(client
, "Received message from RAW socket, processing.");
2285 r
= client_handle_message(client
, &packet
->dhcp
, len
, TRIPLE_TIMESTAMP_FROM_CMSG(&msg
));
2287 client_stop(client
, r
);
2292 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2293 if (!sd_dhcp_client_is_running(client
) || client
->state
!= DHCP_STATE_BOUND
|| client
->bootp
)
2294 return 0; /* do nothing */
2296 client
->start_delay
= 0;
2297 client
->discover_attempt
= 1;
2298 client
->request_attempt
= 1;
2299 client_set_state(client
, DHCP_STATE_RENEWING
);
2301 return client_initialize_time_events(client
);
2304 int sd_dhcp_client_is_running(sd_dhcp_client
*client
) {
2308 return client
->state
!= DHCP_STATE_STOPPED
;
2311 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2314 assert_return(client
, -EINVAL
);
2316 /* Note, do not reset the flag in client_initialize(), as it is also called on expire. */
2317 client
->ipv6_acquired
= false;
2319 r
= client_initialize(client
);
2323 /* If no client identifier exists, construct an RFC 4361-compliant one */
2324 if (!sd_dhcp_client_id_is_set(&client
->client_id
)) {
2325 r
= sd_dhcp_client_set_iaid_duid_en(client
, /* iaid_set = */ false, /* iaid = */ 0);
2330 /* RFC7844 section 3.3:
2331 SHOULD perform a complete four-way handshake, starting with a
2332 DHCPDISCOVER, to obtain a new address lease. If the client can
2333 ascertain that this is exactly the same network to which it was
2334 previously connected, and if the link-layer address did not change,
2335 the client MAY issue a DHCPREQUEST to try to reclaim the current
2337 if (client
->last_addr
&& !client
->anonymize
&& !client
->bootp
)
2338 client_set_state(client
, DHCP_STATE_INIT_REBOOT
);
2340 /* We currently ignore:
2341 * The client SHOULD wait a random time between one and ten seconds to desynchronize the use of
2342 * DHCP at startup. */
2343 r
= client_start(client
);
2345 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2350 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2351 _cleanup_free_ DHCPPacket
*release
= NULL
;
2352 size_t optoffset
, optlen
;
2355 if (!sd_dhcp_client_is_running(client
) || !client
->lease
|| client
->bootp
)
2356 return 0; /* do nothing */
2358 r
= client_message_init(client
, DHCP_RELEASE
, &release
, &optlen
, &optoffset
);
2362 /* Fill up release IP and MAC */
2363 release
->dhcp
.ciaddr
= client
->lease
->address
;
2364 memcpy(&release
->dhcp
.chaddr
, client
->hw_addr
.bytes
, client
->hw_addr
.length
);
2366 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2367 SD_DHCP_OPTION_END
, 0, NULL
);
2371 r
= dhcp_network_send_udp_socket(client
->fd
,
2372 client
->lease
->server_address
,
2373 client
->server_port
,
2375 sizeof(DHCPMessage
) + optoffset
);
2379 log_dhcp_client(client
, "RELEASE");
2381 /* This function is mostly called when stopping daemon. Hence, do not call client_stop() or
2382 * client_restart(). Otherwise, the notification callback will be called again and we may easily
2383 * enter an infinite loop. */
2384 client_initialize(client
);
2385 return 1; /* sent and stopped. */
2388 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2389 _cleanup_free_ DHCPPacket
*release
= NULL
;
2390 size_t optoffset
, optlen
;
2393 if (!sd_dhcp_client_is_running(client
) || !client
->lease
)
2394 return 0; /* do nothing */
2396 r
= client_message_init(client
, DHCP_DECLINE
, &release
, &optlen
, &optoffset
);
2400 release
->dhcp
.ciaddr
= client
->lease
->address
;
2401 memcpy(&release
->dhcp
.chaddr
, client
->hw_addr
.bytes
, client
->hw_addr
.length
);
2403 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2404 SD_DHCP_OPTION_END
, 0, NULL
);
2408 r
= dhcp_network_send_udp_socket(client
->fd
,
2409 client
->lease
->server_address
,
2410 client
->server_port
,
2412 sizeof(DHCPMessage
) + optoffset
);
2416 log_dhcp_client(client
, "DECLINE");
2418 /* This function is mostly called when the acquired address conflicts with another host.
2419 * Restarting the daemon to acquire another address. */
2420 r
= client_restart(client
);
2424 return 1; /* sent and restarted. */
2427 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2431 DHCP_CLIENT_DONT_DESTROY(client
);
2433 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2438 int sd_dhcp_client_set_ipv6_connectivity(sd_dhcp_client
*client
, int have
) {
2442 /* We have already received a message with IPv6-Only preferred option, and are waiting for IPv6
2443 * connectivity or timeout, let's stop the client. */
2444 if (have
&& sd_event_source_get_enabled(client
->timeout_ipv6_only_mode
, NULL
) > 0)
2445 return sd_dhcp_client_stop(client
);
2447 /* Otherwise, save that the host already has IPv6 connectivity. */
2448 client
->ipv6_acquired
= have
;
2452 int sd_dhcp_client_interrupt_ipv6_only_mode(sd_dhcp_client
*client
) {
2453 assert_return(client
, -EINVAL
);
2454 assert_return(sd_dhcp_client_is_running(client
), -ESTALE
);
2455 assert_return(client
->fd
>= 0, -EINVAL
);
2457 if (sd_event_source_get_enabled(client
->timeout_ipv6_only_mode
, NULL
) <= 0)
2460 client_initialize(client
);
2461 return client_start(client
);
2464 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2467 assert_return(client
, -EINVAL
);
2468 assert_return(!client
->event
, -EBUSY
);
2469 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
2472 client
->event
= sd_event_ref(event
);
2474 r
= sd_event_default(&client
->event
);
2479 client
->event_priority
= priority
;
2484 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2485 assert_return(client
, -EINVAL
);
2486 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
2488 client
->event
= sd_event_unref(client
->event
);
2493 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2494 assert_return(client
, NULL
);
2496 return client
->event
;
2499 int sd_dhcp_client_attach_device(sd_dhcp_client
*client
, sd_device
*dev
) {
2500 assert_return(client
, -EINVAL
);
2502 return device_unref_and_replace(client
->dev
, dev
);
2505 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2509 log_dhcp_client(client
, "FREE");
2511 client_initialize(client
);
2513 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2514 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2515 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2516 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2518 sd_dhcp_client_detach_event(client
);
2520 sd_device_unref(client
->dev
);
2522 set_free(client
->req_opts
);
2523 free(client
->hostname
);
2524 free(client
->vendor_class_identifier
);
2525 free(client
->mudurl
);
2526 client
->user_class
= strv_free(client
->user_class
);
2527 ordered_hashmap_free(client
->extra_options
);
2528 ordered_hashmap_free(client
->vendor_options
);
2529 free(client
->ifname
);
2530 return mfree(client
);
2533 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2535 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2536 const uint8_t *opts
;
2540 assert_return(ret
, -EINVAL
);
2542 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2546 *client
= (sd_dhcp_client
) {
2548 .state
= DHCP_STATE_STOPPED
,
2551 .mtu
= DHCP_MIN_PACKET_SIZE
,
2552 .port
= DHCP_PORT_CLIENT
,
2553 .server_port
= DHCP_PORT_SERVER
,
2554 .anonymize
= !!anonymize
,
2555 .max_discover_attempts
= UINT64_MAX
,
2556 .max_request_attempts
= 5,
2557 .ip_service_type
= -1,
2559 /* NOTE: this could be moved to a function. */
2561 n_opts
= ELEMENTSOF(default_req_opts_anonymize
);
2562 opts
= default_req_opts_anonymize
;
2564 n_opts
= ELEMENTSOF(default_req_opts
);
2565 opts
= default_req_opts
;
2568 for (size_t i
= 0; i
< n_opts
; i
++) {
2569 r
= sd_dhcp_client_set_request_option(client
, opts
[i
]);
2574 *ret
= TAKE_PTR(client
);
2579 static const char* const dhcp_state_table
[_DHCP_STATE_MAX
] = {
2580 [DHCP_STATE_STOPPED
] = "stopped",
2581 [DHCP_STATE_INIT
] = "initialization",
2582 [DHCP_STATE_SELECTING
] = "selecting",
2583 [DHCP_STATE_INIT_REBOOT
] = "init-reboot",
2584 [DHCP_STATE_REBOOTING
] = "rebooting",
2585 [DHCP_STATE_REQUESTING
] = "requesting",
2586 [DHCP_STATE_BOUND
] = "bound",
2587 [DHCP_STATE_RENEWING
] = "renewing",
2588 [DHCP_STATE_REBINDING
] = "rebinding",
2591 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(dhcp_state
, DHCPState
);