1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2013 Intel Corporation. All rights reserved.
7 #include <net/ethernet.h>
8 #include <net/if_arp.h>
11 #include <sys/ioctl.h>
12 #include <linux/if_infiniband.h>
14 #include "sd-dhcp-client.h"
16 #include "alloc-util.h"
17 #include "dhcp-identifier.h"
18 #include "dhcp-internal.h"
19 #include "dhcp-lease-internal.h"
20 #include "dhcp-protocol.h"
21 #include "dns-domain.h"
22 #include "event-util.h"
24 #include "hostname-util.h"
26 #include "memory-util.h"
27 #include "random-util.h"
29 #include "sort-util.h"
30 #include "string-util.h"
32 #include "time-util.h"
36 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
37 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
39 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
40 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
42 #define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
43 * transient failure. */
45 typedef struct sd_dhcp_client_id
{
49 /* 0: Generic (non-LL) (RFC 2132) */
50 uint8_t data
[MAX_CLIENT_ID_LEN
];
53 /* 1: Ethernet Link-Layer (RFC 2132) */
54 uint8_t haddr
[ETH_ALEN
];
57 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
61 /* 255: Node-specific (RFC 4361) */
66 uint8_t data
[MAX_CLIENT_ID_LEN
];
69 } _packed_ sd_dhcp_client_id
;
71 struct sd_dhcp_client
{
77 sd_event_source
*timeout_resend
;
81 union sockaddr_union link
;
82 sd_event_source
*receive_message
;
83 bool request_broadcast
;
87 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
89 uint8_t bcast_addr
[MAX_MAC_ADDR_LEN
];
90 size_t bcast_addr_len
;
92 sd_dhcp_client_id client_id
;
95 char *vendor_class_identifier
;
99 uint32_t fallback_lease_lifetime
;
106 uint64_t max_attempts
;
107 OrderedHashmap
*extra_options
;
108 OrderedHashmap
*vendor_options
;
110 sd_event_source
*timeout_t1
;
111 sd_event_source
*timeout_t2
;
112 sd_event_source
*timeout_expire
;
113 sd_dhcp_client_callback_t callback
;
115 sd_dhcp_lease
*lease
;
120 static const uint8_t default_req_opts
[] = {
121 SD_DHCP_OPTION_SUBNET_MASK
,
122 SD_DHCP_OPTION_ROUTER
,
123 SD_DHCP_OPTION_HOST_NAME
,
124 SD_DHCP_OPTION_DOMAIN_NAME
,
125 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
128 /* RFC7844 section 3:
129 MAY contain the Parameter Request List option.
131 The client intending to protect its privacy SHOULD only request a
132 minimal number of options in the PRL and SHOULD also randomly shuffle
133 the ordering of option codes in the PRL. If this random ordering
134 cannot be implemented, the client MAY order the option codes in the
135 PRL by option code number (lowest to highest).
137 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
138 static const uint8_t default_req_opts_anonymize
[] = {
139 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
140 SD_DHCP_OPTION_ROUTER
, /* 3 */
141 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
142 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
143 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
144 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
145 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
146 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
147 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
148 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
149 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
150 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
151 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
154 static int client_receive_message_raw(
159 static int client_receive_message_udp(
164 static void client_stop(sd_dhcp_client
*client
, int error
);
166 int sd_dhcp_client_id_to_string(const void *data
, size_t len
, char **ret
) {
167 const sd_dhcp_client_id
*client_id
= data
;
168 _cleanup_free_
char *t
= NULL
;
171 assert_return(data
, -EINVAL
);
172 assert_return(len
>= 1, -EINVAL
);
173 assert_return(ret
, -EINVAL
);
176 if (len
> MAX_CLIENT_ID_LEN
)
179 switch (client_id
->type
) {
181 if (utf8_is_printable((char *) client_id
->gen
.data
, len
))
182 r
= asprintf(&t
, "%.*s", (int) len
, client_id
->gen
.data
);
184 r
= asprintf(&t
, "DATA");
187 if (len
!= sizeof_field(sd_dhcp_client_id
, eth
))
190 r
= asprintf(&t
, "%x:%x:%x:%x:%x:%x",
191 client_id
->eth
.haddr
[0],
192 client_id
->eth
.haddr
[1],
193 client_id
->eth
.haddr
[2],
194 client_id
->eth
.haddr
[3],
195 client_id
->eth
.haddr
[4],
196 client_id
->eth
.haddr
[5]);
199 r
= asprintf(&t
, "ARP/LL");
205 uint32_t iaid
= be32toh(client_id
->ns
.iaid
);
206 uint16_t duid_type
= be16toh(client_id
->ns
.duid
.type
);
207 if (dhcp_validate_duid_len(duid_type
, len
- 6, true) < 0)
210 r
= asprintf(&t
, "IAID:0x%x/DUID", iaid
);
220 int sd_dhcp_client_set_callback(
221 sd_dhcp_client
*client
,
222 sd_dhcp_client_callback_t cb
,
225 assert_return(client
, -EINVAL
);
227 client
->callback
= cb
;
228 client
->userdata
= userdata
;
233 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
234 assert_return(client
, -EINVAL
);
236 client
->request_broadcast
= !!broadcast
;
241 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
242 assert_return(client
, -EINVAL
);
243 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
247 case SD_DHCP_OPTION_PAD
:
248 case SD_DHCP_OPTION_OVERLOAD
:
249 case SD_DHCP_OPTION_MESSAGE_TYPE
:
250 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
251 case SD_DHCP_OPTION_END
:
258 return set_ensure_put(&client
->req_opts
, NULL
, UINT8_TO_PTR(option
));
261 int sd_dhcp_client_set_request_address(
262 sd_dhcp_client
*client
,
263 const struct in_addr
*last_addr
) {
265 assert_return(client
, -EINVAL
);
266 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
269 client
->last_addr
= last_addr
->s_addr
;
271 client
->last_addr
= INADDR_ANY
;
276 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
277 assert_return(client
, -EINVAL
);
278 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
279 assert_return(ifindex
> 0, -EINVAL
);
281 client
->ifindex
= ifindex
;
285 int sd_dhcp_client_set_mac(
286 sd_dhcp_client
*client
,
288 const uint8_t *bcast_addr
,
292 DHCP_CLIENT_DONT_DESTROY(client
);
293 bool need_restart
= false;
296 assert_return(client
, -EINVAL
);
297 assert_return(addr
, -EINVAL
);
298 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
299 assert_return(arp_type
> 0, -EINVAL
);
301 if (arp_type
== ARPHRD_ETHER
)
302 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
303 else if (arp_type
== ARPHRD_INFINIBAND
)
304 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
308 if (client
->mac_addr_len
== addr_len
&&
309 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0 &&
310 (client
->bcast_addr_len
> 0) == !!bcast_addr
&&
311 (!bcast_addr
|| memcmp(&client
->bcast_addr
, bcast_addr
, addr_len
) == 0))
314 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
315 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
317 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
320 memcpy(&client
->mac_addr
, addr
, addr_len
);
321 client
->mac_addr_len
= addr_len
;
322 client
->arp_type
= arp_type
;
323 client
->bcast_addr_len
= 0;
326 memcpy(&client
->bcast_addr
, bcast_addr
, addr_len
);
327 client
->bcast_addr_len
= addr_len
;
330 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
331 r
= sd_dhcp_client_start(client
);
333 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
339 int sd_dhcp_client_get_client_id(
340 sd_dhcp_client
*client
,
342 const uint8_t **data
,
345 assert_return(client
, -EINVAL
);
346 assert_return(type
, -EINVAL
);
347 assert_return(data
, -EINVAL
);
348 assert_return(data_len
, -EINVAL
);
350 if (client
->client_id_len
) {
351 *type
= client
->client_id
.type
;
352 *data
= client
->client_id
.raw
.data
;
353 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
363 int sd_dhcp_client_set_client_id(
364 sd_dhcp_client
*client
,
369 DHCP_CLIENT_DONT_DESTROY(client
);
370 bool need_restart
= false;
373 assert_return(client
, -EINVAL
);
374 assert_return(data
, -EINVAL
);
375 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
377 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
378 client
->client_id
.type
== type
&&
379 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
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 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
394 log_dhcp_client(client
, "Changing client ID on running DHCP "
395 "client, restarting");
397 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
400 client
->client_id
.type
= type
;
401 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
402 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
404 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
405 r
= sd_dhcp_client_start(client
);
407 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
414 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
415 * without further modification. Otherwise, if duid_type is supported, DUID
416 * is set based on that type. Otherwise, an error is returned.
418 static int dhcp_client_set_iaid_duid_internal(
419 sd_dhcp_client
*client
,
428 DHCP_CLIENT_DONT_DESTROY(client
);
432 assert_return(client
, -EINVAL
);
433 assert_return(duid_len
== 0 || duid
, -EINVAL
);
436 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
438 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
441 zero(client
->client_id
);
442 client
->client_id
.type
= 255;
446 client
->client_id
.ns
.iaid
= htobe32(iaid
);
448 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
449 client
->mac_addr_len
,
451 &client
->client_id
.ns
.iaid
);
453 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
458 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
459 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
460 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
464 if (client
->mac_addr_len
== 0)
465 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
467 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
469 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
472 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
474 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
477 if (client
->mac_addr_len
== 0)
478 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
480 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
482 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
485 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
487 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
490 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
493 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
494 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
496 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
497 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
498 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
499 r
= sd_dhcp_client_start(client
);
501 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
507 int sd_dhcp_client_set_iaid_duid(
508 sd_dhcp_client
*client
,
514 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
517 int sd_dhcp_client_set_iaid_duid_llt(
518 sd_dhcp_client
*client
,
522 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
525 int sd_dhcp_client_set_duid(
526 sd_dhcp_client
*client
,
530 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
533 int sd_dhcp_client_set_duid_llt(
534 sd_dhcp_client
*client
,
536 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
539 int sd_dhcp_client_set_hostname(
540 sd_dhcp_client
*client
,
541 const char *hostname
) {
543 assert_return(client
, -EINVAL
);
545 /* Make sure hostnames qualify as DNS and as Linux hostnames */
547 !(hostname_is_valid(hostname
, 0) && dns_name_is_valid(hostname
) > 0))
550 return free_and_strdup(&client
->hostname
, hostname
);
553 int sd_dhcp_client_set_vendor_class_identifier(
554 sd_dhcp_client
*client
,
557 assert_return(client
, -EINVAL
);
559 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
562 int sd_dhcp_client_set_mud_url(
563 sd_dhcp_client
*client
,
564 const char *mudurl
) {
566 assert_return(client
, -EINVAL
);
567 assert_return(mudurl
, -EINVAL
);
568 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
569 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
571 return free_and_strdup(&client
->mudurl
, mudurl
);
574 int sd_dhcp_client_set_user_class(
575 sd_dhcp_client
*client
,
576 char * const *user_class
) {
581 assert_return(client
, -EINVAL
);
582 assert_return(!strv_isempty(user_class
), -EINVAL
);
584 STRV_FOREACH(p
, user_class
) {
585 size_t n
= strlen(*p
);
587 if (n
> 255 || n
== 0)
591 s
= strv_copy(user_class
);
595 return strv_free_and_replace(client
->user_class
, s
);
598 int sd_dhcp_client_set_client_port(
599 sd_dhcp_client
*client
,
602 assert_return(client
, -EINVAL
);
609 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
610 assert_return(client
, -EINVAL
);
611 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
618 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
619 assert_return(client
, -EINVAL
);
621 client
->max_attempts
= max_attempts
;
626 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
629 assert_return(client
, -EINVAL
);
630 assert_return(v
, -EINVAL
);
632 r
= ordered_hashmap_ensure_put(&client
->extra_options
, &dhcp_option_hash_ops
, UINT_TO_PTR(v
->option
), v
);
636 sd_dhcp_option_ref(v
);
640 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
643 assert_return(client
, -EINVAL
);
644 assert_return(v
, -EINVAL
);
646 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
650 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
654 sd_dhcp_option_ref(v
);
659 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
660 assert_return(client
, -EINVAL
);
662 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
663 return -EADDRNOTAVAIL
;
666 *ret
= client
->lease
;
671 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
672 assert_return(client
, -EINVAL
);
674 client
->ip_service_type
= type
;
679 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint32_t fallback_lease_lifetime
) {
680 assert_return(client
, -EINVAL
);
681 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
683 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
688 static int client_notify(sd_dhcp_client
*client
, int event
) {
691 if (client
->callback
)
692 return client
->callback(client
, event
, client
->userdata
);
697 static int client_initialize(sd_dhcp_client
*client
) {
698 assert_return(client
, -EINVAL
);
700 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
702 client
->fd
= safe_close(client
->fd
);
704 (void) event_source_disable(client
->timeout_resend
);
705 (void) event_source_disable(client
->timeout_t1
);
706 (void) event_source_disable(client
->timeout_t2
);
707 (void) event_source_disable(client
->timeout_expire
);
711 client
->state
= DHCP_STATE_INIT
;
714 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
719 static void client_stop(sd_dhcp_client
*client
, int error
) {
723 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
724 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
725 log_dhcp_client(client
, "STOPPED");
727 log_dhcp_client(client
, "STOPPED: Unknown event");
729 client_notify(client
, error
);
731 client_initialize(client
);
734 /* RFC2131 section 4.1:
735 * retransmission delays should include -1 to +1 sec of random 'fuzz'. */
736 #define RFC2131_RANDOM_FUZZ \
737 ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
739 /* RFC2131 section 4.1:
740 * for retransmission delays, timeout should start at 4s then double
741 * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
742 * This assumes the first call will be using attempt 1. */
743 static usec_t
client_compute_request_timeout(usec_t now
, uint64_t attempt
) {
744 usec_t timeout
= (UINT64_C(1) << MIN(attempt
+ 1, UINT64_C(6))) * USEC_PER_SEC
;
746 return usec_sub_signed(usec_add(now
, timeout
), RFC2131_RANDOM_FUZZ
);
749 /* RFC2131 section 4.4.5:
750 * T1 defaults to (0.5 * duration_of_lease).
751 * T2 defaults to (0.875 * duration_of_lease). */
752 #define T1_DEFAULT(lifetime) ((lifetime) / 2)
753 #define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
755 /* RFC2131 section 4.4.5:
756 * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
757 * and one-half of the remaining lease time (in REBINDING state), down to a minimum
759 * Note that while the default T1/T2 initial times do have random 'fuzz' applied,
760 * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
761 static usec_t
client_compute_reacquisition_timeout(usec_t now
, usec_t expire
) {
762 return now
+ MAX(usec_sub_unsigned(expire
, now
) / 2, 60 * USEC_PER_SEC
);
765 static int cmp_uint8(const uint8_t *a
, const uint8_t *b
) {
769 static int client_message_init(
770 sd_dhcp_client
*client
,
774 size_t *_optoffset
) {
776 _cleanup_free_ DHCPPacket
*packet
= NULL
;
777 size_t optlen
, optoffset
, size
;
784 assert(client
->start_time
);
788 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
790 optlen
= DHCP_MIN_OPTIONS_SIZE
;
791 size
= sizeof(DHCPPacket
) + optlen
;
793 packet
= malloc0(size
);
797 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
798 client
->arp_type
, optlen
, &optoffset
);
802 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
803 refuse to issue an DHCP lease if 'secs' is set to zero */
804 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
807 assert(time_now
>= client
->start_time
);
809 /* seconds between sending first and last DISCOVER
810 * must always be strictly positive to deal with broken servers */
811 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
812 packet
->dhcp
.secs
= htobe16(secs
);
814 /* RFC2132 section 4.1
815 A client that cannot receive unicast IP datagrams until its protocol
816 software has been configured with an IP address SHOULD set the
817 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
818 DHCPREQUEST messages that client sends. The BROADCAST bit will
819 provide a hint to the DHCP server and BOOTP relay agent to broadcast
820 any messages to the client on the client's subnet.
822 Note: some interfaces needs this to be enabled, but some networks
823 needs this to be disabled as broadcasts are filteretd, so this
824 needs to be configurable */
825 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
826 packet
->dhcp
.flags
= htobe16(0x8000);
828 /* RFC2132 section 4.1.1:
829 The client MUST include its hardware address in the ’chaddr’ field, if
830 necessary for delivery of DHCP reply messages. Non-Ethernet
831 interfaces will leave 'chaddr' empty and use the client identifier
832 instead (eg, RFC 4390 section 2.1).
834 if (client
->arp_type
== ARPHRD_ETHER
)
835 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
837 /* If no client identifier exists, construct an RFC 4361-compliant one */
838 if (client
->client_id_len
== 0) {
841 client
->client_id
.type
= 255;
843 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
844 true, &client
->client_id
.ns
.iaid
);
848 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
852 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
855 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
856 Identifier option is not set */
857 if (client
->client_id_len
) {
858 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
859 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
860 client
->client_id_len
,
866 /* RFC2131 section 3.5:
867 in its initial DHCPDISCOVER or DHCPREQUEST message, a
868 client may provide the server with a list of specific
869 parameters the client is interested in. If the client
870 includes a list of parameters in a DHCPDISCOVER message,
871 it MUST include that list in any subsequent DHCPREQUEST
875 /* RFC7844 section 3:
876 MAY contain the Parameter Request List option. */
877 /* NOTE: in case that there would be an option to do not send
878 * any PRL at all, the size should be checked before sending */
879 if (!set_isempty(client
->req_opts
) && type
!= DHCP_RELEASE
) {
880 _cleanup_free_
uint8_t *opts
= NULL
;
881 size_t n_opts
, i
= 0;
884 n_opts
= set_size(client
->req_opts
);
885 opts
= new(uint8_t, n_opts
);
889 SET_FOREACH(val
, client
->req_opts
)
890 opts
[i
++] = PTR_TO_UINT8(val
);
893 /* For anonymizing the request, let's sort the options. */
894 typesafe_qsort(opts
, n_opts
, cmp_uint8
);
896 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
897 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
903 /* RFC2131 section 3.5:
904 The client SHOULD include the ’maximum DHCP message size’ option to
905 let the server know how large the server may make its DHCP messages.
907 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
908 than the defined default size unless the Maximum Message Size option
911 RFC3442 "Requirements to Avoid Sizing Constraints":
912 Because a full routing table can be quite large, the standard 576
913 octet maximum size for a DHCP message may be too short to contain
914 some legitimate Classless Static Route options. Because of this,
915 clients implementing the Classless Static Route option SHOULD send a
916 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
917 stack is capable of receiving larger IP datagrams. In this case, the
918 client SHOULD set the value of this option to at least the MTU of the
919 interface that the client is configuring. The client MAY set the
920 value of this option higher, up to the size of the largest UDP packet
921 it is prepared to accept. (Note that the value specified in the
922 Maximum DHCP Message Size option is the total maximum packet size,
923 including IP and UDP headers.)
925 /* RFC7844 section 3:
926 SHOULD NOT contain any other option. */
927 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
928 max_size
= htobe16(size
);
929 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
930 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
937 *_optoffset
= optoffset
;
938 *ret
= TAKE_PTR(packet
);
943 static int client_append_fqdn_option(
944 DHCPMessage
*message
,
949 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
952 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
953 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
954 buffer
[1] = 0; /* RCODE1 (deprecated) */
955 buffer
[2] = 0; /* RCODE2 (deprecated) */
957 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
959 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
960 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
965 static int dhcp_client_send_raw(
966 sd_dhcp_client
*client
,
970 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
971 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
973 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
977 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
983 if (client
->hostname
) {
984 /* According to RFC 4702 "clients that send the Client FQDN option in
985 their messages MUST NOT also send the Host Name option". Just send
986 one of the two depending on the hostname type.
988 if (dns_name_is_single_label(client
->hostname
)) {
989 /* it is unclear from RFC 2131 if client should send hostname in
990 DHCPDISCOVER but dhclient does and so we do as well
992 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
993 SD_DHCP_OPTION_HOST_NAME
,
994 strlen(client
->hostname
), client
->hostname
);
996 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
1002 if (client
->vendor_class_identifier
) {
1003 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1004 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1005 strlen(client
->vendor_class_identifier
),
1006 client
->vendor_class_identifier
);
1011 if (client
->mudurl
) {
1012 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1013 SD_DHCP_OPTION_MUD_URL
,
1014 strlen(client
->mudurl
),
1020 if (client
->user_class
) {
1021 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1022 SD_DHCP_OPTION_USER_CLASS
,
1023 strv_length(client
->user_class
),
1024 client
->user_class
);
1029 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
) {
1030 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
1031 j
->option
, j
->length
, j
->data
);
1036 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
1037 r
= dhcp_option_append(
1038 &packet
->dhcp
, optlen
, optoffset
, 0,
1039 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
1040 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
1049 static int client_send_discover(sd_dhcp_client
*client
) {
1050 _cleanup_free_ DHCPPacket
*discover
= NULL
;
1051 size_t optoffset
, optlen
;
1055 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
1057 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
1058 &optlen
, &optoffset
);
1062 /* the client may suggest values for the network address
1063 and lease time in the DHCPDISCOVER message. The client may include
1064 the ’requested IP address’ option to suggest that a particular IP
1065 address be assigned, and may include the ’IP address lease time’
1066 option to suggest the lease time it would like.
1068 /* RFC7844 section 3:
1069 SHOULD NOT contain any other option. */
1070 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
1071 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1072 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1073 4, &client
->last_addr
);
1078 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
1082 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1083 SD_DHCP_OPTION_END
, 0, NULL
);
1087 /* We currently ignore:
1088 The client SHOULD wait a random time between one and ten seconds to
1089 desynchronize the use of DHCP at startup.
1091 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1095 log_dhcp_client(client
, "DISCOVER");
1100 static int client_send_request(sd_dhcp_client
*client
) {
1101 _cleanup_free_ DHCPPacket
*request
= NULL
;
1102 size_t optoffset
, optlen
;
1107 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
1111 switch (client
->state
) {
1112 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1113 SELECTING should be REQUESTING)
1116 case DHCP_STATE_REQUESTING
:
1117 /* Client inserts the address of the selected server in ’server
1118 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1119 filled in with the yiaddr value from the chosen DHCPOFFER.
1122 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1123 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1124 4, &client
->lease
->server_address
);
1128 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1129 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1130 4, &client
->lease
->address
);
1136 case DHCP_STATE_INIT_REBOOT
:
1137 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1138 option MUST be filled in with client’s notion of its previously
1139 assigned address. ’ciaddr’ MUST be zero.
1141 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1142 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1143 4, &client
->last_addr
);
1148 case DHCP_STATE_RENEWING
:
1149 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1150 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1151 client’s IP address.
1154 case DHCP_STATE_REBINDING
:
1155 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1156 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1157 client’s IP address.
1159 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1161 request
->dhcp
.ciaddr
= client
->lease
->address
;
1165 case DHCP_STATE_INIT
:
1166 case DHCP_STATE_SELECTING
:
1167 case DHCP_STATE_REBOOTING
:
1168 case DHCP_STATE_BOUND
:
1169 case DHCP_STATE_STOPPED
:
1173 r
= client_append_common_discover_request_options(client
, request
, &optoffset
, optlen
);
1177 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1178 SD_DHCP_OPTION_END
, 0, NULL
);
1182 if (client
->state
== DHCP_STATE_RENEWING
)
1183 r
= dhcp_network_send_udp_socket(client
->fd
,
1184 client
->lease
->server_address
,
1187 sizeof(DHCPMessage
) + optoffset
);
1189 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1193 switch (client
->state
) {
1195 case DHCP_STATE_REQUESTING
:
1196 log_dhcp_client(client
, "REQUEST (requesting)");
1199 case DHCP_STATE_INIT_REBOOT
:
1200 log_dhcp_client(client
, "REQUEST (init-reboot)");
1203 case DHCP_STATE_RENEWING
:
1204 log_dhcp_client(client
, "REQUEST (renewing)");
1207 case DHCP_STATE_REBINDING
:
1208 log_dhcp_client(client
, "REQUEST (rebinding)");
1212 log_dhcp_client(client
, "REQUEST (invalid)");
1219 static int client_start(sd_dhcp_client
*client
);
1221 static int client_timeout_resend(
1226 sd_dhcp_client
*client
= userdata
;
1227 DHCP_CLIENT_DONT_DESTROY(client
);
1228 usec_t next_timeout
;
1234 assert(client
->event
);
1236 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1240 switch (client
->state
) {
1242 case DHCP_STATE_RENEWING
:
1243 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->t2_time
);
1246 case DHCP_STATE_REBINDING
:
1247 next_timeout
= client_compute_reacquisition_timeout(time_now
, client
->expire_time
);
1250 case DHCP_STATE_REBOOTING
:
1251 /* start over as we did not receive a timely ack or nak */
1252 r
= client_initialize(client
);
1256 r
= client_start(client
);
1260 log_dhcp_client(client
, "REBOOTED");
1263 case DHCP_STATE_INIT
:
1264 case DHCP_STATE_INIT_REBOOT
:
1265 case DHCP_STATE_SELECTING
:
1266 case DHCP_STATE_REQUESTING
:
1267 case DHCP_STATE_BOUND
:
1268 if (client
->attempt
>= client
->max_attempts
)
1272 next_timeout
= client_compute_request_timeout(time_now
, client
->attempt
);
1275 case DHCP_STATE_STOPPED
:
1280 assert_not_reached("Unhandled choice");
1283 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1284 clock_boottime_or_monotonic(),
1285 next_timeout
, 10 * USEC_PER_MSEC
,
1286 client_timeout_resend
, client
,
1287 client
->event_priority
, "dhcp4-resend-timer", true);
1291 switch (client
->state
) {
1292 case DHCP_STATE_INIT
:
1293 r
= client_send_discover(client
);
1295 client
->state
= DHCP_STATE_SELECTING
;
1296 client
->attempt
= 0;
1297 } else if (client
->attempt
>= client
->max_attempts
)
1302 case DHCP_STATE_SELECTING
:
1303 r
= client_send_discover(client
);
1304 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1309 case DHCP_STATE_INIT_REBOOT
:
1310 case DHCP_STATE_REQUESTING
:
1311 case DHCP_STATE_RENEWING
:
1312 case DHCP_STATE_REBINDING
:
1313 r
= client_send_request(client
);
1314 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1317 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1318 client
->state
= DHCP_STATE_REBOOTING
;
1320 client
->request_sent
= time_now
;
1323 case DHCP_STATE_REBOOTING
:
1324 case DHCP_STATE_BOUND
:
1327 case DHCP_STATE_STOPPED
:
1332 if (client
->attempt
>= TRANSIENT_FAILURE_ATTEMPTS
)
1333 client_notify(client
, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE
);
1338 client_stop(client
, r
);
1340 /* Errors were dealt with when stopping the client, don't spill
1341 errors into the event loop handler */
1345 static int client_initialize_io_events(
1346 sd_dhcp_client
*client
,
1347 sd_event_io_handler_t io_callback
) {
1352 assert(client
->event
);
1354 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1355 client
->fd
, EPOLLIN
, io_callback
,
1360 r
= sd_event_source_set_priority(client
->receive_message
,
1361 client
->event_priority
);
1365 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1371 client_stop(client
, r
);
1376 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1381 assert(client
->event
);
1383 if (client
->start_delay
> 0) {
1384 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1385 usec
+= client
->start_delay
;
1388 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1389 clock_boottime_or_monotonic(),
1391 client_timeout_resend
, client
,
1392 client
->event_priority
, "dhcp4-resend-timer", true);
1394 client_stop(client
, r
);
1400 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1401 client_initialize_io_events(client
, io_callback
);
1402 client_initialize_time_events(client
);
1407 static int client_start_delayed(sd_dhcp_client
*client
) {
1410 assert_return(client
, -EINVAL
);
1411 assert_return(client
->event
, -EINVAL
);
1412 assert_return(client
->ifindex
> 0, -EINVAL
);
1413 assert_return(client
->fd
< 0, -EBUSY
);
1414 assert_return(client
->xid
== 0, -EINVAL
);
1415 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1417 client
->xid
= random_u32();
1419 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1420 client
->mac_addr
, client
->mac_addr_len
,
1421 client
->bcast_addr
, client
->bcast_addr_len
,
1422 client
->arp_type
, client
->port
);
1424 client_stop(client
, r
);
1429 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1430 client
->start_time
= now(clock_boottime_or_monotonic());
1432 return client_initialize_events(client
, client_receive_message_raw
);
1435 static int client_start(sd_dhcp_client
*client
) {
1436 client
->start_delay
= 0;
1437 return client_start_delayed(client
);
1440 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1441 sd_dhcp_client
*client
= userdata
;
1442 DHCP_CLIENT_DONT_DESTROY(client
);
1444 log_dhcp_client(client
, "EXPIRED");
1446 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1448 /* lease was lost, start over if not freed or stopped in callback */
1449 if (client
->state
!= DHCP_STATE_STOPPED
) {
1450 client_initialize(client
);
1451 client_start(client
);
1457 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1458 sd_dhcp_client
*client
= userdata
;
1459 DHCP_CLIENT_DONT_DESTROY(client
);
1464 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1465 client
->fd
= safe_close(client
->fd
);
1467 client
->state
= DHCP_STATE_REBINDING
;
1468 client
->attempt
= 0;
1470 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
, client
->xid
,
1471 client
->mac_addr
, client
->mac_addr_len
,
1472 client
->bcast_addr
, client
->bcast_addr_len
,
1473 client
->arp_type
, client
->port
);
1475 client_stop(client
, r
);
1480 return client_initialize_events(client
, client_receive_message_raw
);
1483 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1484 sd_dhcp_client
*client
= userdata
;
1485 DHCP_CLIENT_DONT_DESTROY(client
);
1488 client
->state
= DHCP_STATE_RENEWING
;
1489 else if (client
->state
!= DHCP_STATE_INIT
)
1490 client
->state
= DHCP_STATE_INIT_REBOOT
;
1491 client
->attempt
= 0;
1493 return client_initialize_time_events(client
);
1496 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1497 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1500 r
= dhcp_lease_new(&lease
);
1504 if (client
->client_id_len
) {
1505 r
= dhcp_lease_set_client_id(lease
,
1506 (uint8_t *) &client
->client_id
,
1507 client
->client_id_len
);
1512 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1513 if (r
!= DHCP_OFFER
) {
1514 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1518 lease
->next_server
= offer
->siaddr
;
1519 lease
->address
= offer
->yiaddr
;
1521 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1522 lease
->lifetime
= client
->fallback_lease_lifetime
;
1524 if (lease
->address
== 0 ||
1525 lease
->server_address
== 0 ||
1526 lease
->lifetime
== 0) {
1527 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1531 if (!lease
->have_subnet_mask
) {
1532 r
= dhcp_lease_set_default_subnet_mask(lease
);
1534 log_dhcp_client(client
,
1535 "received lease lacks subnet mask, "
1536 "and a fallback one cannot be generated, ignoring");
1541 sd_dhcp_lease_unref(client
->lease
);
1542 client
->lease
= TAKE_PTR(lease
);
1544 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1547 log_dhcp_client(client
, "OFFER");
1552 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1555 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1556 if (r
!= DHCP_FORCERENEW
)
1559 log_dhcp_client(client
, "FORCERENEW");
1564 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1565 if (a
->address
!= b
->address
)
1568 if (a
->subnet_mask
!= b
->subnet_mask
)
1571 if (a
->router_size
!= b
->router_size
)
1574 for (size_t i
= 0; i
< a
->router_size
; i
++)
1575 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1581 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1582 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1583 _cleanup_free_
char *error_message
= NULL
;
1586 r
= dhcp_lease_new(&lease
);
1590 if (client
->client_id_len
) {
1591 r
= dhcp_lease_set_client_id(lease
,
1592 (uint8_t *) &client
->client_id
,
1593 client
->client_id_len
);
1598 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1599 if (r
== DHCP_NAK
) {
1600 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1601 return -EADDRNOTAVAIL
;
1604 if (r
!= DHCP_ACK
) {
1605 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1609 lease
->next_server
= ack
->siaddr
;
1611 lease
->address
= ack
->yiaddr
;
1613 if (lease
->address
== INADDR_ANY
||
1614 lease
->server_address
== INADDR_ANY
||
1615 lease
->lifetime
== 0) {
1616 log_dhcp_client(client
, "received lease lacks address, server "
1617 "address or lease lifetime, ignoring");
1621 if (lease
->subnet_mask
== INADDR_ANY
) {
1622 r
= dhcp_lease_set_default_subnet_mask(lease
);
1624 log_dhcp_client(client
,
1625 "received lease lacks subnet mask, "
1626 "and a fallback one cannot be generated, ignoring");
1631 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1632 if (client
->lease
) {
1633 if (lease_equal(client
->lease
, lease
))
1634 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1636 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1638 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1641 client
->lease
= TAKE_PTR(lease
);
1643 log_dhcp_client(client
, "ACK");
1648 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1650 char time_string
[FORMAT_TIMESPAN_MAX
];
1654 assert(client
->event
);
1655 assert(client
->lease
);
1656 assert(client
->lease
->lifetime
);
1658 /* don't set timers for infinite leases */
1659 if (client
->lease
->lifetime
== 0xffffffff) {
1660 (void) event_source_disable(client
->timeout_t1
);
1661 (void) event_source_disable(client
->timeout_t2
);
1662 (void) event_source_disable(client
->timeout_expire
);
1667 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1670 assert(client
->request_sent
<= time_now
);
1672 /* verify that 0 < t2 < lifetime */
1673 if (client
->lease
->t2
== 0 || client
->lease
->t2
>= client
->lease
->lifetime
)
1674 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1675 /* verify that 0 < t1 < lifetime */
1676 if (client
->lease
->t1
== 0 || client
->lease
->t1
>= client
->lease
->t2
)
1677 client
->lease
->t1
= T1_DEFAULT(client
->lease
->lifetime
);
1678 /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
1679 * could not evalate to false if t1 >= t2; so setting t2 to T2_DEFAULT
1680 * guarantees t1 < t2. */
1681 if (client
->lease
->t1
>= client
->lease
->t2
)
1682 client
->lease
->t2
= T2_DEFAULT(client
->lease
->lifetime
);
1684 client
->expire_time
= client
->request_sent
+ client
->lease
->lifetime
* USEC_PER_SEC
;
1685 client
->t1_time
= client
->request_sent
+ client
->lease
->t1
* USEC_PER_SEC
;
1686 client
->t2_time
= client
->request_sent
+ client
->lease
->t2
* USEC_PER_SEC
;
1688 /* RFC2131 section 4.4.5:
1689 * Times T1 and T2 SHOULD be chosen with some random "fuzz".
1690 * Since the RFC doesn't specify here the exact 'fuzz' to use,
1691 * we use the range from section 4.1: -1 to +1 sec. */
1692 client
->t1_time
= usec_sub_signed(client
->t1_time
, RFC2131_RANDOM_FUZZ
);
1693 client
->t2_time
= usec_sub_signed(client
->t2_time
, RFC2131_RANDOM_FUZZ
);
1695 /* after fuzzing, ensure t2 is still >= t1 */
1696 client
->t2_time
= MAX(client
->t1_time
, client
->t2_time
);
1698 /* arm lifetime timeout */
1699 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1700 clock_boottime_or_monotonic(),
1701 client
->expire_time
, 10 * USEC_PER_MSEC
,
1702 client_timeout_expire
, client
,
1703 client
->event_priority
, "dhcp4-lifetime", true);
1707 /* don't arm earlier timeouts if this has already expired */
1708 if (client
->expire_time
<= time_now
)
1711 log_dhcp_client(client
, "lease expires in %s",
1712 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, client
->expire_time
- time_now
, USEC_PER_SEC
));
1714 /* arm T2 timeout */
1715 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1716 clock_boottime_or_monotonic(),
1717 client
->t2_time
, 10 * USEC_PER_MSEC
,
1718 client_timeout_t2
, client
,
1719 client
->event_priority
, "dhcp4-t2-timeout", true);
1723 /* don't arm earlier timeout if this has already expired */
1724 if (client
->t2_time
<= time_now
)
1727 log_dhcp_client(client
, "T2 expires in %s",
1728 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, client
->t2_time
- time_now
, USEC_PER_SEC
));
1730 /* arm T1 timeout */
1731 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1732 clock_boottime_or_monotonic(),
1733 client
->t1_time
, 10 * USEC_PER_MSEC
,
1734 client_timeout_t1
, client
,
1735 client
->event_priority
, "dhcp4-t1-timer", true);
1739 if (client
->t1_time
> time_now
)
1740 log_dhcp_client(client
, "T1 expires in %s",
1741 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, client
->t1_time
- time_now
, USEC_PER_SEC
));
1746 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1747 DHCP_CLIENT_DONT_DESTROY(client
);
1748 char time_string
[FORMAT_TIMESPAN_MAX
];
1749 int r
= 0, notify_event
= 0;
1752 assert(client
->event
);
1755 switch (client
->state
) {
1756 case DHCP_STATE_SELECTING
:
1758 r
= client_handle_offer(client
, message
, len
);
1761 client
->state
= DHCP_STATE_REQUESTING
;
1762 client
->attempt
= 0;
1764 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1765 clock_boottime_or_monotonic(),
1767 client_timeout_resend
, client
,
1768 client
->event_priority
, "dhcp4-resend-timer", true);
1771 } else if (r
== -ENOMSG
)
1772 /* invalid message, let's ignore it */
1777 case DHCP_STATE_REBOOTING
:
1778 case DHCP_STATE_REQUESTING
:
1779 case DHCP_STATE_RENEWING
:
1780 case DHCP_STATE_REBINDING
:
1782 r
= client_handle_ack(client
, message
, len
);
1784 client
->start_delay
= 0;
1785 (void) event_source_disable(client
->timeout_resend
);
1786 client
->receive_message
=
1787 sd_event_source_unref(client
->receive_message
);
1788 client
->fd
= safe_close(client
->fd
);
1790 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1791 DHCP_STATE_REBOOTING
))
1792 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1793 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1796 client
->state
= DHCP_STATE_BOUND
;
1797 client
->attempt
= 0;
1799 client
->last_addr
= client
->lease
->address
;
1801 r
= client_set_lease_timeouts(client
);
1803 log_dhcp_client(client
, "could not set lease timeouts");
1807 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1809 log_dhcp_client(client
, "could not bind UDP socket");
1815 client_initialize_io_events(client
, client_receive_message_udp
);
1818 client_notify(client
, notify_event
);
1819 if (client
->state
== DHCP_STATE_STOPPED
)
1823 } else if (r
== -EADDRNOTAVAIL
) {
1824 /* got a NAK, let's restart the client */
1825 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1827 r
= client_initialize(client
);
1831 r
= client_start_delayed(client
);
1835 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1836 client
->start_delay
, USEC_PER_SEC
));
1838 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1839 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1842 } else if (r
== -ENOMSG
)
1843 /* invalid message, let's ignore it */
1848 case DHCP_STATE_BOUND
:
1849 r
= client_handle_forcerenew(client
, message
, len
);
1851 r
= client_timeout_t1(NULL
, 0, client
);
1854 } else if (r
== -ENOMSG
)
1855 /* invalid message, let's ignore it */
1860 case DHCP_STATE_INIT
:
1861 case DHCP_STATE_INIT_REBOOT
:
1865 case DHCP_STATE_STOPPED
:
1872 client_stop(client
, r
);
1877 static int client_receive_message_udp(
1883 sd_dhcp_client
*client
= userdata
;
1884 _cleanup_free_ DHCPMessage
*message
= NULL
;
1885 const uint8_t *expected_chaddr
= NULL
;
1886 uint8_t expected_hlen
= 0;
1887 ssize_t len
, buflen
;
1892 buflen
= next_datagram_size_fd(fd
);
1893 if (buflen
== -ENETDOWN
)
1894 /* the link is down. Don't return an error or the I/O event
1895 source will be disconnected and we won't be able to receive
1896 packets again when the link comes back. */
1901 message
= malloc0(buflen
);
1905 len
= recv(fd
, message
, buflen
, 0);
1907 /* see comment above for why we shouldn't error out on ENETDOWN. */
1908 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1911 return log_dhcp_client_errno(client
, errno
,
1912 "Could not receive message from UDP socket: %m");
1914 if ((size_t) len
< sizeof(DHCPMessage
)) {
1915 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1919 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1920 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1924 if (message
->op
!= BOOTREPLY
) {
1925 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1929 if (message
->htype
!= client
->arp_type
) {
1930 log_dhcp_client(client
, "Packet type does not match client type");
1934 if (client
->arp_type
== ARPHRD_ETHER
) {
1935 expected_hlen
= ETH_ALEN
;
1936 expected_chaddr
= &client
->mac_addr
[0];
1939 if (message
->hlen
!= expected_hlen
) {
1940 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1944 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1945 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1949 if (client
->state
!= DHCP_STATE_BOUND
&&
1950 be32toh(message
->xid
) != client
->xid
) {
1951 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1952 so ignore the xid in this case */
1953 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1954 be32toh(message
->xid
), client
->xid
);
1958 return client_handle_message(client
, message
, len
);
1961 static int client_receive_message_raw(
1967 sd_dhcp_client
*client
= userdata
;
1968 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1969 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
;
1970 struct iovec iov
= {};
1971 struct msghdr msg
= {
1974 .msg_control
= &control
,
1975 .msg_controllen
= sizeof(control
),
1977 struct cmsghdr
*cmsg
;
1978 bool checksum
= true;
1979 ssize_t buflen
, len
;
1985 buflen
= next_datagram_size_fd(fd
);
1986 if (buflen
== -ENETDOWN
)
1991 packet
= malloc0(buflen
);
1995 iov
= IOVEC_MAKE(packet
, buflen
);
1997 len
= recvmsg_safe(fd
, &msg
, 0);
1998 if (IN_SET(len
, -EAGAIN
, -EINTR
, -ENETDOWN
))
2001 return log_dhcp_client_errno(client
, len
,
2002 "Could not receive message from raw socket: %m");
2004 if ((size_t) len
< sizeof(DHCPPacket
))
2007 cmsg
= cmsg_find(&msg
, SOL_PACKET
, PACKET_AUXDATA
, CMSG_LEN(sizeof(struct tpacket_auxdata
)));
2009 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*) CMSG_DATA(cmsg
);
2010 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2013 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
2017 len
-= DHCP_IP_UDP_SIZE
;
2019 return client_handle_message(client
, &packet
->dhcp
, len
);
2022 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2023 assert_return(client
, -EINVAL
);
2024 assert_return(client
->fd
>= 0, -EINVAL
);
2029 client
->start_delay
= 0;
2030 client
->attempt
= 1;
2031 client
->state
= DHCP_STATE_RENEWING
;
2033 return client_initialize_time_events(client
);
2036 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2039 assert_return(client
, -EINVAL
);
2041 r
= client_initialize(client
);
2045 /* RFC7844 section 3.3:
2046 SHOULD perform a complete four-way handshake, starting with a
2047 DHCPDISCOVER, to obtain a new address lease. If the client can
2048 ascertain that this is exactly the same network to which it was
2049 previously connected, and if the link-layer address did not change,
2050 the client MAY issue a DHCPREQUEST to try to reclaim the current
2052 if (client
->last_addr
&& !client
->anonymize
)
2053 client
->state
= DHCP_STATE_INIT_REBOOT
;
2055 r
= client_start(client
);
2057 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2062 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2063 assert_return(client
, -EINVAL
);
2064 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2065 assert_return(client
->lease
, -EUNATCH
);
2067 _cleanup_free_ DHCPPacket
*release
= NULL
;
2068 size_t optoffset
, optlen
;
2071 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2075 /* Fill up release IP and MAC */
2076 release
->dhcp
.ciaddr
= client
->lease
->address
;
2077 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2079 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2080 SD_DHCP_OPTION_END
, 0, NULL
);
2084 r
= dhcp_network_send_udp_socket(client
->fd
,
2085 client
->lease
->server_address
,
2088 sizeof(DHCPMessage
) + optoffset
);
2092 log_dhcp_client(client
, "RELEASE");
2097 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2098 assert_return(client
, -EINVAL
);
2099 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2100 assert_return(client
->lease
, -EUNATCH
);
2102 _cleanup_free_ DHCPPacket
*release
= NULL
;
2103 size_t optoffset
, optlen
;
2106 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2110 release
->dhcp
.ciaddr
= client
->lease
->address
;
2111 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2113 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2114 SD_DHCP_OPTION_END
, 0, NULL
);
2118 r
= dhcp_network_send_udp_socket(client
->fd
,
2119 client
->lease
->server_address
,
2122 sizeof(DHCPMessage
) + optoffset
);
2126 log_dhcp_client(client
, "DECLINE");
2128 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2130 if (client
->state
!= DHCP_STATE_STOPPED
) {
2131 r
= sd_dhcp_client_start(client
);
2139 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2143 DHCP_CLIENT_DONT_DESTROY(client
);
2145 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2146 client
->state
= DHCP_STATE_STOPPED
;
2151 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2154 assert_return(client
, -EINVAL
);
2155 assert_return(!client
->event
, -EBUSY
);
2158 client
->event
= sd_event_ref(event
);
2160 r
= sd_event_default(&client
->event
);
2165 client
->event_priority
= priority
;
2170 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2171 assert_return(client
, -EINVAL
);
2173 client
->event
= sd_event_unref(client
->event
);
2178 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2179 assert_return(client
, NULL
);
2181 return client
->event
;
2184 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2188 log_dhcp_client(client
, "FREE");
2190 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2191 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2192 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2193 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2195 client_initialize(client
);
2197 sd_dhcp_client_detach_event(client
);
2199 sd_dhcp_lease_unref(client
->lease
);
2201 set_free(client
->req_opts
);
2202 free(client
->hostname
);
2203 free(client
->vendor_class_identifier
);
2204 free(client
->mudurl
);
2205 client
->user_class
= strv_free(client
->user_class
);
2206 ordered_hashmap_free(client
->extra_options
);
2207 ordered_hashmap_free(client
->vendor_options
);
2208 return mfree(client
);
2211 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2213 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2214 const uint8_t *opts
;
2218 assert_return(ret
, -EINVAL
);
2220 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2224 *client
= (sd_dhcp_client
) {
2226 .state
= DHCP_STATE_INIT
,
2229 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2230 .port
= DHCP_PORT_CLIENT
,
2231 .anonymize
= !!anonymize
,
2232 .max_attempts
= UINT64_MAX
,
2233 .ip_service_type
= -1,
2235 /* NOTE: this could be moved to a function. */
2237 n_opts
= ELEMENTSOF(default_req_opts_anonymize
);
2238 opts
= default_req_opts_anonymize
;
2240 n_opts
= ELEMENTSOF(default_req_opts
);
2241 opts
= default_req_opts
;
2244 for (size_t i
= 0; i
< n_opts
; i
++) {
2245 r
= sd_dhcp_client_set_request_option(client
, opts
[i
]);
2250 *ret
= TAKE_PTR(client
);