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-identifier.h"
19 #include "dhcp-internal.h"
20 #include "dhcp-lease-internal.h"
21 #include "dhcp-protocol.h"
22 #include "dns-domain.h"
23 #include "ether-addr-util.h"
24 #include "event-util.h"
26 #include "hostname-util.h"
28 #include "memory-util.h"
29 #include "network-common.h"
30 #include "random-util.h"
32 #include "sort-util.h"
33 #include "string-util.h"
35 #include "time-util.h"
39 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
40 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
42 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
43 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
45 #define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
46 * transient failure. */
48 typedef struct sd_dhcp_client_id
{
52 /* 0: Generic (non-LL) (RFC 2132) */
53 uint8_t data
[MAX_CLIENT_ID_LEN
];
56 /* 1: Ethernet Link-Layer (RFC 2132) */
57 uint8_t haddr
[ETH_ALEN
];
60 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
64 /* 255: Node-specific (RFC 4361) */
69 uint8_t data
[MAX_CLIENT_ID_LEN
];
72 } _packed_ sd_dhcp_client_id
;
74 struct sd_dhcp_client
{
80 sd_event_source
*timeout_resend
;
89 union sockaddr_union link
;
90 sd_event_source
*receive_message
;
91 bool request_broadcast
;
95 struct hw_addr_data hw_addr
;
96 struct hw_addr_data bcast_addr
;
98 sd_dhcp_client_id client_id
;
101 char *vendor_class_identifier
;
105 uint32_t fallback_lease_lifetime
;
112 uint64_t max_attempts
;
113 OrderedHashmap
*extra_options
;
114 OrderedHashmap
*vendor_options
;
116 sd_event_source
*timeout_t1
;
117 sd_event_source
*timeout_t2
;
118 sd_event_source
*timeout_expire
;
119 sd_dhcp_client_callback_t callback
;
121 sd_dhcp_lease
*lease
;
125 bool socket_priority_set
;
127 /* Ignore machine-ID when generating DUID. See dhcp_identifier_set_duid_en(). */
131 static const uint8_t default_req_opts
[] = {
132 SD_DHCP_OPTION_SUBNET_MASK
,
133 SD_DHCP_OPTION_ROUTER
,
134 SD_DHCP_OPTION_HOST_NAME
,
135 SD_DHCP_OPTION_DOMAIN_NAME
,
136 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
139 /* RFC7844 section 3:
140 MAY contain the Parameter Request List option.
142 The client intending to protect its privacy SHOULD only request a
143 minimal number of options in the PRL and SHOULD also randomly shuffle
144 the ordering of option codes in the PRL. If this random ordering
145 cannot be implemented, the client MAY order the option codes in the
146 PRL by option code number (lowest to highest).
148 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
149 static const uint8_t default_req_opts_anonymize
[] = {
150 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
151 SD_DHCP_OPTION_ROUTER
, /* 3 */
152 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
153 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
154 SD_DHCP_OPTION_ROUTER_DISCOVERY
, /* 31 */
155 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
156 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
157 SD_DHCP_OPTION_NETBIOS_NAME_SERVER
, /* 44 */
158 SD_DHCP_OPTION_NETBIOS_NODE_TYPE
, /* 46 */
159 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
160 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
161 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
162 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
165 static int client_receive_message_raw(
170 static int client_receive_message_udp(
175 static void client_stop(sd_dhcp_client
*client
, int error
);
177 int sd_dhcp_client_id_to_string(const void *data
, size_t len
, char **ret
) {
178 const sd_dhcp_client_id
*client_id
= data
;
179 _cleanup_free_
char *t
= NULL
;
182 assert_return(data
, -EINVAL
);
183 assert_return(len
>= 1, -EINVAL
);
184 assert_return(ret
, -EINVAL
);
187 if (len
> MAX_CLIENT_ID_LEN
)
190 switch (client_id
->type
) {
192 if (utf8_is_printable((char *) client_id
->gen
.data
, len
))
193 r
= asprintf(&t
, "%.*s", (int) len
, client_id
->gen
.data
);
195 r
= asprintf(&t
, "DATA");
198 if (len
== sizeof_field(sd_dhcp_client_id
, eth
))
199 r
= asprintf(&t
, "%02x:%02x:%02x:%02x:%02x:%02x",
200 client_id
->eth
.haddr
[0],
201 client_id
->eth
.haddr
[1],
202 client_id
->eth
.haddr
[2],
203 client_id
->eth
.haddr
[3],
204 client_id
->eth
.haddr
[4],
205 client_id
->eth
.haddr
[5]);
207 r
= asprintf(&t
, "ETHER");
210 r
= asprintf(&t
, "ARP/LL");
213 if (len
< sizeof(uint32_t))
214 r
= asprintf(&t
, "IAID/DUID");
216 uint32_t iaid
= be32toh(client_id
->ns
.iaid
);
217 /* TODO: check and stringify DUID */
218 r
= asprintf(&t
, "IAID:0x%x/DUID", iaid
);
229 int sd_dhcp_client_set_callback(
230 sd_dhcp_client
*client
,
231 sd_dhcp_client_callback_t cb
,
234 assert_return(client
, -EINVAL
);
236 client
->callback
= cb
;
237 client
->userdata
= userdata
;
242 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
243 assert_return(client
, -EINVAL
);
244 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
246 client
->request_broadcast
= broadcast
;
251 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
252 assert_return(client
, -EINVAL
);
253 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
257 case SD_DHCP_OPTION_PAD
:
258 case SD_DHCP_OPTION_OVERLOAD
:
259 case SD_DHCP_OPTION_MESSAGE_TYPE
:
260 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
261 case SD_DHCP_OPTION_END
:
268 return set_ensure_put(&client
->req_opts
, NULL
, UINT8_TO_PTR(option
));
271 int sd_dhcp_client_set_request_address(
272 sd_dhcp_client
*client
,
273 const struct in_addr
*last_addr
) {
275 assert_return(client
, -EINVAL
);
276 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
279 client
->last_addr
= last_addr
->s_addr
;
281 client
->last_addr
= INADDR_ANY
;
286 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
287 assert_return(client
, -EINVAL
);
288 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
289 assert_return(ifindex
> 0, -EINVAL
);
291 client
->ifindex
= ifindex
;
295 int sd_dhcp_client_set_ifname(sd_dhcp_client
*client
, const char *ifname
) {
296 assert_return(client
, -EINVAL
);
297 assert_return(ifname
, -EINVAL
);
299 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
302 return free_and_strdup(&client
->ifname
, ifname
);
305 int sd_dhcp_client_get_ifname(sd_dhcp_client
*client
, const char **ret
) {
308 assert_return(client
, -EINVAL
);
310 r
= get_ifname(client
->ifindex
, &client
->ifname
);
315 *ret
= client
->ifname
;
320 int sd_dhcp_client_set_mac(
321 sd_dhcp_client
*client
,
322 const uint8_t *hw_addr
,
323 const uint8_t *bcast_addr
,
327 assert_return(client
, -EINVAL
);
328 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
329 assert_return(IN_SET(arp_type
, ARPHRD_ETHER
, ARPHRD_INFINIBAND
), -EINVAL
);
330 assert_return(hw_addr
, -EINVAL
);
331 assert_return(addr_len
== (arp_type
== ARPHRD_ETHER
? ETH_ALEN
: INFINIBAND_ALEN
), -EINVAL
);
333 client
->arp_type
= arp_type
;
334 hw_addr_set(&client
->hw_addr
, hw_addr
, addr_len
);
335 hw_addr_set(&client
->bcast_addr
, bcast_addr
, bcast_addr
? addr_len
: 0);
340 int sd_dhcp_client_get_client_id(
341 sd_dhcp_client
*client
,
343 const uint8_t **ret_data
,
344 size_t *ret_data_len
) {
346 assert_return(client
, -EINVAL
);
348 if (client
->client_id_len
> 0) {
349 if (client
->client_id_len
<= offsetof(sd_dhcp_client_id
, raw
.data
))
353 *ret_type
= client
->client_id
.type
;
355 *ret_data
= client
->client_id
.raw
.data
;
357 *ret_data_len
= client
->client_id_len
- offsetof(sd_dhcp_client_id
, raw
.data
);
371 int sd_dhcp_client_set_client_id(
372 sd_dhcp_client
*client
,
377 assert_return(client
, -EINVAL
);
378 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
379 assert_return(data
, -EINVAL
);
380 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
382 /* For hardware types, log debug message about unexpected data length.
384 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
385 * the last 8 bytes of the address are stable and suitable to put into
386 * the client-id. The caller is advised to account for that. */
387 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
388 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
389 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
390 "unexpected address length %zu",
393 client
->client_id
.type
= type
;
394 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
395 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
401 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
402 * without further modification. Otherwise, if duid_type is supported, DUID
403 * is set based on that type. Otherwise, an error is returned.
405 static int dhcp_client_set_iaid(
406 sd_dhcp_client
*client
,
412 assert_return(client
, -EINVAL
);
413 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
415 zero(client
->client_id
);
416 client
->client_id
.type
= 255;
419 client
->client_id
.ns
.iaid
= htobe32(iaid
);
421 r
= dhcp_identifier_set_iaid(client
->dev
, &client
->hw_addr
,
422 /* legacy_unstable_byteorder = */ true,
423 &client
->client_id
.ns
.iaid
);
425 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
431 int sd_dhcp_client_set_iaid_duid_llt(
432 sd_dhcp_client
*client
,
440 assert_return(client
, -EINVAL
);
441 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
443 r
= dhcp_client_set_iaid(client
, iaid_set
, iaid
);
447 r
= dhcp_identifier_set_duid_llt(&client
->hw_addr
, client
->arp_type
, llt_time
, &client
->client_id
.ns
.duid
, &len
);
449 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
451 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + len
;
456 int sd_dhcp_client_set_iaid_duid_ll(
457 sd_dhcp_client
*client
,
464 assert_return(client
, -EINVAL
);
465 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
467 r
= dhcp_client_set_iaid(client
, iaid_set
, iaid
);
471 r
= dhcp_identifier_set_duid_ll(&client
->hw_addr
, client
->arp_type
, &client
->client_id
.ns
.duid
, &len
);
473 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
475 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + len
;
480 int sd_dhcp_client_set_iaid_duid_en(
481 sd_dhcp_client
*client
,
488 assert_return(client
, -EINVAL
);
489 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
491 r
= dhcp_client_set_iaid(client
, iaid_set
, iaid
);
495 r
= dhcp_identifier_set_duid_en(client
->test_mode
, &client
->client_id
.ns
.duid
, &len
);
497 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
499 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + len
;
504 int sd_dhcp_client_set_iaid_duid_uuid(
505 sd_dhcp_client
*client
,
512 assert_return(client
, -EINVAL
);
513 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
515 r
= dhcp_client_set_iaid(client
, iaid_set
, iaid
);
519 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
521 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
523 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + len
;
528 int sd_dhcp_client_set_iaid_duid_raw(
529 sd_dhcp_client
*client
,
539 assert_return(client
, -EINVAL
);
540 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
541 assert_return(duid
|| duid_len
== 0, -EINVAL
);
543 r
= dhcp_client_set_iaid(client
, iaid_set
, iaid
);
547 r
= dhcp_identifier_set_duid_raw(duid_type
, duid
, duid_len
, &client
->client_id
.ns
.duid
, &len
);
549 return log_dhcp_client_errno(client
, r
, "Failed to set DUID: %m");
551 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + len
;
556 void dhcp_client_set_test_mode(sd_dhcp_client
*client
, bool test_mode
) {
559 client
->test_mode
= test_mode
;
562 int sd_dhcp_client_set_hostname(
563 sd_dhcp_client
*client
,
564 const char *hostname
) {
566 assert_return(client
, -EINVAL
);
567 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
569 /* Make sure hostnames qualify as DNS and as Linux hostnames */
571 !(hostname_is_valid(hostname
, 0) && dns_name_is_valid(hostname
) > 0))
574 return free_and_strdup(&client
->hostname
, hostname
);
577 int sd_dhcp_client_set_vendor_class_identifier(
578 sd_dhcp_client
*client
,
581 assert_return(client
, -EINVAL
);
582 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
584 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
587 int sd_dhcp_client_set_mud_url(
588 sd_dhcp_client
*client
,
589 const char *mudurl
) {
591 assert_return(client
, -EINVAL
);
592 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
593 assert_return(mudurl
, -EINVAL
);
594 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
595 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
597 return free_and_strdup(&client
->mudurl
, mudurl
);
600 int sd_dhcp_client_set_user_class(
601 sd_dhcp_client
*client
,
602 char * const *user_class
) {
606 assert_return(client
, -EINVAL
);
607 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
608 assert_return(!strv_isempty(user_class
), -EINVAL
);
610 STRV_FOREACH(p
, user_class
) {
611 size_t n
= strlen(*p
);
613 if (n
> 255 || n
== 0)
617 s
= strv_copy(user_class
);
621 return strv_free_and_replace(client
->user_class
, s
);
624 int sd_dhcp_client_set_client_port(
625 sd_dhcp_client
*client
,
628 assert_return(client
, -EINVAL
);
629 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
636 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
637 assert_return(client
, -EINVAL
);
638 assert_return(mtu
>= DHCP_MIN_PACKET_SIZE
, -ERANGE
);
640 /* MTU may be changed by the acquired lease. Hence, we cannot require that the client is stopped here.
641 * Please do not add assertion for !sd_dhcp_client_is_running(client) here. */
648 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
649 assert_return(client
, -EINVAL
);
650 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
652 client
->max_attempts
= max_attempts
;
657 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
660 assert_return(client
, -EINVAL
);
661 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
662 assert_return(v
, -EINVAL
);
664 r
= ordered_hashmap_ensure_put(&client
->extra_options
, &dhcp_option_hash_ops
, UINT_TO_PTR(v
->option
), v
);
668 sd_dhcp_option_ref(v
);
672 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
675 assert_return(client
, -EINVAL
);
676 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
677 assert_return(v
, -EINVAL
);
679 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
683 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
687 sd_dhcp_option_ref(v
);
692 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
693 assert_return(client
, -EINVAL
);
695 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
696 return -EADDRNOTAVAIL
;
699 *ret
= client
->lease
;
704 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
705 assert_return(client
, -EINVAL
);
706 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
708 client
->ip_service_type
= type
;
713 int sd_dhcp_client_set_socket_priority(sd_dhcp_client
*client
, int socket_priority
) {
714 assert_return(client
, -EINVAL
);
715 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
717 client
->socket_priority_set
= true;
718 client
->socket_priority
= socket_priority
;
723 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint32_t fallback_lease_lifetime
) {
724 assert_return(client
, -EINVAL
);
725 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
726 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
728 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
733 static int client_notify(sd_dhcp_client
*client
, int event
) {
736 if (client
->callback
)
737 return client
->callback(client
, event
, client
->userdata
);
742 static int client_initialize(sd_dhcp_client
*client
) {
743 assert_return(client
, -EINVAL
);
745 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
747 client
->fd
= safe_close(client
->fd
);
749 (void) event_source_disable(client
->timeout_resend
);
750 (void) event_source_disable(client
->timeout_t1
);
751 (void) event_source_disable(client
->timeout_t2
);
752 (void) event_source_disable(client
->timeout_expire
);
756 client
->state
= DHCP_STATE_INIT
;
759 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
764 static void client_stop(sd_dhcp_client
*client
, int error
) {
768 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
769 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
770 log_dhcp_client(client
, "STOPPED");
772 log_dhcp_client(client
, "STOPPED: Unknown event");
774 client_notify(client
, error
);
776 client_initialize(client
);
779 /* RFC2131 section 4.1:
780 * retransmission delays should include -1 to +1 sec of random 'fuzz'. */
781 #define RFC2131_RANDOM_FUZZ \
782 ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
784 /* RFC2131 section 4.1:
785 * for retransmission delays, timeout should start at 4s then double
786 * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
787 * This assumes the first call will be using attempt 1. */
788 static usec_t
client_compute_request_timeout(usec_t now
, uint64_t attempt
) {
789 usec_t timeout
= (UINT64_C(1) << MIN(attempt
+ 1, UINT64_C(6))) * USEC_PER_SEC
;
791 return usec_sub_signed(usec_add(now
, timeout
), RFC2131_RANDOM_FUZZ
);
794 /* RFC2131 section 4.4.5:
795 * T1 defaults to (0.5 * duration_of_lease).
796 * T2 defaults to (0.875 * duration_of_lease). */
797 #define T1_DEFAULT(lifetime) ((lifetime) / 2)
798 #define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
800 /* RFC2131 section 4.4.5:
801 * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
802 * and one-half of the remaining lease time (in REBINDING state), down to a minimum
804 * Note that while the default T1/T2 initial times do have random 'fuzz' applied,
805 * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
806 static usec_t
client_compute_reacquisition_timeout(usec_t now
, usec_t expire
) {
807 return now
+ MAX(usec_sub_unsigned(expire
, now
) / 2, 60 * USEC_PER_SEC
);
810 static int cmp_uint8(const uint8_t *a
, const uint8_t *b
) {
814 static int client_message_init(
815 sd_dhcp_client
*client
,
819 size_t *_optoffset
) {
821 _cleanup_free_ DHCPPacket
*packet
= NULL
;
822 size_t optlen
, optoffset
, size
;
828 assert(client
->start_time
);
832 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
834 optlen
= DHCP_MIN_OPTIONS_SIZE
;
835 size
= sizeof(DHCPPacket
) + optlen
;
837 packet
= malloc0(size
);
841 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
842 client
->arp_type
, client
->hw_addr
.length
, client
->hw_addr
.bytes
,
847 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
848 refuse to issue an DHCP lease if 'secs' is set to zero */
849 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
852 assert(time_now
>= client
->start_time
);
854 /* seconds between sending first and last DISCOVER
855 * must always be strictly positive to deal with broken servers */
856 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ?: 1;
857 packet
->dhcp
.secs
= htobe16(secs
);
859 /* RFC2131 section 4.1
860 A client that cannot receive unicast IP datagrams until its protocol
861 software has been configured with an IP address SHOULD set the
862 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
863 DHCPREQUEST messages that client sends. The BROADCAST bit will
864 provide a hint to the DHCP server and BOOTP relay agent to broadcast
865 any messages to the client on the client's subnet.
867 Note: some interfaces needs this to be enabled, but some networks
868 needs this to be disabled as broadcasts are filteretd, so this
869 needs to be configurable */
870 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
871 packet
->dhcp
.flags
= htobe16(0x8000);
873 /* If no client identifier exists, construct an RFC 4361-compliant one */
874 if (client
->client_id_len
== 0) {
875 r
= sd_dhcp_client_set_iaid_duid_en(client
, /* iaid_set = */ false, /* iaid = */ 0);
880 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
881 Identifier option is not set */
882 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
883 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
884 client
->client_id_len
,
889 /* RFC2131 section 3.5:
890 in its initial DHCPDISCOVER or DHCPREQUEST message, a
891 client may provide the server with a list of specific
892 parameters the client is interested in. If the client
893 includes a list of parameters in a DHCPDISCOVER message,
894 it MUST include that list in any subsequent DHCPREQUEST
898 /* RFC7844 section 3:
899 MAY contain the Parameter Request List option. */
900 /* NOTE: in case that there would be an option to do not send
901 * any PRL at all, the size should be checked before sending */
902 if (!set_isempty(client
->req_opts
) && type
!= DHCP_RELEASE
) {
903 _cleanup_free_
uint8_t *opts
= NULL
;
904 size_t n_opts
, i
= 0;
907 n_opts
= set_size(client
->req_opts
);
908 opts
= new(uint8_t, n_opts
);
912 SET_FOREACH(val
, client
->req_opts
)
913 opts
[i
++] = PTR_TO_UINT8(val
);
916 /* For anonymizing the request, let's sort the options. */
917 typesafe_qsort(opts
, n_opts
, cmp_uint8
);
919 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
920 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
926 /* RFC2131 section 3.5:
927 The client SHOULD include the ’maximum DHCP message size’ option to
928 let the server know how large the server may make its DHCP messages.
930 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
931 than the defined default size unless the Maximum Message Size option
934 RFC3442 "Requirements to Avoid Sizing Constraints":
935 Because a full routing table can be quite large, the standard 576
936 octet maximum size for a DHCP message may be too short to contain
937 some legitimate Classless Static Route options. Because of this,
938 clients implementing the Classless Static Route option SHOULD send a
939 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
940 stack is capable of receiving larger IP datagrams. In this case, the
941 client SHOULD set the value of this option to at least the MTU of the
942 interface that the client is configuring. The client MAY set the
943 value of this option higher, up to the size of the largest UDP packet
944 it is prepared to accept. (Note that the value specified in the
945 Maximum DHCP Message Size option is the total maximum packet size,
946 including IP and UDP headers.)
948 /* RFC7844 section 3:
949 SHOULD NOT contain any other option. */
950 if (!client
->anonymize
&& IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
)) {
951 be16_t max_size
= htobe16(MIN(client
->mtu
- DHCP_IP_UDP_SIZE
, (uint32_t) UINT16_MAX
));
952 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
953 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
960 *_optoffset
= optoffset
;
961 *ret
= TAKE_PTR(packet
);
966 static int client_append_fqdn_option(
967 DHCPMessage
*message
,
972 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
975 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
976 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
977 buffer
[1] = 0; /* RCODE1 (deprecated) */
978 buffer
[2] = 0; /* RCODE2 (deprecated) */
980 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
982 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
983 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
988 static int dhcp_client_send_raw(
989 sd_dhcp_client
*client
,
993 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
994 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
996 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
1000 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
1006 if (client
->hostname
) {
1007 /* According to RFC 4702 "clients that send the Client FQDN option in
1008 their messages MUST NOT also send the Host Name option". Just send
1009 one of the two depending on the hostname type.
1011 if (dns_name_is_single_label(client
->hostname
)) {
1012 /* it is unclear from RFC 2131 if client should send hostname in
1013 DHCPDISCOVER but dhclient does and so we do as well
1015 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1016 SD_DHCP_OPTION_HOST_NAME
,
1017 strlen(client
->hostname
), client
->hostname
);
1019 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
1025 if (client
->vendor_class_identifier
) {
1026 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1027 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1028 strlen(client
->vendor_class_identifier
),
1029 client
->vendor_class_identifier
);
1034 if (client
->mudurl
) {
1035 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1036 SD_DHCP_OPTION_MUD_URL
,
1037 strlen(client
->mudurl
),
1043 if (client
->user_class
) {
1044 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1045 SD_DHCP_OPTION_USER_CLASS
,
1046 strv_length(client
->user_class
),
1047 client
->user_class
);
1052 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
) {
1053 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1054 j
->option
, j
->length
, j
->data
);
1059 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
1060 r
= dhcp_option_append(
1061 &packet
->dhcp
, optlen
, optoffset
, 0,
1062 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
1063 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
1072 static int client_send_discover(sd_dhcp_client
*client
) {
1073 _cleanup_free_ DHCPPacket
*discover
= NULL
;
1074 size_t optoffset
, optlen
;
1078 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
1080 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
1081 &optlen
, &optoffset
);
1085 /* the client may suggest values for the network address
1086 and lease time in the DHCPDISCOVER message. The client may include
1087 the ’requested IP address’ option to suggest that a particular IP
1088 address be assigned, and may include the ’IP address lease time’
1089 option to suggest the lease time it would like.
1091 /* RFC7844 section 3:
1092 SHOULD NOT contain any other option. */
1093 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
1094 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1095 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1096 4, &client
->last_addr
);
1101 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
1105 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1106 SD_DHCP_OPTION_END
, 0, NULL
);
1110 /* We currently ignore:
1111 The client SHOULD wait a random time between one and ten seconds to
1112 desynchronize the use of DHCP at startup.
1114 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1118 log_dhcp_client(client
, "DISCOVER");
1123 static int client_send_request(sd_dhcp_client
*client
) {
1124 _cleanup_free_ DHCPPacket
*request
= NULL
;
1125 size_t optoffset
, optlen
;
1130 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
1134 switch (client
->state
) {
1135 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1136 SELECTING should be REQUESTING)
1139 case DHCP_STATE_REQUESTING
:
1140 /* Client inserts the address of the selected server in ’server
1141 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1142 filled in with the yiaddr value from the chosen DHCPOFFER.
1145 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1146 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1147 4, &client
->lease
->server_address
);
1151 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1152 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1153 4, &client
->lease
->address
);
1159 case DHCP_STATE_INIT_REBOOT
:
1160 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1161 option MUST be filled in with client’s notion of its previously
1162 assigned address. ’ciaddr’ MUST be zero.
1164 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1165 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1166 4, &client
->last_addr
);
1171 case DHCP_STATE_RENEWING
:
1172 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1173 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1174 client’s IP address.
1177 case DHCP_STATE_REBINDING
:
1178 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1179 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1180 client’s IP address.
1182 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1184 request
->dhcp
.ciaddr
= client
->lease
->address
;
1188 case DHCP_STATE_INIT
:
1189 case DHCP_STATE_SELECTING
:
1190 case DHCP_STATE_REBOOTING
:
1191 case DHCP_STATE_BOUND
:
1192 case DHCP_STATE_STOPPED
:
1196 r
= client_append_common_discover_request_options(client
, request
, &optoffset
, optlen
);
1200 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1201 SD_DHCP_OPTION_END
, 0, NULL
);
1205 if (client
->state
== DHCP_STATE_RENEWING
)
1206 r
= dhcp_network_send_udp_socket(client
->fd
,
1207 client
->lease
->server_address
,
1210 sizeof(DHCPMessage
) + optoffset
);
1212 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1216 switch (client
->state
) {
1218 case DHCP_STATE_REQUESTING
:
1219 log_dhcp_client(client
, "REQUEST (requesting)");
1222 case DHCP_STATE_INIT_REBOOT
:
1223 log_dhcp_client(client
, "REQUEST (init-reboot)");
1226 case DHCP_STATE_RENEWING
:
1227 log_dhcp_client(client
, "REQUEST (renewing)");
1230 case DHCP_STATE_REBINDING
:
1231 log_dhcp_client(client
, "REQUEST (rebinding)");
1235 log_dhcp_client(client
, "REQUEST (invalid)");
1242 static int client_start(sd_dhcp_client
*client
);
1244 static int client_timeout_resend(
1249 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1250 DHCP_CLIENT_DONT_DESTROY(client
);
1251 usec_t next_timeout
;
1256 assert(client
->event
);
1258 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
1262 switch (client
->state
) {
1264 case DHCP_STATE_RENEWING
:
1265 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->t2_time
);
1268 case DHCP_STATE_REBINDING
:
1269 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->expire_time
);
1272 case DHCP_STATE_REBOOTING
:
1273 /* start over as we did not receive a timely ack or nak */
1274 r
= client_initialize(client
);
1278 r
= client_start(client
);
1282 log_dhcp_client(client
, "REBOOTED");
1285 case DHCP_STATE_INIT
:
1286 case DHCP_STATE_INIT_REBOOT
:
1287 case DHCP_STATE_SELECTING
:
1288 case DHCP_STATE_REQUESTING
:
1289 case DHCP_STATE_BOUND
:
1290 if (client
->attempt
>= client
->max_attempts
)
1294 next_timeout
= client_compute_request_timeout(time_now
, client
->attempt
);
1297 case DHCP_STATE_STOPPED
:
1302 assert_not_reached();
1305 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1307 next_timeout
, 10 * USEC_PER_MSEC
,
1308 client_timeout_resend
, client
,
1309 client
->event_priority
, "dhcp4-resend-timer", true);
1313 switch (client
->state
) {
1314 case DHCP_STATE_INIT
:
1315 r
= client_send_discover(client
);
1317 client
->state
= DHCP_STATE_SELECTING
;
1318 client
->attempt
= 0;
1319 } else if (client
->attempt
>= client
->max_attempts
)
1324 case DHCP_STATE_SELECTING
:
1325 r
= client_send_discover(client
);
1326 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1331 case DHCP_STATE_INIT_REBOOT
:
1332 case DHCP_STATE_REQUESTING
:
1333 case DHCP_STATE_RENEWING
:
1334 case DHCP_STATE_REBINDING
:
1335 r
= client_send_request(client
);
1336 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1339 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1340 client
->state
= DHCP_STATE_REBOOTING
;
1342 client
->request_sent
= time_now
;
1345 case DHCP_STATE_REBOOTING
:
1346 case DHCP_STATE_BOUND
:
1349 case DHCP_STATE_STOPPED
:
1354 if (client
->attempt
>= TRANSIENT_FAILURE_ATTEMPTS
)
1355 client_notify(client
, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE
);
1360 client_stop(client
, r
);
1362 /* Errors were dealt with when stopping the client, don't spill
1363 errors into the event loop handler */
1367 static int client_initialize_io_events(
1368 sd_dhcp_client
*client
,
1369 sd_event_io_handler_t io_callback
) {
1374 assert(client
->event
);
1376 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1377 client
->fd
, EPOLLIN
, io_callback
,
1382 r
= sd_event_source_set_priority(client
->receive_message
,
1383 client
->event_priority
);
1387 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1393 client_stop(client
, r
);
1398 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1403 assert(client
->event
);
1405 if (client
->start_delay
> 0) {
1406 assert_se(sd_event_now(client
->event
, CLOCK_BOOTTIME
, &usec
) >= 0);
1407 usec
+= client
->start_delay
;
1410 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1413 client_timeout_resend
, client
,
1414 client
->event_priority
, "dhcp4-resend-timer", true);
1416 client_stop(client
, r
);
1422 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1423 client_initialize_io_events(client
, io_callback
);
1424 client_initialize_time_events(client
);
1429 static int client_start_delayed(sd_dhcp_client
*client
) {
1432 assert_return(client
, -EINVAL
);
1433 assert_return(client
->event
, -EINVAL
);
1434 assert_return(client
->ifindex
> 0, -EINVAL
);
1435 assert_return(client
->fd
< 0, -EBUSY
);
1436 assert_return(client
->xid
== 0, -EINVAL
);
1437 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1439 client
->xid
= random_u32();
1441 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1442 &client
->hw_addr
, &client
->bcast_addr
,
1443 client
->arp_type
, client
->port
,
1444 client
->socket_priority_set
, client
->socket_priority
);
1446 client_stop(client
, r
);
1451 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1452 client
->start_time
= now(CLOCK_BOOTTIME
);
1454 return client_initialize_events(client
, client_receive_message_raw
);
1457 static int client_start(sd_dhcp_client
*client
) {
1458 client
->start_delay
= 0;
1459 return client_start_delayed(client
);
1462 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1463 sd_dhcp_client
*client
= userdata
;
1464 DHCP_CLIENT_DONT_DESTROY(client
);
1466 log_dhcp_client(client
, "EXPIRED");
1468 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1470 /* lease was lost, start over if not freed or stopped in callback */
1471 if (client
->state
!= DHCP_STATE_STOPPED
) {
1472 client_initialize(client
);
1473 client_start(client
);
1479 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1480 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1481 DHCP_CLIENT_DONT_DESTROY(client
);
1484 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
1485 client
->fd
= safe_close(client
->fd
);
1487 client
->state
= DHCP_STATE_REBINDING
;
1488 client
->attempt
= 0;
1490 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1491 &client
->hw_addr
, &client
->bcast_addr
,
1492 client
->arp_type
, client
->port
,
1493 client
->socket_priority_set
, client
->socket_priority
);
1495 client_stop(client
, r
);
1500 return client_initialize_events(client
, client_receive_message_raw
);
1503 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1504 sd_dhcp_client
*client
= userdata
;
1505 DHCP_CLIENT_DONT_DESTROY(client
);
1508 client
->state
= DHCP_STATE_RENEWING
;
1509 else if (client
->state
!= DHCP_STATE_INIT
)
1510 client
->state
= DHCP_STATE_INIT_REBOOT
;
1511 client
->attempt
= 0;
1513 return client_initialize_time_events(client
);
1516 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1517 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1520 r
= dhcp_lease_new(&lease
);
1524 if (client
->client_id_len
> 0) {
1525 r
= dhcp_lease_set_client_id(lease
,
1526 (uint8_t *) &client
->client_id
,
1527 client
->client_id_len
);
1532 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1533 if (r
!= DHCP_OFFER
) {
1534 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1538 lease
->next_server
= offer
->siaddr
;
1539 lease
->address
= offer
->yiaddr
;
1541 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1542 lease
->lifetime
= client
->fallback_lease_lifetime
;
1544 if (lease
->address
== 0 ||
1545 lease
->server_address
== 0 ||
1546 lease
->lifetime
== 0) {
1547 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1551 if (!lease
->have_subnet_mask
) {
1552 r
= dhcp_lease_set_default_subnet_mask(lease
);
1554 log_dhcp_client(client
,
1555 "received lease lacks subnet mask, "
1556 "and a fallback one cannot be generated, ignoring");
1561 sd_dhcp_lease_unref(client
->lease
);
1562 client
->lease
= TAKE_PTR(lease
);
1564 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1567 log_dhcp_client(client
, "OFFER");
1572 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1575 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1576 if (r
!= DHCP_FORCERENEW
)
1580 log_dhcp_client(client
, "FORCERENEW");
1584 /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP
1585 * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW
1586 * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */
1587 log_dhcp_client(client
, "Received FORCERENEW, ignoring.");
1592 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1593 if (a
->address
!= b
->address
)
1596 if (a
->subnet_mask
!= b
->subnet_mask
)
1599 if (a
->router_size
!= b
->router_size
)
1602 for (size_t i
= 0; i
< a
->router_size
; i
++)
1603 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1609 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1610 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1611 _cleanup_free_
char *error_message
= NULL
;
1614 r
= dhcp_lease_new(&lease
);
1618 if (client
->client_id_len
> 0) {
1619 r
= dhcp_lease_set_client_id(lease
,
1620 (uint8_t *) &client
->client_id
,
1621 client
->client_id_len
);
1626 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1627 if (r
== DHCP_NAK
) {
1628 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1629 return -EADDRNOTAVAIL
;
1632 if (r
!= DHCP_ACK
) {
1633 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1637 lease
->next_server
= ack
->siaddr
;
1639 lease
->address
= ack
->yiaddr
;
1641 if (lease
->address
== INADDR_ANY
||
1642 lease
->server_address
== INADDR_ANY
||
1643 lease
->lifetime
== 0) {
1644 log_dhcp_client(client
, "received lease lacks address, server "
1645 "address or lease lifetime, ignoring");
1649 if (lease
->subnet_mask
== INADDR_ANY
) {
1650 r
= dhcp_lease_set_default_subnet_mask(lease
);
1652 log_dhcp_client(client
,
1653 "received lease lacks subnet mask, "
1654 "and a fallback one cannot be generated, ignoring");
1659 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1660 if (client
->lease
) {
1661 if (lease_equal(client
->lease
, lease
))
1662 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1664 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1666 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1669 client
->lease
= TAKE_PTR(lease
);
1671 log_dhcp_client(client
, "ACK");
1676 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1681 assert(client
->event
);
1682 assert(client
->lease
);
1683 assert(client
->lease
->lifetime
);
1685 /* don't set timers for infinite leases */
1686 if (client
->lease
->lifetime
== 0xffffffff) {
1687 (void) event_source_disable(client
->timeout_t1
);
1688 (void) event_source_disable(client
->timeout_t2
);
1689 (void) event_source_disable(client
->timeout_expire
);
1694 r
= sd_event_now(client
->event
, CLOCK_BOOTTIME
, &time_now
);
1697 assert(client
->request_sent
<= time_now
);
1699 /* verify that 0 < t2 < lifetime */
1700 if (client
->lease
->t2
== 0 || client
->lease
->t2
>= client
->lease
->lifetime
)
1701 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1702 /* verify that 0 < t1 < lifetime */
1703 if (client
->lease
->t1
== 0 || client
->lease
->t1
>= client
->lease
->t2
)
1704 client
->lease
->t1
= T1_DEFAULT(client
->lease
->lifetime
);
1705 /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
1706 * could not evalate to false if t1 >= t2; so setting t2 to T2_DEFAULT
1707 * guarantees t1 < t2. */
1708 if (client
->lease
->t1
>= client
->lease
->t2
)
1709 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1711 client
->expire_time
= client
->request_sent
+ client
->lease
->lifetime
* USEC_PER_SEC
;
1712 client
->t1_time
= client
->request_sent
+ client
->lease
->t1
* USEC_PER_SEC
;
1713 client
->t2_time
= client
->request_sent
+ client
->lease
->t2
* USEC_PER_SEC
;
1715 /* RFC2131 section 4.4.5:
1716 * Times T1 and T2 SHOULD be chosen with some random "fuzz".
1717 * Since the RFC doesn't specify here the exact 'fuzz' to use,
1718 * we use the range from section 4.1: -1 to +1 sec. */
1719 client
->t1_time
= usec_sub_signed(client
->t1_time
, RFC2131_RANDOM_FUZZ
);
1720 client
->t2_time
= usec_sub_signed(client
->t2_time
, RFC2131_RANDOM_FUZZ
);
1722 /* after fuzzing, ensure t2 is still >= t1 */
1723 client
->t2_time
= MAX(client
->t1_time
, client
->t2_time
);
1725 /* arm lifetime timeout */
1726 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1728 client
->expire_time
, 10 * USEC_PER_MSEC
,
1729 client_timeout_expire
, client
,
1730 client
->event_priority
, "dhcp4-lifetime", true);
1734 /* don't arm earlier timeouts if this has already expired */
1735 if (client
->expire_time
<= time_now
)
1738 log_dhcp_client(client
, "lease expires in %s",
1739 FORMAT_TIMESPAN(client
->expire_time
- time_now
, USEC_PER_SEC
));
1741 /* arm T2 timeout */
1742 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1744 client
->t2_time
, 10 * USEC_PER_MSEC
,
1745 client_timeout_t2
, client
,
1746 client
->event_priority
, "dhcp4-t2-timeout", true);
1750 /* don't arm earlier timeout if this has already expired */
1751 if (client
->t2_time
<= time_now
)
1754 log_dhcp_client(client
, "T2 expires in %s",
1755 FORMAT_TIMESPAN(client
->t2_time
- time_now
, USEC_PER_SEC
));
1757 /* arm T1 timeout */
1758 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1760 client
->t1_time
, 10 * USEC_PER_MSEC
,
1761 client_timeout_t1
, client
,
1762 client
->event_priority
, "dhcp4-t1-timer", true);
1766 if (client
->t1_time
> time_now
)
1767 log_dhcp_client(client
, "T1 expires in %s",
1768 FORMAT_TIMESPAN(client
->t1_time
- time_now
, USEC_PER_SEC
));
1773 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1774 DHCP_CLIENT_DONT_DESTROY(client
);
1775 int r
, notify_event
;
1778 assert(client
->event
);
1781 switch (client
->state
) {
1782 case DHCP_STATE_SELECTING
:
1784 r
= client_handle_offer(client
, message
, len
);
1786 return 0; /* invalid message, let's ignore it */
1790 client
->state
= DHCP_STATE_REQUESTING
;
1791 client
->attempt
= 0;
1793 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1796 client_timeout_resend
, client
,
1797 client
->event_priority
, "dhcp4-resend-timer", true);
1800 case DHCP_STATE_REBOOTING
:
1801 case DHCP_STATE_REQUESTING
:
1802 case DHCP_STATE_RENEWING
:
1803 case DHCP_STATE_REBINDING
:
1805 r
= client_handle_ack(client
, message
, len
);
1807 return 0; /* invalid message, let's ignore it */
1808 if (r
== -EADDRNOTAVAIL
) {
1809 /* got a NAK, let's restart the client */
1810 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1812 r
= client_initialize(client
);
1816 r
= client_start_delayed(client
);
1820 log_dhcp_client(client
, "REBOOT in %s", FORMAT_TIMESPAN(client
->start_delay
, USEC_PER_SEC
));
1822 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1823 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1829 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
, DHCP_STATE_REBOOTING
))
1830 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1834 client
->start_delay
= 0;
1835 (void) event_source_disable(client
->timeout_resend
);
1836 client
->receive_message
= sd_event_source_disable_unref(client
->receive_message
);
1837 client
->fd
= safe_close(client
->fd
);
1839 client
->state
= DHCP_STATE_BOUND
;
1840 client
->attempt
= 0;
1842 client
->last_addr
= client
->lease
->address
;
1844 r
= client_set_lease_timeouts(client
);
1846 log_dhcp_client(client
, "could not set lease timeouts");
1850 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1852 log_dhcp_client(client
, "could not bind UDP socket");
1858 client_initialize_io_events(client
, client_receive_message_udp
);
1860 if (IN_SET(client
->state
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
) &&
1861 notify_event
== SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1862 /* FIXME: hmm, maybe this is a bug... */
1863 log_dhcp_client(client
, "client_handle_ack() returned SD_DHCP_CLIENT_EVENT_IP_ACQUIRE while DHCP client is %s the address, skipping callback.",
1864 client
->state
== DHCP_STATE_RENEWING
? "renewing" : "rebinding");
1866 client_notify(client
, notify_event
);
1869 case DHCP_STATE_BOUND
:
1870 r
= client_handle_forcerenew(client
, message
, len
);
1872 return 0; /* invalid message, let's ignore it */
1876 r
= client_timeout_t1(NULL
, 0, client
);
1879 case DHCP_STATE_INIT
:
1880 case DHCP_STATE_INIT_REBOOT
:
1884 case DHCP_STATE_STOPPED
:
1888 assert_not_reached();
1893 client_stop(client
, r
);
1898 static int client_receive_message_udp(
1904 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1905 _cleanup_free_ DHCPMessage
*message
= NULL
;
1906 const uint8_t *expected_chaddr
= NULL
;
1907 uint8_t expected_hlen
= 0;
1908 ssize_t len
, buflen
;
1912 buflen
= next_datagram_size_fd(fd
);
1913 if (ERRNO_IS_NEG_TRANSIENT(buflen
) || ERRNO_IS_NEG_DISCONNECT(buflen
))
1916 log_dhcp_client_errno(client
, buflen
, "Failed to determine datagram size to read, ignoring: %m");
1920 message
= malloc0(buflen
);
1924 len
= recv(fd
, message
, buflen
, 0);
1926 if (ERRNO_IS_TRANSIENT(errno
) || ERRNO_IS_DISCONNECT(errno
))
1929 log_dhcp_client_errno(client
, errno
, "Could not receive message from UDP socket, ignoring: %m");
1932 if ((size_t) len
< sizeof(DHCPMessage
)) {
1933 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1937 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1938 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1942 if (message
->op
!= BOOTREPLY
) {
1943 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1947 if (message
->htype
!= client
->arp_type
) {
1948 log_dhcp_client(client
, "Packet type does not match client type");
1952 if (client
->arp_type
== ARPHRD_ETHER
) {
1953 expected_hlen
= ETH_ALEN
;
1954 expected_chaddr
= client
->hw_addr
.bytes
;
1957 if (message
->hlen
!= expected_hlen
) {
1958 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1962 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1963 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1967 if (client
->state
!= DHCP_STATE_BOUND
&&
1968 be32toh(message
->xid
) != client
->xid
) {
1969 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1970 so ignore the xid in this case */
1971 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1972 be32toh(message
->xid
), client
->xid
);
1976 log_dhcp_client(client
, "Received message from UDP socket, processing.");
1977 (void) client_handle_message(client
, message
, len
);
1981 static int client_receive_message_raw(
1987 sd_dhcp_client
*client
= ASSERT_PTR(userdata
);
1988 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1989 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
;
1990 struct iovec iov
= {};
1991 struct msghdr msg
= {
1994 .msg_control
= &control
,
1995 .msg_controllen
= sizeof(control
),
1997 struct cmsghdr
*cmsg
;
1998 bool checksum
= true;
1999 ssize_t buflen
, len
;
2004 buflen
= next_datagram_size_fd(fd
);
2005 if (ERRNO_IS_NEG_TRANSIENT(buflen
) || ERRNO_IS_NEG_DISCONNECT(buflen
))
2008 log_dhcp_client_errno(client
, buflen
, "Failed to determine datagram size to read, ignoring: %m");
2012 packet
= malloc0(buflen
);
2016 iov
= IOVEC_MAKE(packet
, buflen
);
2018 len
= recvmsg_safe(fd
, &msg
, 0);
2019 if (ERRNO_IS_NEG_TRANSIENT(len
) || ERRNO_IS_NEG_DISCONNECT(len
))
2022 log_dhcp_client_errno(client
, len
, "Could not receive message from raw socket, ignoring: %m");
2025 if ((size_t) len
< sizeof(DHCPPacket
))
2028 cmsg
= cmsg_find(&msg
, SOL_PACKET
, PACKET_AUXDATA
, CMSG_LEN(sizeof(struct tpacket_auxdata
)));
2030 struct tpacket_auxdata
*aux
= CMSG_TYPED_DATA(cmsg
, struct tpacket_auxdata
);
2031 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2034 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
2038 len
-= DHCP_IP_UDP_SIZE
;
2040 log_dhcp_client(client
, "Received message from RAW socket, processing.");
2041 (void) client_handle_message(client
, &packet
->dhcp
, len
);
2045 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2046 assert_return(client
, -EINVAL
);
2047 assert_return(sd_dhcp_client_is_running(client
), -ESTALE
);
2048 assert_return(client
->fd
>= 0, -EINVAL
);
2053 client
->start_delay
= 0;
2054 client
->attempt
= 1;
2055 client
->state
= DHCP_STATE_RENEWING
;
2057 return client_initialize_time_events(client
);
2060 int sd_dhcp_client_is_running(sd_dhcp_client
*client
) {
2064 return !IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
);
2067 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2070 assert_return(client
, -EINVAL
);
2072 r
= client_initialize(client
);
2076 /* RFC7844 section 3.3:
2077 SHOULD perform a complete four-way handshake, starting with a
2078 DHCPDISCOVER, to obtain a new address lease. If the client can
2079 ascertain that this is exactly the same network to which it was
2080 previously connected, and if the link-layer address did not change,
2081 the client MAY issue a DHCPREQUEST to try to reclaim the current
2083 if (client
->last_addr
&& !client
->anonymize
)
2084 client
->state
= DHCP_STATE_INIT_REBOOT
;
2086 r
= client_start(client
);
2088 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2093 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2094 assert_return(client
, -EINVAL
);
2095 assert_return(sd_dhcp_client_is_running(client
), -ESTALE
);
2096 assert_return(client
->lease
, -EUNATCH
);
2098 _cleanup_free_ DHCPPacket
*release
= NULL
;
2099 size_t optoffset
, optlen
;
2102 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2106 /* Fill up release IP and MAC */
2107 release
->dhcp
.ciaddr
= client
->lease
->address
;
2108 memcpy(&release
->dhcp
.chaddr
, client
->hw_addr
.bytes
, client
->hw_addr
.length
);
2110 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2111 SD_DHCP_OPTION_END
, 0, NULL
);
2115 r
= dhcp_network_send_udp_socket(client
->fd
,
2116 client
->lease
->server_address
,
2119 sizeof(DHCPMessage
) + optoffset
);
2123 log_dhcp_client(client
, "RELEASE");
2128 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2129 assert_return(client
, -EINVAL
);
2130 assert_return(sd_dhcp_client_is_running(client
), -ESTALE
);
2131 assert_return(client
->lease
, -EUNATCH
);
2133 _cleanup_free_ DHCPPacket
*release
= NULL
;
2134 size_t optoffset
, optlen
;
2137 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2141 release
->dhcp
.ciaddr
= client
->lease
->address
;
2142 memcpy(&release
->dhcp
.chaddr
, client
->hw_addr
.bytes
, client
->hw_addr
.length
);
2144 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2145 SD_DHCP_OPTION_END
, 0, NULL
);
2149 r
= dhcp_network_send_udp_socket(client
->fd
,
2150 client
->lease
->server_address
,
2153 sizeof(DHCPMessage
) + optoffset
);
2157 log_dhcp_client(client
, "DECLINE");
2159 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2161 if (client
->state
!= DHCP_STATE_STOPPED
) {
2162 r
= sd_dhcp_client_start(client
);
2170 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2174 DHCP_CLIENT_DONT_DESTROY(client
);
2176 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2177 client
->state
= DHCP_STATE_STOPPED
;
2182 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2185 assert_return(client
, -EINVAL
);
2186 assert_return(!client
->event
, -EBUSY
);
2187 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
2190 client
->event
= sd_event_ref(event
);
2192 r
= sd_event_default(&client
->event
);
2197 client
->event_priority
= priority
;
2202 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2203 assert_return(client
, -EINVAL
);
2204 assert_return(!sd_dhcp_client_is_running(client
), -EBUSY
);
2206 client
->event
= sd_event_unref(client
->event
);
2211 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2212 assert_return(client
, NULL
);
2214 return client
->event
;
2217 int sd_dhcp_client_attach_device(sd_dhcp_client
*client
, sd_device
*dev
) {
2218 assert_return(client
, -EINVAL
);
2220 return device_unref_and_replace(client
->dev
, dev
);
2223 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2227 log_dhcp_client(client
, "FREE");
2229 client_initialize(client
);
2231 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2232 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2233 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2234 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2236 sd_dhcp_client_detach_event(client
);
2238 sd_device_unref(client
->dev
);
2240 set_free(client
->req_opts
);
2241 free(client
->hostname
);
2242 free(client
->vendor_class_identifier
);
2243 free(client
->mudurl
);
2244 client
->user_class
= strv_free(client
->user_class
);
2245 ordered_hashmap_free(client
->extra_options
);
2246 ordered_hashmap_free(client
->vendor_options
);
2247 free(client
->ifname
);
2248 return mfree(client
);
2251 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2253 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2254 const uint8_t *opts
;
2258 assert_return(ret
, -EINVAL
);
2260 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2264 *client
= (sd_dhcp_client
) {
2266 .state
= DHCP_STATE_INIT
,
2269 .mtu
= DHCP_MIN_PACKET_SIZE
,
2270 .port
= DHCP_PORT_CLIENT
,
2271 .anonymize
= !!anonymize
,
2272 .max_attempts
= UINT64_MAX
,
2273 .ip_service_type
= -1,
2275 /* NOTE: this could be moved to a function. */
2277 n_opts
= ELEMENTSOF(default_req_opts_anonymize
);
2278 opts
= default_req_opts_anonymize
;
2280 n_opts
= ELEMENTSOF(default_req_opts
);
2281 opts
= default_req_opts
;
2284 for (size_t i
= 0; i
< n_opts
; i
++) {
2285 r
= sd_dhcp_client_set_request_option(client
, opts
[i
]);
2290 *ret
= TAKE_PTR(client
);