1 /* SPDX-License-Identifier: LGPL-2.1+ */
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"
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 "event-util.h"
24 #include "hostname-util.h"
26 #include "memory-util.h"
27 #include "random-util.h"
28 #include "string-util.h"
33 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
34 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
36 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
37 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
39 typedef struct sd_dhcp_client_id
{
43 /* 0: Generic (non-LL) (RFC 2132) */
44 uint8_t data
[MAX_CLIENT_ID_LEN
];
47 /* 1: Ethernet Link-Layer (RFC 2132) */
48 uint8_t haddr
[ETH_ALEN
];
51 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
55 /* 255: Node-specific (RFC 4361) */
60 uint8_t data
[MAX_CLIENT_ID_LEN
];
63 } _packed_ sd_dhcp_client_id
;
65 struct sd_dhcp_client
{
71 sd_event_source
*timeout_resend
;
75 union sockaddr_union link
;
76 sd_event_source
*receive_message
;
77 bool request_broadcast
;
79 size_t req_opts_allocated
;
83 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
86 sd_dhcp_client_id client_id
;
89 char *vendor_class_identifier
;
93 uint32_t fallback_lease_lifetime
;
97 uint64_t max_attempts
;
98 OrderedHashmap
*extra_options
;
99 OrderedHashmap
*vendor_options
;
101 sd_event_source
*timeout_t1
;
102 sd_event_source
*timeout_t2
;
103 sd_event_source
*timeout_expire
;
104 sd_dhcp_client_callback_t callback
;
106 sd_dhcp_lease
*lease
;
111 static const uint8_t default_req_opts
[] = {
112 SD_DHCP_OPTION_SUBNET_MASK
,
113 SD_DHCP_OPTION_ROUTER
,
114 SD_DHCP_OPTION_HOST_NAME
,
115 SD_DHCP_OPTION_DOMAIN_NAME
,
116 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
119 /* RFC7844 section 3:
120 MAY contain the Parameter Request List option.
122 The client intending to protect its privacy SHOULD only request a
123 minimal number of options in the PRL and SHOULD also randomly shuffle
124 the ordering of option codes in the PRL. If this random ordering
125 cannot be implemented, the client MAY order the option codes in the
126 PRL by option code number (lowest to highest).
128 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
129 static const uint8_t default_req_opts_anonymize
[] = {
130 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
131 SD_DHCP_OPTION_ROUTER
, /* 3 */
132 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
133 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
134 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
135 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
136 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
137 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
138 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
139 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
140 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
141 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
142 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
145 static int client_receive_message_raw(
150 static int client_receive_message_udp(
155 static void client_stop(sd_dhcp_client
*client
, int error
);
157 int sd_dhcp_client_id_to_string(const void *data
, size_t len
, char **ret
) {
158 const sd_dhcp_client_id
*client_id
= data
;
159 _cleanup_free_
char *t
= NULL
;
162 assert_return(data
, -EINVAL
);
163 assert_return(len
>= 1, -EINVAL
);
164 assert_return(ret
, -EINVAL
);
167 if (len
> MAX_CLIENT_ID_LEN
)
170 switch (client_id
->type
) {
172 if (utf8_is_printable((char *) client_id
->gen
.data
, len
))
173 r
= asprintf(&t
, "%.*s", (int) len
, client_id
->gen
.data
);
175 r
= asprintf(&t
, "DATA");
178 if (len
!= sizeof_field(sd_dhcp_client_id
, eth
))
181 r
= asprintf(&t
, "%x:%x:%x:%x:%x:%x",
182 client_id
->eth
.haddr
[0],
183 client_id
->eth
.haddr
[1],
184 client_id
->eth
.haddr
[2],
185 client_id
->eth
.haddr
[3],
186 client_id
->eth
.haddr
[4],
187 client_id
->eth
.haddr
[5]);
190 r
= asprintf(&t
, "ARP/LL");
196 uint32_t iaid
= be32toh(client_id
->ns
.iaid
);
197 uint16_t duid_type
= be16toh(client_id
->ns
.duid
.type
);
198 if (dhcp_validate_duid_len(duid_type
, len
- 6, true) < 0)
201 r
= asprintf(&t
, "IAID:0x%x/DUID", iaid
);
211 int sd_dhcp_client_set_callback(
212 sd_dhcp_client
*client
,
213 sd_dhcp_client_callback_t cb
,
216 assert_return(client
, -EINVAL
);
218 client
->callback
= cb
;
219 client
->userdata
= userdata
;
224 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
225 assert_return(client
, -EINVAL
);
227 client
->request_broadcast
= !!broadcast
;
232 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
235 assert_return(client
, -EINVAL
);
236 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
240 case SD_DHCP_OPTION_PAD
:
241 case SD_DHCP_OPTION_OVERLOAD
:
242 case SD_DHCP_OPTION_MESSAGE_TYPE
:
243 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
244 case SD_DHCP_OPTION_END
:
251 for (i
= 0; i
< client
->req_opts_size
; i
++)
252 if (client
->req_opts
[i
] == option
)
255 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
256 client
->req_opts_size
+ 1))
259 client
->req_opts
[client
->req_opts_size
++] = option
;
264 int sd_dhcp_client_set_request_address(
265 sd_dhcp_client
*client
,
266 const struct in_addr
*last_addr
) {
268 assert_return(client
, -EINVAL
);
269 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
272 client
->last_addr
= last_addr
->s_addr
;
274 client
->last_addr
= INADDR_ANY
;
279 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
281 assert_return(client
, -EINVAL
);
282 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
283 assert_return(ifindex
> 0, -EINVAL
);
285 client
->ifindex
= ifindex
;
289 int sd_dhcp_client_set_mac(
290 sd_dhcp_client
*client
,
295 DHCP_CLIENT_DONT_DESTROY(client
);
296 bool need_restart
= false;
299 assert_return(client
, -EINVAL
);
300 assert_return(addr
, -EINVAL
);
301 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
302 assert_return(arp_type
> 0, -EINVAL
);
304 if (arp_type
== ARPHRD_ETHER
)
305 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
306 else if (arp_type
== ARPHRD_INFINIBAND
)
307 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
311 if (client
->mac_addr_len
== addr_len
&&
312 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
315 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
316 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
318 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
321 memcpy(&client
->mac_addr
, addr
, addr_len
);
322 client
->mac_addr_len
= addr_len
;
323 client
->arp_type
= arp_type
;
325 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
326 r
= sd_dhcp_client_start(client
);
328 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
334 int sd_dhcp_client_get_client_id(
335 sd_dhcp_client
*client
,
337 const uint8_t **data
,
340 assert_return(client
, -EINVAL
);
341 assert_return(type
, -EINVAL
);
342 assert_return(data
, -EINVAL
);
343 assert_return(data_len
, -EINVAL
);
348 if (client
->client_id_len
) {
349 *type
= client
->client_id
.type
;
350 *data
= client
->client_id
.raw
.data
;
351 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
357 int sd_dhcp_client_set_client_id(
358 sd_dhcp_client
*client
,
363 DHCP_CLIENT_DONT_DESTROY(client
);
364 bool need_restart
= false;
367 assert_return(client
, -EINVAL
);
368 assert_return(data
, -EINVAL
);
369 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
371 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
372 client
->client_id
.type
== type
&&
373 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
376 /* For hardware types, log debug message about unexpected data length.
378 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
379 * last last 8 bytes of the address are stable and suitable to put into
380 * the client-id. The caller is advised to account for that. */
381 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
382 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
383 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
384 "unexpected address length %zu",
387 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
388 log_dhcp_client(client
, "Changing client ID on running DHCP "
389 "client, restarting");
391 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
394 client
->client_id
.type
= type
;
395 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
396 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
398 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
399 r
= sd_dhcp_client_start(client
);
401 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
408 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
409 * without further modification. Otherwise, if duid_type is supported, DUID
410 * is set based on that type. Otherwise, an error is returned.
412 static int dhcp_client_set_iaid_duid_internal(
413 sd_dhcp_client
*client
,
422 DHCP_CLIENT_DONT_DESTROY(client
);
426 assert_return(client
, -EINVAL
);
427 assert_return(duid_len
== 0 || duid
, -EINVAL
);
430 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
432 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
435 zero(client
->client_id
);
436 client
->client_id
.type
= 255;
440 client
->client_id
.ns
.iaid
= htobe32(iaid
);
442 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
443 client
->mac_addr_len
,
445 &client
->client_id
.ns
.iaid
);
447 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
452 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
453 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
454 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
458 if (client
->mac_addr_len
== 0)
459 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
461 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
463 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
466 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
468 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
471 if (client
->mac_addr_len
== 0)
472 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
474 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
476 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
479 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
481 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
484 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
487 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
488 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
490 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
491 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
492 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
493 r
= sd_dhcp_client_start(client
);
495 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
501 int sd_dhcp_client_set_iaid_duid(
502 sd_dhcp_client
*client
,
508 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
511 int sd_dhcp_client_set_iaid_duid_llt(
512 sd_dhcp_client
*client
,
516 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
519 int sd_dhcp_client_set_duid(
520 sd_dhcp_client
*client
,
524 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
527 int sd_dhcp_client_set_duid_llt(
528 sd_dhcp_client
*client
,
530 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
533 int sd_dhcp_client_set_hostname(
534 sd_dhcp_client
*client
,
535 const char *hostname
) {
537 assert_return(client
, -EINVAL
);
539 /* Make sure hostnames qualify as DNS and as Linux hostnames */
541 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
544 return free_and_strdup(&client
->hostname
, hostname
);
547 int sd_dhcp_client_set_vendor_class_identifier(
548 sd_dhcp_client
*client
,
551 assert_return(client
, -EINVAL
);
553 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
556 int sd_dhcp_client_set_mud_url(
557 sd_dhcp_client
*client
,
558 const char *mudurl
) {
560 assert_return(client
, -EINVAL
);
561 assert_return(mudurl
, -EINVAL
);
562 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
563 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
565 return free_and_strdup(&client
->mudurl
, mudurl
);
568 int sd_dhcp_client_set_user_class(
569 sd_dhcp_client
*client
,
570 const char* const* user_class
) {
572 _cleanup_strv_free_
char **s
= NULL
;
575 STRV_FOREACH(p
, (char **) user_class
)
576 if (strlen(*p
) > 255)
577 return -ENAMETOOLONG
;
579 s
= strv_copy((char **) user_class
);
583 client
->user_class
= TAKE_PTR(s
);
588 int sd_dhcp_client_set_client_port(
589 sd_dhcp_client
*client
,
592 assert_return(client
, -EINVAL
);
599 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
600 assert_return(client
, -EINVAL
);
601 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
608 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
609 assert_return(client
, -EINVAL
);
611 client
->max_attempts
= max_attempts
;
616 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
619 assert_return(client
, -EINVAL
);
620 assert_return(v
, -EINVAL
);
622 r
= ordered_hashmap_ensure_allocated(&client
->extra_options
, &dhcp_option_hash_ops
);
626 r
= ordered_hashmap_put(client
->extra_options
, UINT_TO_PTR(v
->option
), v
);
630 sd_dhcp_option_ref(v
);
634 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
637 assert_return(client
, -EINVAL
);
638 assert_return(v
, -EINVAL
);
640 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
644 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
648 sd_dhcp_option_ref(v
);
653 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
654 assert_return(client
, -EINVAL
);
656 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
657 return -EADDRNOTAVAIL
;
660 *ret
= client
->lease
;
665 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
666 assert_return(client
, -EINVAL
);
668 client
->ip_service_type
= type
;
673 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint32_t fallback_lease_lifetime
) {
674 assert_return(client
, -EINVAL
);
675 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
677 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
682 static int client_notify(sd_dhcp_client
*client
, int event
) {
685 if (client
->callback
)
686 return client
->callback(client
, event
, client
->userdata
);
691 static int client_initialize(sd_dhcp_client
*client
) {
692 assert_return(client
, -EINVAL
);
694 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
696 client
->fd
= asynchronous_close(client
->fd
);
698 (void) event_source_disable(client
->timeout_resend
);
699 (void) event_source_disable(client
->timeout_t1
);
700 (void) event_source_disable(client
->timeout_t2
);
701 (void) event_source_disable(client
->timeout_expire
);
705 client
->state
= DHCP_STATE_INIT
;
708 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
713 static void client_stop(sd_dhcp_client
*client
, int error
) {
717 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
718 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
719 log_dhcp_client(client
, "STOPPED");
721 log_dhcp_client(client
, "STOPPED: Unknown event");
723 client_notify(client
, error
);
725 client_initialize(client
);
728 static int client_message_init(
729 sd_dhcp_client
*client
,
733 size_t *_optoffset
) {
735 _cleanup_free_ DHCPPacket
*packet
= NULL
;
736 size_t optlen
, optoffset
, size
;
743 assert(client
->start_time
);
747 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
749 optlen
= DHCP_MIN_OPTIONS_SIZE
;
750 size
= sizeof(DHCPPacket
) + optlen
;
752 packet
= malloc0(size
);
756 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
757 client
->arp_type
, optlen
, &optoffset
);
761 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
762 refuse to issue an DHCP lease if 'secs' is set to zero */
763 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
766 assert(time_now
>= client
->start_time
);
768 /* seconds between sending first and last DISCOVER
769 * must always be strictly positive to deal with broken servers */
770 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
771 packet
->dhcp
.secs
= htobe16(secs
);
773 /* RFC2132 section 4.1
774 A client that cannot receive unicast IP datagrams until its protocol
775 software has been configured with an IP address SHOULD set the
776 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
777 DHCPREQUEST messages that client sends. The BROADCAST bit will
778 provide a hint to the DHCP server and BOOTP relay agent to broadcast
779 any messages to the client on the client's subnet.
781 Note: some interfaces needs this to be enabled, but some networks
782 needs this to be disabled as broadcasts are filteretd, so this
783 needs to be configurable */
784 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
785 packet
->dhcp
.flags
= htobe16(0x8000);
787 /* RFC2132 section 4.1.1:
788 The client MUST include its hardware address in the ’chaddr’ field, if
789 necessary for delivery of DHCP reply messages. Non-Ethernet
790 interfaces will leave 'chaddr' empty and use the client identifier
791 instead (eg, RFC 4390 section 2.1).
793 if (client
->arp_type
== ARPHRD_ETHER
)
794 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
796 /* If no client identifier exists, construct an RFC 4361-compliant one */
797 if (client
->client_id_len
== 0) {
800 client
->client_id
.type
= 255;
802 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
803 true, &client
->client_id
.ns
.iaid
);
807 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
811 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
814 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
815 Identifier option is not set */
816 if (client
->client_id_len
) {
817 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
818 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
819 client
->client_id_len
,
825 /* RFC2131 section 3.5:
826 in its initial DHCPDISCOVER or DHCPREQUEST message, a
827 client may provide the server with a list of specific
828 parameters the client is interested in. If the client
829 includes a list of parameters in a DHCPDISCOVER message,
830 it MUST include that list in any subsequent DHCPREQUEST
834 /* RFC7844 section 3:
835 MAY contain the Parameter Request List option. */
836 /* NOTE: in case that there would be an option to do not send
837 * any PRL at all, the size should be checked before sending */
838 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
839 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
840 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
841 client
->req_opts_size
, client
->req_opts
);
846 /* RFC2131 section 3.5:
847 The client SHOULD include the ’maximum DHCP message size’ option to
848 let the server know how large the server may make its DHCP messages.
850 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
851 than the defined default size unless the Maximum Message Size option
854 RFC3442 "Requirements to Avoid Sizing Constraints":
855 Because a full routing table can be quite large, the standard 576
856 octet maximum size for a DHCP message may be too short to contain
857 some legitimate Classless Static Route options. Because of this,
858 clients implementing the Classless Static Route option SHOULD send a
859 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
860 stack is capable of receiving larger IP datagrams. In this case, the
861 client SHOULD set the value of this option to at least the MTU of the
862 interface that the client is configuring. The client MAY set the
863 value of this option higher, up to the size of the largest UDP packet
864 it is prepared to accept. (Note that the value specified in the
865 Maximum DHCP Message Size option is the total maximum packet size,
866 including IP and UDP headers.)
868 /* RFC7844 section 3:
869 SHOULD NOT contain any other option. */
870 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
871 max_size
= htobe16(size
);
872 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
873 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
880 *_optoffset
= optoffset
;
881 *ret
= TAKE_PTR(packet
);
886 static int client_append_fqdn_option(
887 DHCPMessage
*message
,
892 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
895 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
896 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
897 buffer
[1] = 0; /* RCODE1 (deprecated) */
898 buffer
[2] = 0; /* RCODE2 (deprecated) */
900 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
902 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
903 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
908 static int dhcp_client_send_raw(
909 sd_dhcp_client
*client
,
913 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
914 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
916 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
920 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
927 if (client
->hostname
) {
928 /* According to RFC 4702 "clients that send the Client FQDN option in
929 their messages MUST NOT also send the Host Name option". Just send
930 one of the two depending on the hostname type.
932 if (dns_name_is_single_label(client
->hostname
)) {
933 /* it is unclear from RFC 2131 if client should send hostname in
934 DHCPDISCOVER but dhclient does and so we do as well
936 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
937 SD_DHCP_OPTION_HOST_NAME
,
938 strlen(client
->hostname
), client
->hostname
);
940 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
946 if (client
->vendor_class_identifier
) {
947 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
948 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
949 strlen(client
->vendor_class_identifier
),
950 client
->vendor_class_identifier
);
955 if (client
->mudurl
) {
956 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
957 SD_DHCP_OPTION_MUD_URL
,
958 strlen(client
->mudurl
),
964 if (client
->user_class
) {
965 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
966 SD_DHCP_OPTION_USER_CLASS
,
967 strv_length(client
->user_class
),
973 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
, i
) {
974 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
975 j
->option
, j
->length
, j
->data
);
980 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
981 r
= dhcp_option_append(
982 &packet
->dhcp
, optlen
, optoffset
, 0,
983 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
984 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
993 static int client_send_discover(sd_dhcp_client
*client
) {
994 _cleanup_free_ DHCPPacket
*discover
= NULL
;
995 size_t optoffset
, optlen
;
999 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
1001 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
1002 &optlen
, &optoffset
);
1006 /* the client may suggest values for the network address
1007 and lease time in the DHCPDISCOVER message. The client may include
1008 the ’requested IP address’ option to suggest that a particular IP
1009 address be assigned, and may include the ’IP address lease time’
1010 option to suggest the lease time it would like.
1012 /* RFC7844 section 3:
1013 SHOULD NOT contain any other option. */
1014 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
1015 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1016 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1017 4, &client
->last_addr
);
1022 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
1026 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1027 SD_DHCP_OPTION_END
, 0, NULL
);
1031 /* We currently ignore:
1032 The client SHOULD wait a random time between one and ten seconds to
1033 desynchronize the use of DHCP at startup.
1035 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1039 log_dhcp_client(client
, "DISCOVER");
1044 static int client_send_request(sd_dhcp_client
*client
) {
1045 _cleanup_free_ DHCPPacket
*request
= NULL
;
1046 size_t optoffset
, optlen
;
1051 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
1055 switch (client
->state
) {
1056 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1057 SELECTING should be REQUESTING)
1060 case DHCP_STATE_REQUESTING
:
1061 /* Client inserts the address of the selected server in ’server
1062 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1063 filled in with the yiaddr value from the chosen DHCPOFFER.
1066 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1067 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1068 4, &client
->lease
->server_address
);
1072 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1073 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1074 4, &client
->lease
->address
);
1080 case DHCP_STATE_INIT_REBOOT
:
1081 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1082 option MUST be filled in with client’s notion of its previously
1083 assigned address. ’ciaddr’ MUST be zero.
1085 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1086 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1087 4, &client
->last_addr
);
1092 case DHCP_STATE_RENEWING
:
1093 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1094 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1095 client’s IP address.
1098 case DHCP_STATE_REBINDING
:
1099 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1100 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1101 client’s IP address.
1103 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1105 request
->dhcp
.ciaddr
= client
->lease
->address
;
1109 case DHCP_STATE_INIT
:
1110 case DHCP_STATE_SELECTING
:
1111 case DHCP_STATE_REBOOTING
:
1112 case DHCP_STATE_BOUND
:
1113 case DHCP_STATE_STOPPED
:
1117 r
= client_append_common_discover_request_options(client
, request
, &optoffset
, optlen
);
1121 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1122 SD_DHCP_OPTION_END
, 0, NULL
);
1126 if (client
->state
== DHCP_STATE_RENEWING
)
1127 r
= dhcp_network_send_udp_socket(client
->fd
,
1128 client
->lease
->server_address
,
1131 sizeof(DHCPMessage
) + optoffset
);
1133 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1137 switch (client
->state
) {
1139 case DHCP_STATE_REQUESTING
:
1140 log_dhcp_client(client
, "REQUEST (requesting)");
1143 case DHCP_STATE_INIT_REBOOT
:
1144 log_dhcp_client(client
, "REQUEST (init-reboot)");
1147 case DHCP_STATE_RENEWING
:
1148 log_dhcp_client(client
, "REQUEST (renewing)");
1151 case DHCP_STATE_REBINDING
:
1152 log_dhcp_client(client
, "REQUEST (rebinding)");
1156 log_dhcp_client(client
, "REQUEST (invalid)");
1163 static int client_start(sd_dhcp_client
*client
);
1165 static int client_timeout_resend(
1170 sd_dhcp_client
*client
= userdata
;
1171 DHCP_CLIENT_DONT_DESTROY(client
);
1172 usec_t next_timeout
= 0;
1179 assert(client
->event
);
1181 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1185 switch (client
->state
) {
1187 case DHCP_STATE_RENEWING
:
1189 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1193 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1197 case DHCP_STATE_REBINDING
:
1199 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1203 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1206 case DHCP_STATE_REBOOTING
:
1207 /* start over as we did not receive a timely ack or nak */
1208 r
= client_initialize(client
);
1212 r
= client_start(client
);
1216 log_dhcp_client(client
, "REBOOTED");
1220 case DHCP_STATE_INIT
:
1221 case DHCP_STATE_INIT_REBOOT
:
1222 case DHCP_STATE_SELECTING
:
1223 case DHCP_STATE_REQUESTING
:
1224 case DHCP_STATE_BOUND
:
1226 if (client
->attempt
< client
->max_attempts
)
1231 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1235 case DHCP_STATE_STOPPED
:
1240 next_timeout
+= (random_u32() & 0x1fffff);
1242 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1243 clock_boottime_or_monotonic(),
1244 next_timeout
, 10 * USEC_PER_MSEC
,
1245 client_timeout_resend
, client
,
1246 client
->event_priority
, "dhcp4-resend-timer", true);
1250 switch (client
->state
) {
1251 case DHCP_STATE_INIT
:
1252 r
= client_send_discover(client
);
1254 client
->state
= DHCP_STATE_SELECTING
;
1255 client
->attempt
= 0;
1256 } else if (client
->attempt
>= client
->max_attempts
)
1261 case DHCP_STATE_SELECTING
:
1262 r
= client_send_discover(client
);
1263 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1268 case DHCP_STATE_INIT_REBOOT
:
1269 case DHCP_STATE_REQUESTING
:
1270 case DHCP_STATE_RENEWING
:
1271 case DHCP_STATE_REBINDING
:
1272 r
= client_send_request(client
);
1273 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1276 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1277 client
->state
= DHCP_STATE_REBOOTING
;
1279 client
->request_sent
= time_now
;
1283 case DHCP_STATE_REBOOTING
:
1284 case DHCP_STATE_BOUND
:
1288 case DHCP_STATE_STOPPED
:
1296 client_stop(client
, r
);
1298 /* Errors were dealt with when stopping the client, don't spill
1299 errors into the event loop handler */
1303 static int client_initialize_io_events(
1304 sd_dhcp_client
*client
,
1305 sd_event_io_handler_t io_callback
) {
1310 assert(client
->event
);
1312 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1313 client
->fd
, EPOLLIN
, io_callback
,
1318 r
= sd_event_source_set_priority(client
->receive_message
,
1319 client
->event_priority
);
1323 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1329 client_stop(client
, r
);
1334 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1339 assert(client
->event
);
1341 if (client
->start_delay
> 0) {
1342 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1343 usec
+= client
->start_delay
;
1346 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1347 clock_boottime_or_monotonic(),
1349 client_timeout_resend
, client
,
1350 client
->event_priority
, "dhcp4-resend-timer", true);
1352 client_stop(client
, r
);
1358 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1359 client_initialize_io_events(client
, io_callback
);
1360 client_initialize_time_events(client
);
1365 static int client_start_delayed(sd_dhcp_client
*client
) {
1368 assert_return(client
, -EINVAL
);
1369 assert_return(client
->event
, -EINVAL
);
1370 assert_return(client
->ifindex
> 0, -EINVAL
);
1371 assert_return(client
->fd
< 0, -EBUSY
);
1372 assert_return(client
->xid
== 0, -EINVAL
);
1373 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1375 client
->xid
= random_u32();
1377 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1378 client
->xid
, client
->mac_addr
,
1379 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1381 client_stop(client
, r
);
1386 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1387 client
->start_time
= now(clock_boottime_or_monotonic());
1389 return client_initialize_events(client
, client_receive_message_raw
);
1392 static int client_start(sd_dhcp_client
*client
) {
1393 client
->start_delay
= 0;
1394 return client_start_delayed(client
);
1397 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1398 sd_dhcp_client
*client
= userdata
;
1399 DHCP_CLIENT_DONT_DESTROY(client
);
1401 log_dhcp_client(client
, "EXPIRED");
1403 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1405 /* lease was lost, start over if not freed or stopped in callback */
1406 if (client
->state
!= DHCP_STATE_STOPPED
) {
1407 client_initialize(client
);
1408 client_start(client
);
1414 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1415 sd_dhcp_client
*client
= userdata
;
1416 DHCP_CLIENT_DONT_DESTROY(client
);
1421 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1422 client
->fd
= asynchronous_close(client
->fd
);
1424 client
->state
= DHCP_STATE_REBINDING
;
1425 client
->attempt
= 0;
1427 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1428 client
->xid
, client
->mac_addr
,
1429 client
->mac_addr_len
, client
->arp_type
,
1432 client_stop(client
, r
);
1437 return client_initialize_events(client
, client_receive_message_raw
);
1440 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1441 sd_dhcp_client
*client
= userdata
;
1442 DHCP_CLIENT_DONT_DESTROY(client
);
1444 client
->state
= DHCP_STATE_RENEWING
;
1445 client
->attempt
= 0;
1447 return client_initialize_time_events(client
);
1450 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1451 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1454 r
= dhcp_lease_new(&lease
);
1458 if (client
->client_id_len
) {
1459 r
= dhcp_lease_set_client_id(lease
,
1460 (uint8_t *) &client
->client_id
,
1461 client
->client_id_len
);
1466 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1467 if (r
!= DHCP_OFFER
) {
1468 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1472 lease
->next_server
= offer
->siaddr
;
1473 lease
->address
= offer
->yiaddr
;
1475 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1476 lease
->lifetime
= client
->fallback_lease_lifetime
;
1478 if (lease
->address
== 0 ||
1479 lease
->server_address
== 0 ||
1480 lease
->lifetime
== 0) {
1481 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1485 if (!lease
->have_subnet_mask
) {
1486 r
= dhcp_lease_set_default_subnet_mask(lease
);
1488 log_dhcp_client(client
,
1489 "received lease lacks subnet mask, "
1490 "and a fallback one cannot be generated, ignoring");
1495 sd_dhcp_lease_unref(client
->lease
);
1496 client
->lease
= TAKE_PTR(lease
);
1498 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1501 log_dhcp_client(client
, "OFFER");
1506 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1509 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1510 if (r
!= DHCP_FORCERENEW
)
1513 log_dhcp_client(client
, "FORCERENEW");
1518 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1519 if (a
->address
!= b
->address
)
1522 if (a
->subnet_mask
!= b
->subnet_mask
)
1525 if (a
->router_size
!= b
->router_size
)
1528 for (size_t i
= 0; i
< a
->router_size
; i
++)
1529 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1535 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1536 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1537 _cleanup_free_
char *error_message
= NULL
;
1540 r
= dhcp_lease_new(&lease
);
1544 if (client
->client_id_len
) {
1545 r
= dhcp_lease_set_client_id(lease
,
1546 (uint8_t *) &client
->client_id
,
1547 client
->client_id_len
);
1552 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1553 if (r
== DHCP_NAK
) {
1554 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1555 return -EADDRNOTAVAIL
;
1558 if (r
!= DHCP_ACK
) {
1559 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1563 lease
->next_server
= ack
->siaddr
;
1565 lease
->address
= ack
->yiaddr
;
1567 if (lease
->address
== INADDR_ANY
||
1568 lease
->server_address
== INADDR_ANY
||
1569 lease
->lifetime
== 0) {
1570 log_dhcp_client(client
, "received lease lacks address, server "
1571 "address or lease lifetime, ignoring");
1575 if (lease
->subnet_mask
== INADDR_ANY
) {
1576 r
= dhcp_lease_set_default_subnet_mask(lease
);
1578 log_dhcp_client(client
,
1579 "received lease lacks subnet mask, "
1580 "and a fallback one cannot be generated, ignoring");
1585 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1586 if (client
->lease
) {
1587 if (lease_equal(client
->lease
, lease
))
1588 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1590 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1592 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1595 client
->lease
= TAKE_PTR(lease
);
1597 log_dhcp_client(client
, "ACK");
1602 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1604 assert(client
->request_sent
);
1605 assert(lifetime
> 0);
1612 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1613 + (random_u32() & 0x1fffff);
1616 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1618 uint64_t lifetime_timeout
;
1619 uint64_t t2_timeout
;
1620 uint64_t t1_timeout
;
1621 char time_string
[FORMAT_TIMESPAN_MAX
];
1625 assert(client
->event
);
1626 assert(client
->lease
);
1627 assert(client
->lease
->lifetime
);
1629 /* don't set timers for infinite leases */
1630 if (client
->lease
->lifetime
== 0xffffffff) {
1631 (void) event_source_disable(client
->timeout_t1
);
1632 (void) event_source_disable(client
->timeout_t2
);
1633 (void) event_source_disable(client
->timeout_expire
);
1638 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1641 assert(client
->request_sent
<= time_now
);
1643 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1644 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1645 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1646 /* both T1 and T2 are given */
1647 if (client
->lease
->t1
< client
->lease
->t2
&&
1648 client
->lease
->t2
< client
->lease
->lifetime
) {
1649 /* they are both valid */
1650 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1651 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1654 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1655 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1656 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1657 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1659 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1660 /* only T2 is given, and it is valid */
1661 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1662 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1663 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1664 if (t2_timeout
<= t1_timeout
) {
1665 /* the computed T1 would be invalid, so discard T2 */
1666 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1667 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1669 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1670 /* only T1 is given, and it is valid */
1671 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1672 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1673 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1674 if (t2_timeout
<= t1_timeout
) {
1675 /* the computed T2 would be invalid, so discard T1 */
1676 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1677 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1680 /* fall back to the default timeouts */
1681 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1682 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1683 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1684 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1687 /* arm lifetime timeout */
1688 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1689 clock_boottime_or_monotonic(),
1690 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1691 client_timeout_expire
, client
,
1692 client
->event_priority
, "dhcp4-lifetime", true);
1696 log_dhcp_client(client
, "lease expires in %s",
1697 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1699 /* don't arm earlier timeouts if this has already expired */
1700 if (lifetime_timeout
<= time_now
)
1703 /* arm T2 timeout */
1704 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1705 clock_boottime_or_monotonic(),
1706 t2_timeout
, 10 * USEC_PER_MSEC
,
1707 client_timeout_t2
, client
,
1708 client
->event_priority
, "dhcp4-t2-timeout", true);
1712 log_dhcp_client(client
, "T2 expires in %s",
1713 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1715 /* don't arm earlier timeout if this has already expired */
1716 if (t2_timeout
<= time_now
)
1719 /* arm T1 timeout */
1720 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1721 clock_boottime_or_monotonic(),
1722 t1_timeout
, 10 * USEC_PER_MSEC
,
1723 client_timeout_t1
, client
,
1724 client
->event_priority
, "dhcp4-t1-timer", true);
1728 log_dhcp_client(client
, "T1 expires in %s",
1729 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1734 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1735 DHCP_CLIENT_DONT_DESTROY(client
);
1736 char time_string
[FORMAT_TIMESPAN_MAX
];
1737 int r
= 0, notify_event
= 0;
1740 assert(client
->event
);
1743 switch (client
->state
) {
1744 case DHCP_STATE_SELECTING
:
1746 r
= client_handle_offer(client
, message
, len
);
1749 client
->state
= DHCP_STATE_REQUESTING
;
1750 client
->attempt
= 0;
1752 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1753 clock_boottime_or_monotonic(),
1755 client_timeout_resend
, client
,
1756 client
->event_priority
, "dhcp4-resend-timer", true);
1759 } else if (r
== -ENOMSG
)
1760 /* invalid message, let's ignore it */
1765 case DHCP_STATE_REBOOTING
:
1766 case DHCP_STATE_REQUESTING
:
1767 case DHCP_STATE_RENEWING
:
1768 case DHCP_STATE_REBINDING
:
1770 r
= client_handle_ack(client
, message
, len
);
1772 client
->start_delay
= 0;
1773 (void) event_source_disable(client
->timeout_resend
);
1774 client
->receive_message
=
1775 sd_event_source_unref(client
->receive_message
);
1776 client
->fd
= asynchronous_close(client
->fd
);
1778 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1779 DHCP_STATE_REBOOTING
))
1780 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1781 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1784 client
->state
= DHCP_STATE_BOUND
;
1785 client
->attempt
= 0;
1787 client
->last_addr
= client
->lease
->address
;
1789 r
= client_set_lease_timeouts(client
);
1791 log_dhcp_client(client
, "could not set lease timeouts");
1795 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1797 log_dhcp_client(client
, "could not bind UDP socket");
1803 client_initialize_io_events(client
, client_receive_message_udp
);
1806 client_notify(client
, notify_event
);
1807 if (client
->state
== DHCP_STATE_STOPPED
)
1811 } else if (r
== -EADDRNOTAVAIL
) {
1812 /* got a NAK, let's restart the client */
1813 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1815 r
= client_initialize(client
);
1819 r
= client_start_delayed(client
);
1823 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1824 client
->start_delay
, USEC_PER_SEC
));
1826 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1827 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1830 } else if (r
== -ENOMSG
)
1831 /* invalid message, let's ignore it */
1836 case DHCP_STATE_BOUND
:
1837 r
= client_handle_forcerenew(client
, message
, len
);
1839 r
= client_timeout_t1(NULL
, 0, client
);
1842 } else if (r
== -ENOMSG
)
1843 /* invalid message, let's ignore it */
1848 case DHCP_STATE_INIT
:
1849 case DHCP_STATE_INIT_REBOOT
:
1853 case DHCP_STATE_STOPPED
:
1860 client_stop(client
, r
);
1865 static int client_receive_message_udp(
1871 sd_dhcp_client
*client
= userdata
;
1872 _cleanup_free_ DHCPMessage
*message
= NULL
;
1873 const uint8_t *expected_chaddr
= NULL
;
1874 uint8_t expected_hlen
= 0;
1875 ssize_t len
, buflen
;
1880 buflen
= next_datagram_size_fd(fd
);
1881 if (buflen
== -ENETDOWN
) {
1882 /* the link is down. Don't return an error or the I/O event
1883 source will be disconnected and we won't be able to receive
1884 packets again when the link comes back. */
1890 message
= malloc0(buflen
);
1894 len
= recv(fd
, message
, buflen
, 0);
1896 /* see comment above for why we shouldn't error out on ENETDOWN. */
1897 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1900 return log_dhcp_client_errno(client
, errno
,
1901 "Could not receive message from UDP socket: %m");
1903 if ((size_t) len
< sizeof(DHCPMessage
)) {
1904 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1908 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1909 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1913 if (message
->op
!= BOOTREPLY
) {
1914 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1918 if (message
->htype
!= client
->arp_type
) {
1919 log_dhcp_client(client
, "Packet type does not match client type");
1923 if (client
->arp_type
== ARPHRD_ETHER
) {
1924 expected_hlen
= ETH_ALEN
;
1925 expected_chaddr
= &client
->mac_addr
[0];
1928 if (message
->hlen
!= expected_hlen
) {
1929 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1933 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1934 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1938 if (client
->state
!= DHCP_STATE_BOUND
&&
1939 be32toh(message
->xid
) != client
->xid
) {
1940 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1941 so ignore the xid in this case */
1942 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1943 be32toh(message
->xid
), client
->xid
);
1947 return client_handle_message(client
, message
, len
);
1950 static int client_receive_message_raw(
1956 sd_dhcp_client
*client
= userdata
;
1957 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1958 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
;
1959 struct iovec iov
= {};
1960 struct msghdr msg
= {
1963 .msg_control
= &control
,
1964 .msg_controllen
= sizeof(control
),
1966 struct cmsghdr
*cmsg
;
1967 bool checksum
= true;
1968 ssize_t buflen
, len
;
1974 buflen
= next_datagram_size_fd(fd
);
1975 if (buflen
== -ENETDOWN
)
1980 packet
= malloc0(buflen
);
1984 iov
= IOVEC_MAKE(packet
, buflen
);
1986 len
= recvmsg_safe(fd
, &msg
, 0);
1987 if (IN_SET(len
, -EAGAIN
, -EINTR
, -ENETDOWN
))
1990 return log_dhcp_client_errno(client
, len
,
1991 "Could not receive message from raw socket: %m");
1993 if ((size_t) len
< sizeof(DHCPPacket
))
1996 cmsg
= cmsg_find(&msg
, SOL_PACKET
, PACKET_AUXDATA
, CMSG_LEN(sizeof(struct tpacket_auxdata
)));
1998 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*) CMSG_DATA(cmsg
);
1999 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2002 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
2006 len
-= DHCP_IP_UDP_SIZE
;
2008 return client_handle_message(client
, &packet
->dhcp
, len
);
2011 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2012 assert_return(client
, -EINVAL
);
2013 assert_return(client
->fd
>= 0, -EINVAL
);
2015 client
->start_delay
= 0;
2016 client
->attempt
= 1;
2017 client
->state
= DHCP_STATE_RENEWING
;
2019 return client_initialize_time_events(client
);
2022 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2025 assert_return(client
, -EINVAL
);
2027 r
= client_initialize(client
);
2031 /* RFC7844 section 3.3:
2032 SHOULD perform a complete four-way handshake, starting with a
2033 DHCPDISCOVER, to obtain a new address lease. If the client can
2034 ascertain that this is exactly the same network to which it was
2035 previously connected, and if the link-layer address did not change,
2036 the client MAY issue a DHCPREQUEST to try to reclaim the current
2038 if (client
->last_addr
&& !client
->anonymize
)
2039 client
->state
= DHCP_STATE_INIT_REBOOT
;
2041 r
= client_start(client
);
2043 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2048 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2049 assert_return(client
, -EINVAL
);
2050 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2051 assert_return(client
->lease
, -EUNATCH
);
2053 _cleanup_free_ DHCPPacket
*release
= NULL
;
2054 size_t optoffset
, optlen
;
2057 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2061 /* Fill up release IP and MAC */
2062 release
->dhcp
.ciaddr
= client
->lease
->address
;
2063 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2065 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2066 SD_DHCP_OPTION_END
, 0, NULL
);
2070 r
= dhcp_network_send_udp_socket(client
->fd
,
2071 client
->lease
->server_address
,
2074 sizeof(DHCPMessage
) + optoffset
);
2078 log_dhcp_client(client
, "RELEASE");
2083 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2084 assert_return(client
, -EINVAL
);
2085 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2086 assert_return(client
->lease
, -EUNATCH
);
2088 _cleanup_free_ DHCPPacket
*release
= NULL
;
2089 size_t optoffset
, optlen
;
2092 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2096 release
->dhcp
.ciaddr
= client
->lease
->address
;
2097 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2099 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2100 SD_DHCP_OPTION_END
, 0, NULL
);
2104 r
= dhcp_network_send_udp_socket(client
->fd
,
2105 client
->lease
->server_address
,
2108 sizeof(DHCPMessage
) + optoffset
);
2112 log_dhcp_client(client
, "DECLINE");
2114 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2116 if (client
->state
!= DHCP_STATE_STOPPED
) {
2117 r
= sd_dhcp_client_start(client
);
2125 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2126 DHCP_CLIENT_DONT_DESTROY(client
);
2128 assert_return(client
, -EINVAL
);
2130 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2131 client
->state
= DHCP_STATE_STOPPED
;
2136 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2139 assert_return(client
, -EINVAL
);
2140 assert_return(!client
->event
, -EBUSY
);
2143 client
->event
= sd_event_ref(event
);
2145 r
= sd_event_default(&client
->event
);
2150 client
->event_priority
= priority
;
2155 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2156 assert_return(client
, -EINVAL
);
2158 client
->event
= sd_event_unref(client
->event
);
2163 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2164 assert_return(client
, NULL
);
2166 return client
->event
;
2169 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2173 log_dhcp_client(client
, "FREE");
2175 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2176 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2177 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2178 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2180 client_initialize(client
);
2182 sd_dhcp_client_detach_event(client
);
2184 sd_dhcp_lease_unref(client
->lease
);
2186 free(client
->req_opts
);
2187 free(client
->hostname
);
2188 free(client
->vendor_class_identifier
);
2189 free(client
->mudurl
);
2190 client
->user_class
= strv_free(client
->user_class
);
2191 ordered_hashmap_free(client
->extra_options
);
2192 ordered_hashmap_free(client
->vendor_options
);
2193 return mfree(client
);
2196 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2198 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2199 assert_return(ret
, -EINVAL
);
2201 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2205 *client
= (sd_dhcp_client
) {
2207 .state
= DHCP_STATE_INIT
,
2210 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2211 .port
= DHCP_PORT_CLIENT
,
2212 .anonymize
= !!anonymize
,
2213 .max_attempts
= (uint64_t) -1,
2214 .ip_service_type
= -1,
2216 /* NOTE: this could be moved to a function. */
2218 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2219 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2221 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2222 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2224 if (!client
->req_opts
)
2227 *ret
= TAKE_PTR(client
);