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 "device-util.h"
18 #include "dhcp-client-id-internal.h"
19 #include "dhcp-client-internal.h"
20 #include "dhcp-lease-internal.h"
21 #include "dhcp-network.h"
22 #include "dhcp-option.h"
23 #include "dhcp-packet.h"
24 #include "dns-domain.h"
25 #include "ether-addr-util.h"
26 #include "event-util.h"
28 #include "hostname-util.h"
29 #include "iovec-util.h"
30 #include "memory-util.h"
31 #include "network-common.h"
32 #include "random-util.h"
34 #include "sort-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
38 #include "time-util.h"
42 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
44 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
45 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
47 #define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
48 * transient failure. */
50 struct sd_dhcp_client
{
56 sd_event_source
*timeout_resend
;
66 union sockaddr_union link
;
67 sd_event_source
*receive_message
;
68 bool request_broadcast
;
73 struct hw_addr_data hw_addr
;
74 struct hw_addr_data bcast_addr
;
76 sd_dhcp_client_id client_id
;
78 char *vendor_class_identifier
;
82 usec_t fallback_lease_lifetime
;
88 uint64_t discover_attempt
;
89 uint64_t request_attempt
;
90 uint64_t max_discover_attempts
;
91 uint64_t max_request_attempts
;
92 OrderedHashmap
*extra_options
;
93 OrderedHashmap
*vendor_options
;
94 sd_event_source
*timeout_t1
;
95 sd_event_source
*timeout_t2
;
96 sd_event_source
*timeout_expire
;
97 sd_event_source
*timeout_ipv6_only_mode
;
98 sd_dhcp_client_callback_t callback
;
100 sd_dhcp_client_callback_t state_callback
;
101 void *state_userdata
;
102 sd_dhcp_lease
*lease
;
106 bool socket_priority_set
;
110 static const uint8_t default_req_opts
[] = {
111 SD_DHCP_OPTION_SUBNET_MASK
,
112 SD_DHCP_OPTION_ROUTER
,
113 SD_DHCP_OPTION_HOST_NAME
,
114 SD_DHCP_OPTION_DOMAIN_NAME
,
115 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
118 /* RFC7844 section 3:
119 MAY contain the Parameter Request List option.
121 The client intending to protect its privacy SHOULD only request a
122 minimal number of options in the PRL and SHOULD also randomly shuffle
123 the ordering of option codes in the PRL. If this random ordering
124 cannot be implemented, the client MAY order the option codes in the
125 PRL by option code number (lowest to highest).
127 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
128 static const uint8_t default_req_opts_anonymize
[] = {
129 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
130 SD_DHCP_OPTION_ROUTER
, /* 3 */
131 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
132 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
133 SD_DHCP_OPTION_ROUTER_DISCOVERY
, /* 31 */
134 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
135 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
136 SD_DHCP_OPTION_NETBIOS_NAME_SERVER
, /* 44 */
137 SD_DHCP_OPTION_NETBIOS_NODE_TYPE
, /* 46 */
138 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
139 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
140 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
141 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
144 static int client_receive_message_raw(
149 static int client_receive_message_udp(
154 static void client_stop(sd_dhcp_client
*client
, int error
);
155 static int client_restart(sd_dhcp_client
*client
);
157 int dhcp_client_set_state_callback(
158 sd_dhcp_client
*client
,
159 sd_dhcp_client_callback_t cb
,
162 assert_return(client
, -EINVAL
);
164 client
->state_callback
= cb
;
165 client
->state_userdata
= userdata
;
170 int sd_dhcp_client_set_callback(
171 sd_dhcp_client
*client
,
172 sd_dhcp_client_callback_t cb
,
175 assert_return(client
, -EINVAL
);
177 client
->callback
= cb
;
178 client
->userdata
= userdata
;
183 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
184 assert_return(client
, -EINVAL
);
185 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
187 client
->request_broadcast
= broadcast
;
192 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
193 assert_return(client
, -EINVAL
);
194 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
198 case SD_DHCP_OPTION_PAD
:
199 case SD_DHCP_OPTION_OVERLOAD
:
200 case SD_DHCP_OPTION_MESSAGE_TYPE
:
201 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
202 case SD_DHCP_OPTION_END
:
209 return set_ensure_put(&client
->req_opts
, NULL
, UINT8_TO_PTR(option
));
212 static int client_request_contains(sd_dhcp_client
*client
, uint8_t option
) {
215 return set_contains(client
->req_opts
, UINT8_TO_PTR(option
));
218 int sd_dhcp_client_set_request_address(
219 sd_dhcp_client
*client
,
220 const struct in_addr
*last_addr
) {
222 assert_return(client
, -EINVAL
);
223 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
226 client
->last_addr
= last_addr
->s_addr
;
228 client
->last_addr
= INADDR_ANY
;
233 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
234 assert_return(client
, -EINVAL
);
235 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
236 assert_return(ifindex
> 0, -EINVAL
);
238 client
->ifindex
= ifindex
;
242 int sd_dhcp_client_set_ifname(sd_dhcp_client
*client
, const char *ifname
) {
243 assert_return(client
, -EINVAL
);
244 assert_return(ifname
, -EINVAL
);
246 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
249 return free_and_strdup(&client
->ifname
, ifname
);
252 int sd_dhcp_client_get_ifname(sd_dhcp_client
*client
, const char **ret
) {
255 assert_return(client
, -EINVAL
);
257 r
= get_ifname(client
->ifindex
, &client
->ifname
);
262 *ret
= client
->ifname
;
267 int sd_dhcp_client_set_mac(
268 sd_dhcp_client
*client
,
269 const uint8_t *hw_addr
,
270 const uint8_t *bcast_addr
,
274 assert_return(client
, -EINVAL
);
275 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
276 assert_return(IN_SET(arp_type
, ARPHRD_ETHER
, ARPHRD_INFINIBAND
), -EINVAL
);
277 assert_return(hw_addr
, -EINVAL
);
278 assert_return(addr_len
== (arp_type
== ARPHRD_ETHER
? ETH_ALEN
: INFINIBAND_ALEN
), -EINVAL
);
280 client
->arp_type
= arp_type
;
281 hw_addr_set(&client
->hw_addr
, hw_addr
, addr_len
);
282 hw_addr_set(&client
->bcast_addr
, bcast_addr
, bcast_addr
? addr_len
: 0);
287 int sd_dhcp_client_get_client_id(sd_dhcp_client
*client
, const sd_dhcp_client_id
**ret
) {
288 assert_return(client
, -EINVAL
);
289 assert_return(ret
, -EINVAL
);
291 if (!sd_dhcp_client_id_is_set(&client
->client_id
))
294 *ret
= &client
->client_id
;
298 int sd_dhcp_client_set_client_id(
299 sd_dhcp_client
*client
,
304 assert_return(client
, -EINVAL
);
305 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
306 assert_return(data
, -EINVAL
);
307 assert_return(client_id_data_size_is_valid(data_len
), -EINVAL
);
309 /* For hardware types, log debug message about unexpected data length.
311 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
312 * the last 8 bytes of the address are stable and suitable to put into
313 * the client-id. The caller is advised to account for that. */
314 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
315 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
316 log_dhcp_client(client
,
317 "Changing client ID to hardware type %u with unexpected address length %zu",
320 return sd_dhcp_client_id_set(&client
->client_id
, type
, data
, data_len
);
323 static int dhcp_client_set_iaid_duid(
324 sd_dhcp_client
*client
,
327 sd_dhcp_duid
*duid
) {
332 r
= dhcp_identifier_set_iaid(client
->dev
, &client
->hw_addr
,
333 /* legacy_unstable_byteorder = */ true,
338 iaid
= be32toh(iaid
);
341 return sd_dhcp_client_id_set_iaid_duid(&client
->client_id
, iaid
, duid
);
344 int sd_dhcp_client_set_iaid_duid_llt(
345 sd_dhcp_client
*client
,
353 assert_return(client
, -EINVAL
);
354 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
356 r
= sd_dhcp_duid_set_llt(&duid
, client
->hw_addr
.bytes
, client
->hw_addr
.length
, client
->arp_type
, llt_time
);
360 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
363 int sd_dhcp_client_set_iaid_duid_ll(
364 sd_dhcp_client
*client
,
371 assert_return(client
, -EINVAL
);
372 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
374 r
= sd_dhcp_duid_set_ll(&duid
, client
->hw_addr
.bytes
, client
->hw_addr
.length
, client
->arp_type
);
378 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
381 int sd_dhcp_client_set_iaid_duid_en(
382 sd_dhcp_client
*client
,
389 assert_return(client
, -EINVAL
);
390 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
392 r
= sd_dhcp_duid_set_en(&duid
);
396 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
399 int sd_dhcp_client_set_iaid_duid_uuid(
400 sd_dhcp_client
*client
,
407 assert_return(client
, -EINVAL
);
408 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
410 r
= sd_dhcp_duid_set_uuid(&duid
);
414 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
417 int sd_dhcp_client_set_iaid_duid_raw(
418 sd_dhcp_client
*client
,
422 const uint8_t *duid_data
,
423 size_t duid_data_len
) {
428 assert_return(client
, -EINVAL
);
429 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
430 assert_return(duid_data
|| duid_data_len
== 0, -EINVAL
);
432 r
= sd_dhcp_duid_set(&duid
, duid_type
, duid_data
, duid_data_len
);
436 return dhcp_client_set_iaid_duid(client
, iaid_set
, iaid
, &duid
);
439 int sd_dhcp_client_set_rapid_commit(sd_dhcp_client
*client
, bool rapid_commit
) {
440 assert_return(client
, -EINVAL
);
442 client
->rapid_commit
= !client
->anonymize
&& rapid_commit
;
446 int sd_dhcp_client_set_hostname(
447 sd_dhcp_client
*client
,
448 const char *hostname
) {
450 assert_return(client
, -EINVAL
);
451 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
453 /* Make sure hostnames qualify as DNS and as Linux hostnames */
455 !(hostname_is_valid(hostname
, 0) && dns_name_is_valid(hostname
) > 0))
458 return free_and_strdup(&client
->hostname
, hostname
);
461 int sd_dhcp_client_set_vendor_class_identifier(
462 sd_dhcp_client
*client
,
465 assert_return(client
, -EINVAL
);
466 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
468 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
471 int sd_dhcp_client_set_mud_url(
472 sd_dhcp_client
*client
,
473 const char *mudurl
) {
475 assert_return(client
, -EINVAL
);
476 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
477 assert_return(mudurl
, -EINVAL
);
478 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
479 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
481 return free_and_strdup(&client
->mudurl
, mudurl
);
484 int sd_dhcp_client_set_user_class(
485 sd_dhcp_client
*client
,
486 char * const *user_class
) {
490 assert_return(client
, -EINVAL
);
491 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
492 assert_return(!strv_isempty(user_class
), -EINVAL
);
494 STRV_FOREACH(p
, user_class
) {
495 size_t n
= strlen(*p
);
497 if (n
> 255 || n
== 0)
501 s
= strv_copy(user_class
);
505 return strv_free_and_replace(client
->user_class
, s
);
508 int sd_dhcp_client_set_client_port(
509 sd_dhcp_client
*client
,
512 assert_return(client
, -EINVAL
);
513 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
520 int sd_dhcp_client_set_port(
521 sd_dhcp_client
*client
,
524 assert_return(client
, -EINVAL
);
525 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
527 client
->server_port
= port
;
532 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
533 assert_return(client
, -EINVAL
);
534 assert_return(mtu
>= DHCP_MIN_PACKET_SIZE
, -ERANGE
);
536 /* MTU may be changed by the acquired lease. Hence, we cannot require that the client is stopped here.
537 * Please do not add assertion for !sd_dhcp_client_is_running(client) here. */
544 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
545 assert_return(client
, -EINVAL
);
546 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
548 client
->max_discover_attempts
= max_attempts
;
553 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
556 assert_return(client
, -EINVAL
);
557 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
558 assert_return(v
, -EINVAL
);
560 r
= ordered_hashmap_ensure_put(&client
->extra_options
, &dhcp_option_hash_ops
, UINT_TO_PTR(v
->option
), v
);
564 sd_dhcp_option_ref(v
);
568 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
571 assert_return(client
, -EINVAL
);
572 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
573 assert_return(v
, -EINVAL
);
575 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
579 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
583 sd_dhcp_option_ref(v
);
588 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
589 assert_return(client
, -EINVAL
);
592 return -EADDRNOTAVAIL
;
595 *ret
= client
->lease
;
600 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
601 assert_return(client
, -EINVAL
);
602 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
604 client
->ip_service_type
= type
;
609 int sd_dhcp_client_set_socket_priority(sd_dhcp_client
*client
, int socket_priority
) {
610 assert_return(client
, -EINVAL
);
611 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
613 client
->socket_priority_set
= true;
614 client
->socket_priority
= socket_priority
;
619 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint64_t fallback_lease_lifetime
) {
620 assert_return(client
, -EINVAL
);
621 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
622 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
624 assert_cc(sizeof(usec_t
) == sizeof(uint64_t));
625 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
630 static void client_set_state(sd_dhcp_client
*client
, DHCPState state
) {
633 if (client
->state
== state
)
636 log_dhcp_client(client
, "State changed: %s -> %s",
637 dhcp_state_to_string(client
->state
), dhcp_state_to_string(state
));
639 client
->state
= state
;
641 if (client
->state_callback
)
642 client
->state_callback(client
, state
, client
->state_userdata
);
645 int dhcp_client_get_state(sd_dhcp_client
*client
) {
646 assert_return(client
, -EINVAL
);
648 return client
->state
;
651 static int client_notify(sd_dhcp_client
*client
, int event
) {
654 if (client
->callback
)
655 return client
->callback(client
, event
, client
->userdata
);
660 static int client_initialize(sd_dhcp_client
*client
) {
661 assert_return(client
, -EINVAL
);
663 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
665 client
->fd
= safe_close(client
->fd
);
667 (void) event_source_disable(client
->timeout_resend
);
668 (void) event_source_disable(client
->timeout_t1
);
669 (void) event_source_disable(client
->timeout_t2
);
670 (void) event_source_disable(client
->timeout_expire
);
671 (void) event_source_disable(client
->timeout_ipv6_only_mode
);
673 client
->discover_attempt
= 0;
674 client
->request_attempt
= 0;
676 client_set_state(client
, DHCP_STATE_STOPPED
);
679 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
684 static void client_stop(sd_dhcp_client
*client
, int error
) {
686 DHCP_CLIENT_DONT_DESTROY(client
);
688 if (sd_dhcp_client_is_running(client
)) {
690 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
691 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
692 log_dhcp_client(client
, "STOPPED");
694 log_dhcp_client(client
, "STOPPED: Unknown event");
696 client_notify(client
, error
);
697 } else if (error
< 0) {
698 log_dhcp_client_errno(client
, error
, "FAILED: %m");
699 client_notify(client
, error
);
702 client_initialize(client
);
705 /* RFC2131 section 4.1:
706 * retransmission delays should include -1 to +1 sec of random 'fuzz'. */
707 #define RFC2131_RANDOM_FUZZ \
708 ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
710 /* RFC2131 section 4.1:
711 * for retransmission delays, timeout should start at 4s then double
712 * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
713 * This assumes the first call will be using attempt 1. */
714 static usec_t
client_compute_request_timeout(usec_t now
, uint64_t attempt
) {
715 usec_t timeout
= (UINT64_C(1) << MIN(attempt
+ 1, UINT64_C(6))) * USEC_PER_SEC
;
717 return usec_sub_signed(usec_add(now
, timeout
), RFC2131_RANDOM_FUZZ
);
720 /* RFC2131 section 4.4.5:
721 * T1 defaults to (0.5 * duration_of_lease).
722 * T2 defaults to (0.875 * duration_of_lease). */
723 #define T1_DEFAULT(lifetime) ((lifetime) / 2)
724 #define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
726 /* RFC2131 section 4.4.5:
727 * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
728 * and one-half of the remaining lease time (in REBINDING state), down to a minimum
730 * Note that while the default T1/T2 initial times do have random 'fuzz' applied,
731 * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
732 static usec_t
client_compute_reacquisition_timeout(usec_t now
, usec_t expire
) {
733 return now
+ MAX(usec_sub_unsigned(expire
, now
) / 2, 60 * USEC_PER_SEC
);
736 static int cmp_uint8(const uint8_t *a
, const uint8_t *b
) {
740 static int client_message_init(
741 sd_dhcp_client
*client
,
745 size_t *_optoffset
) {
747 _cleanup_free_ DHCPPacket
*packet
= NULL
;
748 size_t optlen
, optoffset
, size
;
754 assert(client
->start_time
);
758 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
760 optlen
= DHCP_MIN_OPTIONS_SIZE
;
761 size
= sizeof(DHCPPacket
) + optlen
;
763 packet
= malloc0(size
);
767 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
768 client
->arp_type
, client
->hw_addr
.length
, client
->hw_addr
.bytes
,
773 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
774 refuse to issue an DHCP lease if 'secs' is set to zero */
775 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
778 assert(time_now
>= client
->start_time
);
780 /* seconds between sending first and last DISCOVER
781 * must always be strictly positive to deal with broken servers */
782 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ?: 1;
783 packet
->dhcp
.secs
= htobe16(secs
);
785 /* RFC2131 section 4.1
786 A client that cannot receive unicast IP datagrams until its protocol
787 software has been configured with an IP address SHOULD set the
788 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
789 DHCPREQUEST messages that client sends. The BROADCAST bit will
790 provide a hint to the DHCP server and BOOTP relay agent to broadcast
791 any messages to the client on the client's subnet.
793 Note: some interfaces needs this to be enabled, but some networks
794 needs this to be disabled as broadcasts are filteretd, so this
795 needs to be configurable */
796 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
797 packet
->dhcp
.flags
= htobe16(0x8000);
799 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
800 Identifier option is not set */
801 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
802 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
803 client
->client_id
.size
,
804 client
->client_id
.raw
);
808 /* RFC2131 section 3.5:
809 in its initial DHCPDISCOVER or DHCPREQUEST message, a
810 client may provide the server with a list of specific
811 parameters the client is interested in. If the client
812 includes a list of parameters in a DHCPDISCOVER message,
813 it MUST include that list in any subsequent DHCPREQUEST
817 /* RFC7844 section 3:
818 MAY contain the Parameter Request List option. */
819 /* NOTE: in case that there would be an option to do not send
820 * any PRL at all, the size should be checked before sending */
821 if (!set_isempty(client
->req_opts
) && type
!= DHCP_RELEASE
) {
822 _cleanup_free_
uint8_t *opts
= NULL
;
823 size_t n_opts
, i
= 0;
826 n_opts
= set_size(client
->req_opts
);
827 opts
= new(uint8_t, n_opts
);
831 SET_FOREACH(val
, client
->req_opts
)
832 opts
[i
++] = PTR_TO_UINT8(val
);
835 /* For anonymizing the request, let's sort the options. */
836 typesafe_qsort(opts
, n_opts
, cmp_uint8
);
838 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
839 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
845 /* RFC2131 section 3.5:
846 The client SHOULD include the ’maximum DHCP message size’ option to
847 let the server know how large the server may make its DHCP messages.
849 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
850 than the defined default size unless the Maximum Message Size option
853 RFC3442 "Requirements to Avoid Sizing Constraints":
854 Because a full routing table can be quite large, the standard 576
855 octet maximum size for a DHCP message may be too short to contain
856 some legitimate Classless Static Route options. Because of this,
857 clients implementing the Classless Static Route option SHOULD send a
858 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
859 stack is capable of receiving larger IP datagrams. In this case, the
860 client SHOULD set the value of this option to at least the MTU of the
861 interface that the client is configuring. The client MAY set the
862 value of this option higher, up to the size of the largest UDP packet
863 it is prepared to accept. (Note that the value specified in the
864 Maximum DHCP Message Size option is the total maximum packet size,
865 including IP and UDP headers.)
867 /* RFC7844 section 3:
868 SHOULD NOT contain any other option. */
869 if (!client
->anonymize
&& IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
)) {
870 be16_t max_size
= htobe16(MIN(client
->mtu
- DHCP_IP_UDP_SIZE
, (uint32_t) UINT16_MAX
));
871 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
872 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
879 *_optoffset
= optoffset
;
880 *ret
= TAKE_PTR(packet
);
885 static int client_append_fqdn_option(
886 DHCPMessage
*message
,
891 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
894 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
895 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
896 buffer
[1] = 0; /* RCODE1 (deprecated) */
897 buffer
[2] = 0; /* RCODE2 (deprecated) */
899 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
901 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
902 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
907 static int dhcp_client_send_raw(
908 sd_dhcp_client
*client
,
912 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
913 INADDR_BROADCAST
, client
->server_port
, len
, client
->ip_service_type
);
915 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
919 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
925 if (client
->hostname
) {
926 /* According to RFC 4702 "clients that send the Client FQDN option in
927 their messages MUST NOT also send the Host Name option". Just send
928 one of the two depending on the hostname type.
930 if (dns_name_is_single_label(client
->hostname
)) {
931 /* it is unclear from RFC 2131 if client should send hostname in
932 DHCPDISCOVER but dhclient does and so we do as well
934 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
935 SD_DHCP_OPTION_HOST_NAME
,
936 strlen(client
->hostname
), client
->hostname
);
938 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
944 if (client
->vendor_class_identifier
) {
945 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
946 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
947 strlen(client
->vendor_class_identifier
),
948 client
->vendor_class_identifier
);
953 if (client
->mudurl
) {
954 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
955 SD_DHCP_OPTION_MUD_URL
,
956 strlen(client
->mudurl
),
962 if (client
->user_class
) {
963 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
964 SD_DHCP_OPTION_USER_CLASS
,
965 strv_length(client
->user_class
),
971 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
) {
972 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
973 j
->option
, j
->length
, j
->data
);
978 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
979 r
= dhcp_option_append(
980 &packet
->dhcp
, optlen
, optoffset
, 0,
981 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
982 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
991 static int client_send_discover(sd_dhcp_client
*client
) {
992 _cleanup_free_ DHCPPacket
*discover
= NULL
;
993 size_t optoffset
, optlen
;
997 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
999 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
1000 &optlen
, &optoffset
);
1004 /* the client may suggest values for the network address
1005 and lease time in the DHCPDISCOVER message. The client may include
1006 the ’requested IP address’ option to suggest that a particular IP
1007 address be assigned, and may include the ’IP address lease time’
1008 option to suggest the lease time it would like.
1010 /* RFC7844 section 3:
1011 SHOULD NOT contain any other option. */
1012 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
1013 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1014 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1015 4, &client
->last_addr
);
1020 if (client
->rapid_commit
) {
1021 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1022 SD_DHCP_OPTION_RAPID_COMMIT
, 0, NULL
);
1027 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
1031 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1032 SD_DHCP_OPTION_END
, 0, NULL
);
1036 /* We currently ignore:
1037 The client SHOULD wait a random time between one and ten seconds to
1038 desynchronize the use of DHCP at startup.
1040 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1044 log_dhcp_client(client
, "DISCOVER");
1049 static int client_send_request(sd_dhcp_client
*client
) {
1050 _cleanup_free_ DHCPPacket
*request
= NULL
;
1051 size_t optoffset
, optlen
;
1056 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
1060 switch (client
->state
) {
1061 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1062 SELECTING should be REQUESTING)
1065 case DHCP_STATE_REQUESTING
:
1066 /* Client inserts the address of the selected server in ’server
1067 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1068 filled in with the yiaddr value from the chosen DHCPOFFER.
1071 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1072 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1073 4, &client
->lease
->server_address
);
1077 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1078 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1079 4, &client
->lease
->address
);
1085 case DHCP_STATE_INIT_REBOOT
:
1086 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1087 option MUST be filled in with client’s notion of its previously
1088 assigned address. ’ciaddr’ MUST be zero.
1090 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1091 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1092 4, &client
->last_addr
);
1097 case DHCP_STATE_RENEWING
:
1098 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1099 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1100 client’s IP address.
1103 case DHCP_STATE_REBINDING
:
1104 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1105 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1106 client’s IP address.
1108 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1110 request
->dhcp
.ciaddr
= client
->lease
->address
;
1114 case DHCP_STATE_INIT
:
1115 case DHCP_STATE_SELECTING
:
1116 case DHCP_STATE_REBOOTING
:
1117 case DHCP_STATE_BOUND
:
1118 case DHCP_STATE_STOPPED
:
1123 r
= client_append_common_discover_request_options(client
, request
, &optoffset
, optlen
);
1127 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1128 SD_DHCP_OPTION_END
, 0, NULL
);
1132 if (client
->state
== DHCP_STATE_RENEWING
)
1133 r
= dhcp_network_send_udp_socket(client
->fd
,
1134 client
->lease
->server_address
,
1135 client
->server_port
,
1137 sizeof(DHCPMessage
) + optoffset
);
1139 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1143 switch (client
->state
) {
1145 case DHCP_STATE_REQUESTING
:
1146 log_dhcp_client(client
, "REQUEST (requesting)");
1149 case DHCP_STATE_INIT_REBOOT
:
1150 log_dhcp_client(client
, "REQUEST (init-reboot)");
1153 case DHCP_STATE_RENEWING
:
1154 log_dhcp_client(client
, "REQUEST (renewing)");
1157 case DHCP_STATE_REBINDING
:
1158 log_dhcp_client(client
, "REQUEST (rebinding)");
1162 log_dhcp_client(client
, "REQUEST (invalid)");
1169 static int client_start(sd_dhcp_client
*client
);
1171 static int client_timeout_resend(
1176 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1177 DHCP_CLIENT_DONT_DESTROY(client
);
1178 usec_t time_now
, next_timeout
;
1182 assert(client
->event
);
1184 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
1188 switch (client
->state
) {
1190 case DHCP_STATE_RENEWING
:
1191 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->t2_time
);
1194 case DHCP_STATE_REBINDING
:
1195 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->expire_time
);
1198 case DHCP_STATE_REBOOTING
:
1199 /* start over as we did not receive a timely ack or nak */
1200 r
= client_initialize(client
);
1204 r
= client_start(client
);
1208 log_dhcp_client(client
, "REBOOTED");
1211 case DHCP_STATE_INIT
:
1212 case DHCP_STATE_INIT_REBOOT
:
1213 case DHCP_STATE_SELECTING
:
1214 if (client
->discover_attempt
>= client
->max_discover_attempts
)
1217 client
->discover_attempt
++;
1218 next_timeout
= client_compute_request_timeout(time_now
, client
->discover_attempt
);
1220 case DHCP_STATE_REQUESTING
:
1221 case DHCP_STATE_BOUND
:
1222 if (client
->request_attempt
>= client
->max_request_attempts
)
1225 client
->request_attempt
++;
1226 next_timeout
= client_compute_request_timeout(time_now
, client
->request_attempt
);
1229 case DHCP_STATE_STOPPED
:
1234 assert_not_reached();
1237 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1239 next_timeout
, 10 * USEC_PER_MSEC
,
1240 client_timeout_resend
, client
,
1241 client
->event_priority
, "dhcp4-resend-timer", true);
1245 switch (client
->state
) {
1246 case DHCP_STATE_INIT
:
1247 r
= client_send_discover(client
);
1249 client_set_state(client
, DHCP_STATE_SELECTING
);
1250 client
->discover_attempt
= 0;
1251 } else if (client
->discover_attempt
>= client
->max_discover_attempts
)
1255 case DHCP_STATE_SELECTING
:
1256 r
= client_send_discover(client
);
1257 if (r
< 0 && client
->discover_attempt
>= client
->max_discover_attempts
)
1261 case DHCP_STATE_INIT_REBOOT
:
1262 case DHCP_STATE_REQUESTING
:
1263 case DHCP_STATE_RENEWING
:
1264 case DHCP_STATE_REBINDING
:
1265 r
= client_send_request(client
);
1266 if (r
< 0 && client
->request_attempt
>= client
->max_request_attempts
)
1269 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1270 client_set_state(client
, DHCP_STATE_REBOOTING
);
1273 case DHCP_STATE_REBOOTING
:
1274 case DHCP_STATE_BOUND
:
1277 case DHCP_STATE_STOPPED
:
1283 if (client
->discover_attempt
>= TRANSIENT_FAILURE_ATTEMPTS
)
1284 client_notify(client
, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE
);
1289 /* Avoid REQUEST infinite loop. Per RFC 2131 section 3.1.5: if the client receives
1290 neither a DHCPACK or a DHCPNAK message after employing the retransmission algorithm,
1291 the client reverts to INIT state and restarts the initialization process */
1292 if (client
->request_attempt
>= client
->max_request_attempts
) {
1293 log_dhcp_client(client
, "Max REQUEST attempts reached. Restarting...");
1294 client_restart(client
);
1297 client_stop(client
, r
);
1299 /* Errors were dealt with when stopping the client, don't spill
1300 errors into the event loop handler */
1304 static int client_initialize_io_events(
1305 sd_dhcp_client
*client
,
1306 sd_event_io_handler_t io_callback
) {
1311 assert(client
->event
);
1313 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1314 client
->fd
, EPOLLIN
, io_callback
,
1319 r
= sd_event_source_set_priority(client
->receive_message
,
1320 client
->event_priority
);
1324 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1330 client_stop(client
, r
);
1335 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1340 assert(client
->event
);
1342 (void) event_source_disable(client
->timeout_ipv6_only_mode
);
1344 if (client
->start_delay
> 0) {
1345 assert_se(sd_event_now(client
->event
, CLOCK_BOOTTIME
, &usec
) >= 0);
1346 usec
= usec_add(usec
, client
->start_delay
);
1349 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1352 client_timeout_resend
, client
,
1353 client
->event_priority
, "dhcp4-resend-timer", true);
1355 client_stop(client
, r
);
1361 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1362 client_initialize_io_events(client
, io_callback
);
1363 client_initialize_time_events(client
);
1368 static int client_start_delayed(sd_dhcp_client
*client
) {
1371 assert_return(client
, -EINVAL
);
1372 assert_return(client
->event
, -EINVAL
);
1373 assert_return(client
->ifindex
> 0, -EINVAL
);
1374 assert_return(client
->fd
< 0, -EBUSY
);
1375 assert_return(client
->xid
== 0, -EINVAL
);
1376 assert_return(IN_SET(client
->state
, DHCP_STATE_STOPPED
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1378 client
->xid
= random_u32();
1380 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1381 &client
->hw_addr
, &client
->bcast_addr
,
1382 client
->arp_type
, client
->port
,
1383 client
->socket_priority_set
, client
->socket_priority
);
1385 client_stop(client
, r
);
1390 client
->start_time
= now(CLOCK_BOOTTIME
);
1392 if (client
->state
== DHCP_STATE_STOPPED
)
1393 client
->state
= DHCP_STATE_INIT
;
1395 return client_initialize_events(client
, client_receive_message_raw
);
1398 static int client_start(sd_dhcp_client
*client
) {
1399 client
->start_delay
= 0;
1400 return client_start_delayed(client
);
1403 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1404 sd_dhcp_client
*client
= userdata
;
1405 DHCP_CLIENT_DONT_DESTROY(client
);
1407 log_dhcp_client(client
, "EXPIRED");
1409 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1411 /* lease was lost, start over if not freed or stopped in callback */
1412 if (client
->state
!= DHCP_STATE_STOPPED
) {
1413 client_initialize(client
);
1414 client_start(client
);
1420 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1421 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1422 DHCP_CLIENT_DONT_DESTROY(client
);
1425 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
1426 client
->fd
= safe_close(client
->fd
);
1428 client_set_state(client
, DHCP_STATE_REBINDING
);
1429 client
->discover_attempt
= 0;
1430 client
->request_attempt
= 0;
1432 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1433 &client
->hw_addr
, &client
->bcast_addr
,
1434 client
->arp_type
, client
->port
,
1435 client
->socket_priority_set
, client
->socket_priority
);
1437 client_stop(client
, r
);
1442 return client_initialize_events(client
, client_receive_message_raw
);
1445 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1446 sd_dhcp_client
*client
= userdata
;
1447 DHCP_CLIENT_DONT_DESTROY(client
);
1450 client_set_state(client
, DHCP_STATE_RENEWING
);
1451 else if (client
->state
!= DHCP_STATE_INIT
)
1452 client_set_state(client
, DHCP_STATE_INIT_REBOOT
);
1453 client
->discover_attempt
= 0;
1454 client
->request_attempt
= 0;
1456 return client_initialize_time_events(client
);
1459 static int client_parse_message(
1460 sd_dhcp_client
*client
,
1461 DHCPMessage
*message
,
1463 sd_dhcp_lease
**ret
) {
1465 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1466 _cleanup_free_
char *error_message
= NULL
;
1473 r
= dhcp_lease_new(&lease
);
1477 if (sd_dhcp_client_id_is_set(&client
->client_id
)) {
1478 r
= dhcp_lease_set_client_id(lease
, &client
->client_id
);
1483 r
= dhcp_option_parse(message
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1485 return log_dhcp_client_errno(client
, r
, "Failed to parse DHCP options, ignoring: %m");
1487 switch (client
->state
) {
1488 case DHCP_STATE_SELECTING
:
1489 if (r
== DHCP_ACK
) {
1490 if (!client
->rapid_commit
)
1491 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1492 "received unexpected ACK, ignoring.");
1493 if (!lease
->rapid_commit
)
1494 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1495 "received rapid ACK without Rapid Commit option, ignoring.");
1496 } else if (r
== DHCP_OFFER
) {
1497 if (lease
->rapid_commit
) {
1498 /* Some RFC incompliant servers provides an OFFER with a rapid commit option.
1499 * See https://github.com/systemd/systemd/issues/29904.
1500 * Let's support such servers gracefully. */
1501 log_dhcp_client(client
, "received OFFER with Rapid Commit option, ignoring.");
1502 lease
->rapid_commit
= false;
1504 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1505 lease
->lifetime
= client
->fallback_lease_lifetime
;
1507 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1508 "received unexpected message, ignoring.");
1512 case DHCP_STATE_REBOOTING
:
1513 case DHCP_STATE_REQUESTING
:
1514 case DHCP_STATE_RENEWING
:
1515 case DHCP_STATE_REBINDING
:
1516 if (r
== DHCP_NAK
) {
1517 if (client
->lease
&& client
->lease
->server_address
!= lease
->server_address
)
1518 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1519 "NAK from unexpected server, ignoring: %s",
1520 strna(error_message
));
1521 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EADDRNOTAVAIL
),
1522 "NAK: %s", strna(error_message
));
1525 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1526 "received message was not an ACK, ignoring.");
1530 assert_not_reached();
1533 lease
->next_server
= message
->siaddr
;
1534 lease
->address
= message
->yiaddr
;
1536 if (lease
->address
== 0 ||
1537 lease
->server_address
== 0 ||
1538 lease
->lifetime
== 0)
1539 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1540 "received lease lacks address, server address or lease lifetime, ignoring.");
1542 r
= dhcp_lease_set_default_subnet_mask(lease
);
1544 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1545 "received lease lacks subnet mask, and a fallback one cannot be generated, ignoring.");
1547 /* RFC 8925 section 3.2
1548 * If the client did not include the IPv6-Only Preferred option code in the Parameter Request List in
1549 * the DHCPDISCOVER or DHCPREQUEST message, it MUST ignore the IPv6-Only Preferred option in any
1550 * messages received from the server. */
1551 if (lease
->ipv6_only_preferred_usec
> 0 &&
1552 !client_request_contains(client
, SD_DHCP_OPTION_IPV6_ONLY_PREFERRED
)) {
1553 log_dhcp_client(client
, "Received message with unrequested IPv6-only preferred option, ignoring the option.");
1554 lease
->ipv6_only_preferred_usec
= 0;
1557 *ret
= TAKE_PTR(lease
);
1561 static int client_handle_offer_or_rapid_ack(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
, const triple_timestamp
*timestamp
) {
1562 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1568 r
= client_parse_message(client
, message
, len
, &lease
);
1572 dhcp_lease_set_timestamp(lease
, timestamp
);
1574 dhcp_lease_unref_and_replace(client
->lease
, lease
);
1576 if (client
->lease
->rapid_commit
) {
1577 log_dhcp_client(client
, "ACK");
1578 return SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1581 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1584 log_dhcp_client(client
, "OFFER");
1588 static int client_enter_requesting_now(sd_dhcp_client
*client
) {
1591 client_set_state(client
, DHCP_STATE_REQUESTING
);
1592 client
->discover_attempt
= 0;
1593 client
->request_attempt
= 0;
1595 return event_reset_time(client
->event
, &client
->timeout_resend
,
1596 CLOCK_BOOTTIME
, 0, 0,
1597 client_timeout_resend
, client
,
1598 client
->event_priority
, "dhcp4-resend-timer",
1599 /* force_reset = */ true);
1602 static int client_enter_requesting_delayed(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1603 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1604 DHCP_CLIENT_DONT_DESTROY(client
);
1607 r
= client_enter_requesting_now(client
);
1609 client_stop(client
, r
);
1614 static int client_enter_requesting(sd_dhcp_client
*client
) {
1616 assert(client
->lease
);
1618 (void) event_source_disable(client
->timeout_resend
);
1620 if (client
->lease
->ipv6_only_preferred_usec
> 0) {
1621 if (client
->ipv6_acquired
) {
1622 log_dhcp_client(client
,
1623 "Received an OFFER with IPv6-only preferred option, and the host already acquired IPv6 connectivity, stopping DHCPv4 client.");
1624 return sd_dhcp_client_stop(client
);
1627 log_dhcp_client(client
,
1628 "Received an OFFER with IPv6-only preferred option, delaying to send REQUEST with %s.",
1629 FORMAT_TIMESPAN(client
->lease
->ipv6_only_preferred_usec
, USEC_PER_SEC
));
1631 return event_reset_time_relative(client
->event
, &client
->timeout_ipv6_only_mode
,
1633 client
->lease
->ipv6_only_preferred_usec
, 0,
1634 client_enter_requesting_delayed
, client
,
1635 client
->event_priority
, "dhcp4-ipv6-only-mode-timer",
1636 /* force_reset = */ true);
1639 return client_enter_requesting_now(client
);
1642 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1645 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1646 if (r
!= DHCP_FORCERENEW
)
1650 log_dhcp_client(client
, "FORCERENEW");
1653 /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP
1654 * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW
1655 * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */
1656 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(ENOMSG
),
1657 "Received FORCERENEW, ignoring.");
1661 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1662 if (a
->address
!= b
->address
)
1665 if (a
->subnet_mask
!= b
->subnet_mask
)
1668 if (a
->router_size
!= b
->router_size
)
1671 for (size_t i
= 0; i
< a
->router_size
; i
++)
1672 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1678 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
, const triple_timestamp
*timestamp
) {
1679 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1685 r
= client_parse_message(client
, message
, len
, &lease
);
1689 dhcp_lease_set_timestamp(lease
, timestamp
);
1692 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1693 else if (lease_equal(client
->lease
, lease
))
1694 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1696 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1698 dhcp_lease_unref_and_replace(client
->lease
, lease
);
1700 log_dhcp_client(client
, "ACK");
1704 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1709 assert(client
->event
);
1710 assert(client
->lease
);
1711 assert(client
->lease
->lifetime
> 0);
1712 assert(triple_timestamp_is_set(&client
->lease
->timestamp
));
1714 /* don't set timers for infinite leases */
1715 if (client
->lease
->lifetime
== USEC_INFINITY
) {
1716 (void) event_source_disable(client
->timeout_t1
);
1717 (void) event_source_disable(client
->timeout_t2
);
1718 (void) event_source_disable(client
->timeout_expire
);
1723 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
1727 /* verify that 0 < t2 < lifetime */
1728 if (client
->lease
->t2
== 0 || client
->lease
->t2
>= client
->lease
->lifetime
)
1729 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1730 /* verify that 0 < t1 < lifetime */
1731 if (client
->lease
->t1
== 0 || client
->lease
->t1
>= client
->lease
->t2
)
1732 client
->lease
->t1
= T1_DEFAULT(client
->lease
->lifetime
);
1733 /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
1734 * could not evaluate to false if t1 >= t2; so setting t2 to T2_DEFAULT
1735 * guarantees t1 < t2. */
1736 if (client
->lease
->t1
>= client
->lease
->t2
)
1737 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1739 assert(client
->lease
->t1
> 0);
1740 assert(client
->lease
->t1
< client
->lease
->t2
);
1741 assert(client
->lease
->t2
< client
->lease
->lifetime
);
1743 r
= sd_dhcp_lease_get_lifetime_timestamp(client
->lease
, CLOCK_BOOTTIME
, &client
->expire_time
);
1746 r
= sd_dhcp_lease_get_t1_timestamp(client
->lease
, CLOCK_BOOTTIME
, &client
->t1_time
);
1749 r
= sd_dhcp_lease_get_t2_timestamp(client
->lease
, CLOCK_BOOTTIME
, &client
->t2_time
);
1753 /* RFC2131 section 4.4.5:
1754 * Times T1 and T2 SHOULD be chosen with some random "fuzz".
1755 * Since the RFC doesn't specify here the exact 'fuzz' to use,
1756 * we use the range from section 4.1: -1 to +1 sec. */
1757 client
->t1_time
= usec_sub_signed(client
->t1_time
, RFC2131_RANDOM_FUZZ
);
1758 client
->t2_time
= usec_sub_signed(client
->t2_time
, RFC2131_RANDOM_FUZZ
);
1760 /* after fuzzing, ensure t2 is still >= t1 */
1761 client
->t2_time
= MAX(client
->t1_time
, client
->t2_time
);
1763 /* arm lifetime timeout */
1764 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1766 client
->expire_time
, 10 * USEC_PER_MSEC
,
1767 client_timeout_expire
, client
,
1768 client
->event_priority
, "dhcp4-lifetime", true);
1772 /* don't arm earlier timeouts if this has already expired */
1773 if (client
->expire_time
<= time_now
)
1776 log_dhcp_client(client
, "lease expires in %s",
1777 FORMAT_TIMESPAN(client
->expire_time
- time_now
, USEC_PER_SEC
));
1779 /* arm T2 timeout */
1780 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1782 client
->t2_time
, 10 * USEC_PER_MSEC
,
1783 client_timeout_t2
, client
,
1784 client
->event_priority
, "dhcp4-t2-timeout", true);
1788 /* don't arm earlier timeout if this has already expired */
1789 if (client
->t2_time
<= time_now
)
1792 log_dhcp_client(client
, "T2 expires in %s",
1793 FORMAT_TIMESPAN(client
->t2_time
- time_now
, USEC_PER_SEC
));
1795 /* arm T1 timeout */
1796 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1798 client
->t1_time
, 10 * USEC_PER_MSEC
,
1799 client_timeout_t1
, client
,
1800 client
->event_priority
, "dhcp4-t1-timer", true);
1804 if (client
->t1_time
> time_now
)
1805 log_dhcp_client(client
, "T1 expires in %s",
1806 FORMAT_TIMESPAN(client
->t1_time
- time_now
, USEC_PER_SEC
));
1811 static int client_enter_bound_now(sd_dhcp_client
*client
, int notify_event
) {
1816 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
, DHCP_STATE_REBOOTING
))
1817 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1819 client_set_state(client
, DHCP_STATE_BOUND
);
1820 client
->discover_attempt
= 0;
1821 client
->request_attempt
= 0;
1823 client
->last_addr
= client
->lease
->address
;
1825 r
= client_set_lease_timeouts(client
);
1827 log_dhcp_client_errno(client
, r
, "could not set lease timeouts: %m");
1829 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1831 return log_dhcp_client_errno(client
, r
, "could not bind UDP socket: %m");
1833 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
1834 close_and_replace(client
->fd
, r
);
1835 client_initialize_io_events(client
, client_receive_message_udp
);
1837 client_notify(client
, notify_event
);
1842 static int client_enter_bound_delayed(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1843 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1844 DHCP_CLIENT_DONT_DESTROY(client
);
1847 r
= client_enter_bound_now(client
, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
);
1849 client_stop(client
, r
);
1854 static int client_enter_bound(sd_dhcp_client
*client
, int notify_event
) {
1856 assert(client
->lease
);
1858 client
->start_delay
= 0;
1859 (void) event_source_disable(client
->timeout_resend
);
1861 /* RFC 8925 section 3.2
1862 * If the client is in the INIT-REBOOT state, it SHOULD stop the DHCPv4 configuration process or
1863 * disable the IPv4 stack completely for V6ONLY_WAIT seconds or until the network attachment event,
1864 * whichever happens first.
1866 * In the below, the condition uses REBOOTING, instead of INIT-REBOOT, as the client state has
1867 * already transitioned from INIT-REBOOT to REBOOTING after sending a DHCPREQUEST message. */
1868 if (client
->state
== DHCP_STATE_REBOOTING
&& client
->lease
->ipv6_only_preferred_usec
> 0) {
1869 if (client
->ipv6_acquired
) {
1870 log_dhcp_client(client
,
1871 "Received an ACK with IPv6-only preferred option, and the host already acquired IPv6 connectivity, stopping DHCPv4 client.");
1872 return sd_dhcp_client_stop(client
);
1875 log_dhcp_client(client
,
1876 "Received an ACK with IPv6-only preferred option, delaying to enter bound state with %s.",
1877 FORMAT_TIMESPAN(client
->lease
->ipv6_only_preferred_usec
, USEC_PER_SEC
));
1879 return event_reset_time_relative(client
->event
, &client
->timeout_ipv6_only_mode
,
1881 client
->lease
->ipv6_only_preferred_usec
, 0,
1882 client_enter_bound_delayed
, client
,
1883 client
->event_priority
, "dhcp4-ipv6-only-mode",
1884 /* force_reset = */ true);
1887 return client_enter_bound_now(client
, notify_event
);
1890 static int client_restart(sd_dhcp_client
*client
) {
1894 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1896 r
= client_initialize(client
);
1900 r
= client_start_delayed(client
);
1904 log_dhcp_client(client
, "REBOOT in %s", FORMAT_TIMESPAN(client
->start_delay
, USEC_PER_SEC
));
1906 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1907 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1911 static int client_verify_message_header(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
) {
1912 const uint8_t *expected_chaddr
= NULL
;
1913 uint8_t expected_hlen
= 0;
1918 if (len
< sizeof(DHCPMessage
))
1919 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
1920 "Too small to be a DHCP message, ignoring.");
1922 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
)
1923 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
1924 "Not a DHCP message, ignoring.");
1926 if (message
->op
!= BOOTREPLY
)
1927 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
1928 "Not a BOOTREPLY message, ignoring.");
1930 if (message
->htype
!= client
->arp_type
)
1931 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
1932 "Packet type does not match client type, ignoring.");
1934 if (client
->arp_type
== ARPHRD_ETHER
) {
1935 expected_hlen
= ETH_ALEN
;
1936 expected_chaddr
= client
->hw_addr
.bytes
;
1939 if (message
->hlen
!= expected_hlen
)
1940 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
1941 "Received packet hlen (%u) does not match expected (%u), ignoring.",
1942 message
->hlen
, expected_hlen
);
1944 if (memcmp_safe(message
->chaddr
, expected_chaddr
, expected_hlen
))
1945 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
1946 "Received chaddr does not match expected, ignoring.");
1948 if (client
->state
!= DHCP_STATE_BOUND
&&
1949 be32toh(message
->xid
) != client
->xid
)
1950 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1951 so ignore the xid in this case */
1952 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EBADMSG
),
1953 "Received xid (%u) does not match expected (%u), ignoring.",
1954 be32toh(message
->xid
), client
->xid
);
1959 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, size_t len
, const triple_timestamp
*timestamp
) {
1960 DHCP_CLIENT_DONT_DESTROY(client
);
1967 if (client_verify_message_header(client
, message
, len
) < 0)
1970 switch (client
->state
) {
1971 case DHCP_STATE_SELECTING
:
1973 r
= client_handle_offer_or_rapid_ack(client
, message
, len
, timestamp
);
1974 if (ERRNO_IS_NEG_RESOURCE(r
))
1976 if (r
== -EADDRNOTAVAIL
)
1977 /* got a rapid NAK, let's restart the client */
1978 return client_restart(client
);
1980 return 0; /* invalid message, let's ignore it */
1982 if (client
->lease
->rapid_commit
)
1983 /* got a successful rapid commit */
1984 return client_enter_bound(client
, r
);
1986 return client_enter_requesting(client
);
1988 case DHCP_STATE_REBOOTING
:
1989 case DHCP_STATE_REQUESTING
:
1990 case DHCP_STATE_RENEWING
:
1991 case DHCP_STATE_REBINDING
:
1993 r
= client_handle_ack(client
, message
, len
, timestamp
);
1994 if (ERRNO_IS_NEG_RESOURCE(r
))
1996 if (r
== -EADDRNOTAVAIL
)
1997 /* got a NAK, let's restart the client */
1998 return client_restart(client
);
2000 return 0; /* invalid message, let's ignore it */
2002 return client_enter_bound(client
, r
);
2004 case DHCP_STATE_BOUND
:
2005 r
= client_handle_forcerenew(client
, message
, len
);
2006 if (ERRNO_IS_NEG_RESOURCE(r
))
2009 return 0; /* invalid message, let's ignore it */
2011 return client_timeout_t1(NULL
, 0, client
);
2013 case DHCP_STATE_INIT
:
2014 case DHCP_STATE_INIT_REBOOT
:
2015 log_dhcp_client(client
, "Unexpectedly receive message without sending any requests, ignoring.");
2019 assert_not_reached();
2025 static int client_receive_message_udp(
2031 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
2032 _cleanup_free_ DHCPMessage
*message
= NULL
;
2033 ssize_t len
, buflen
;
2034 /* This needs to be initialized with zero. See #20741. */
2035 CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL
) control
= {};
2037 struct msghdr msg
= {
2040 .msg_control
= &control
,
2041 .msg_controllen
= sizeof(control
),
2047 buflen
= next_datagram_size_fd(fd
);
2048 if (ERRNO_IS_NEG_TRANSIENT(buflen
) || ERRNO_IS_NEG_DISCONNECT(buflen
))
2051 log_dhcp_client_errno(client
, buflen
, "Failed to determine datagram size to read, ignoring: %m");
2055 message
= malloc0(buflen
);
2059 iov
= IOVEC_MAKE(message
, buflen
);
2061 len
= recvmsg_safe(fd
, &msg
, MSG_DONTWAIT
);
2062 if (ERRNO_IS_NEG_TRANSIENT(len
) || ERRNO_IS_NEG_DISCONNECT(len
))
2065 log_dhcp_client_errno(client
, len
, "Could not receive message from UDP socket, ignoring: %m");
2069 log_dhcp_client(client
, "Received message from UDP socket, processing.");
2070 r
= client_handle_message(client
, message
, len
, TRIPLE_TIMESTAMP_FROM_CMSG(&msg
));
2072 client_stop(client
, r
);
2077 static int client_receive_message_raw(
2083 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
2084 _cleanup_free_ DHCPPacket
*packet
= NULL
;
2085 /* This needs to be initialized with zero. See #20741. */
2086 CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL
+
2087 CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
= {};
2088 struct iovec iov
= {};
2089 struct msghdr msg
= {
2092 .msg_control
= &control
,
2093 .msg_controllen
= sizeof(control
),
2095 bool checksum
= true;
2096 ssize_t buflen
, len
;
2101 buflen
= next_datagram_size_fd(fd
);
2102 if (ERRNO_IS_NEG_TRANSIENT(buflen
) || ERRNO_IS_NEG_DISCONNECT(buflen
))
2105 log_dhcp_client_errno(client
, buflen
, "Failed to determine datagram size to read, ignoring: %m");
2109 packet
= malloc0(buflen
);
2113 iov
= IOVEC_MAKE(packet
, buflen
);
2115 len
= recvmsg_safe(fd
, &msg
, 0);
2116 if (ERRNO_IS_NEG_TRANSIENT(len
) || ERRNO_IS_NEG_DISCONNECT(len
))
2119 log_dhcp_client_errno(client
, len
, "Could not receive message from raw socket, ignoring: %m");
2123 struct tpacket_auxdata
*aux
= CMSG_FIND_DATA(&msg
, SOL_PACKET
, PACKET_AUXDATA
, struct tpacket_auxdata
);
2125 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2127 if (dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
) < 0)
2130 len
-= DHCP_IP_UDP_SIZE
;
2132 log_dhcp_client(client
, "Received message from RAW socket, processing.");
2133 r
= client_handle_message(client
, &packet
->dhcp
, len
, TRIPLE_TIMESTAMP_FROM_CMSG(&msg
));
2135 client_stop(client
, r
);
2140 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2141 if (!sd_dhcp_client_is_running(client
) || client
->state
!= DHCP_STATE_BOUND
)
2142 return 0; /* do nothing */
2144 client
->start_delay
= 0;
2145 client
->discover_attempt
= 1;
2146 client
->request_attempt
= 1;
2147 client_set_state(client
, DHCP_STATE_RENEWING
);
2149 return client_initialize_time_events(client
);
2152 int sd_dhcp_client_is_running(sd_dhcp_client
*client
) {
2156 return client
->state
!= DHCP_STATE_STOPPED
;
2159 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2162 assert_return(client
, -EINVAL
);
2164 /* Note, do not reset the flag in client_initialize(), as it is also called on expire. */
2165 client
->ipv6_acquired
= false;
2167 r
= client_initialize(client
);
2171 /* If no client identifier exists, construct an RFC 4361-compliant one */
2172 if (!sd_dhcp_client_id_is_set(&client
->client_id
)) {
2173 r
= sd_dhcp_client_set_iaid_duid_en(client
, /* iaid_set = */ false, /* iaid = */ 0);
2178 /* RFC7844 section 3.3:
2179 SHOULD perform a complete four-way handshake, starting with a
2180 DHCPDISCOVER, to obtain a new address lease. If the client can
2181 ascertain that this is exactly the same network to which it was
2182 previously connected, and if the link-layer address did not change,
2183 the client MAY issue a DHCPREQUEST to try to reclaim the current
2185 if (client
->last_addr
&& !client
->anonymize
)
2186 client_set_state(client
, DHCP_STATE_INIT_REBOOT
);
2188 r
= client_start(client
);
2190 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2195 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2196 _cleanup_free_ DHCPPacket
*release
= NULL
;
2197 size_t optoffset
, optlen
;
2200 if (!sd_dhcp_client_is_running(client
) || !client
->lease
)
2201 return 0; /* do nothing */
2203 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2207 /* Fill up release IP and MAC */
2208 release
->dhcp
.ciaddr
= client
->lease
->address
;
2209 memcpy(&release
->dhcp
.chaddr
, client
->hw_addr
.bytes
, client
->hw_addr
.length
);
2211 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2212 SD_DHCP_OPTION_END
, 0, NULL
);
2216 r
= dhcp_network_send_udp_socket(client
->fd
,
2217 client
->lease
->server_address
,
2218 client
->server_port
,
2220 sizeof(DHCPMessage
) + optoffset
);
2224 log_dhcp_client(client
, "RELEASE");
2226 /* This function is mostly called when stopping daemon. Hence, do not call client_stop() or
2227 * client_restart(). Otherwise, the notification callback will be called again and we may easily
2228 * enter an infinite loop. */
2229 client_initialize(client
);
2230 return 1; /* sent and stopped. */
2233 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2234 _cleanup_free_ DHCPPacket
*release
= NULL
;
2235 size_t optoffset
, optlen
;
2238 if (!sd_dhcp_client_is_running(client
) || !client
->lease
)
2239 return 0; /* do nothing */
2241 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2245 release
->dhcp
.ciaddr
= client
->lease
->address
;
2246 memcpy(&release
->dhcp
.chaddr
, client
->hw_addr
.bytes
, client
->hw_addr
.length
);
2248 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2249 SD_DHCP_OPTION_END
, 0, NULL
);
2253 r
= dhcp_network_send_udp_socket(client
->fd
,
2254 client
->lease
->server_address
,
2255 client
->server_port
,
2257 sizeof(DHCPMessage
) + optoffset
);
2261 log_dhcp_client(client
, "DECLINE");
2263 /* This function is mostly called when the acquired address conflicts with another host.
2264 * Restarting the daemon to acquire another address. */
2265 r
= client_restart(client
);
2269 return 1; /* sent and restarted. */
2272 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2276 DHCP_CLIENT_DONT_DESTROY(client
);
2278 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2283 int sd_dhcp_client_set_ipv6_connectivity(sd_dhcp_client
*client
, int have
) {
2287 /* We have already received a message with IPv6-Only preferred option, and are waiting for IPv6
2288 * connectivity or timeout, let's stop the client. */
2289 if (have
&& sd_event_source_get_enabled(client
->timeout_ipv6_only_mode
, NULL
) > 0)
2290 return sd_dhcp_client_stop(client
);
2292 /* Otherwise, save that the host already has IPv6 connectivity. */
2293 client
->ipv6_acquired
= have
;
2297 int sd_dhcp_client_interrupt_ipv6_only_mode(sd_dhcp_client
*client
) {
2298 assert_return(client
, -EINVAL
);
2299 assert_return(sd_dhcp_client_is_running(client
), -ESTALE
);
2300 assert_return(client
->fd
>= 0, -EINVAL
);
2302 if (sd_event_source_get_enabled(client
->timeout_ipv6_only_mode
, NULL
) <= 0)
2305 client_initialize(client
);
2306 return client_start(client
);
2309 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2312 assert_return(client
, -EINVAL
);
2313 assert_return(!client
->event
, -EBUSY
);
2314 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
2317 client
->event
= sd_event_ref(event
);
2319 r
= sd_event_default(&client
->event
);
2324 client
->event_priority
= priority
;
2329 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2330 assert_return(client
, -EINVAL
);
2331 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
2333 client
->event
= sd_event_unref(client
->event
);
2338 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2339 assert_return(client
, NULL
);
2341 return client
->event
;
2344 int sd_dhcp_client_attach_device(sd_dhcp_client
*client
, sd_device
*dev
) {
2345 assert_return(client
, -EINVAL
);
2347 return device_unref_and_replace(client
->dev
, dev
);
2350 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2354 log_dhcp_client(client
, "FREE");
2356 client_initialize(client
);
2358 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2359 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2360 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2361 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2363 sd_dhcp_client_detach_event(client
);
2365 sd_device_unref(client
->dev
);
2367 set_free(client
->req_opts
);
2368 free(client
->hostname
);
2369 free(client
->vendor_class_identifier
);
2370 free(client
->mudurl
);
2371 client
->user_class
= strv_free(client
->user_class
);
2372 ordered_hashmap_free(client
->extra_options
);
2373 ordered_hashmap_free(client
->vendor_options
);
2374 free(client
->ifname
);
2375 return mfree(client
);
2378 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2380 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2381 const uint8_t *opts
;
2385 assert_return(ret
, -EINVAL
);
2387 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2391 *client
= (sd_dhcp_client
) {
2393 .state
= DHCP_STATE_STOPPED
,
2396 .mtu
= DHCP_MIN_PACKET_SIZE
,
2397 .port
= DHCP_PORT_CLIENT
,
2398 .server_port
= DHCP_PORT_SERVER
,
2399 .anonymize
= !!anonymize
,
2400 .max_discover_attempts
= UINT64_MAX
,
2401 .max_request_attempts
= 5,
2402 .ip_service_type
= -1,
2404 /* NOTE: this could be moved to a function. */
2406 n_opts
= ELEMENTSOF(default_req_opts_anonymize
);
2407 opts
= default_req_opts_anonymize
;
2409 n_opts
= ELEMENTSOF(default_req_opts
);
2410 opts
= default_req_opts
;
2413 for (size_t i
= 0; i
< n_opts
; i
++) {
2414 r
= sd_dhcp_client_set_request_option(client
, opts
[i
]);
2419 *ret
= TAKE_PTR(client
);
2424 static const char* const dhcp_state_table
[_DHCP_STATE_MAX
] = {
2425 [DHCP_STATE_STOPPED
] = "stopped",
2426 [DHCP_STATE_INIT
] = "initialization",
2427 [DHCP_STATE_SELECTING
] = "selecting",
2428 [DHCP_STATE_INIT_REBOOT
] = "init-reboot",
2429 [DHCP_STATE_REBOOTING
] = "rebooting",
2430 [DHCP_STATE_REQUESTING
] = "requesting",
2431 [DHCP_STATE_BOUND
] = "bound",
2432 [DHCP_STATE_RENEWING
] = "renewing",
2433 [DHCP_STATE_REBINDING
] = "rebinding",
2436 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(dhcp_state
, DHCPState
);