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 * the 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
);
1445 client
->state
= DHCP_STATE_RENEWING
;
1446 else if (client
->state
!= DHCP_STATE_INIT
)
1447 client
->state
= DHCP_STATE_INIT_REBOOT
;
1448 client
->attempt
= 0;
1450 return client_initialize_time_events(client
);
1453 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1454 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1457 r
= dhcp_lease_new(&lease
);
1461 if (client
->client_id_len
) {
1462 r
= dhcp_lease_set_client_id(lease
,
1463 (uint8_t *) &client
->client_id
,
1464 client
->client_id_len
);
1469 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1470 if (r
!= DHCP_OFFER
) {
1471 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1475 lease
->next_server
= offer
->siaddr
;
1476 lease
->address
= offer
->yiaddr
;
1478 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1479 lease
->lifetime
= client
->fallback_lease_lifetime
;
1481 if (lease
->address
== 0 ||
1482 lease
->server_address
== 0 ||
1483 lease
->lifetime
== 0) {
1484 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1488 if (!lease
->have_subnet_mask
) {
1489 r
= dhcp_lease_set_default_subnet_mask(lease
);
1491 log_dhcp_client(client
,
1492 "received lease lacks subnet mask, "
1493 "and a fallback one cannot be generated, ignoring");
1498 sd_dhcp_lease_unref(client
->lease
);
1499 client
->lease
= TAKE_PTR(lease
);
1501 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1504 log_dhcp_client(client
, "OFFER");
1509 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1512 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1513 if (r
!= DHCP_FORCERENEW
)
1516 log_dhcp_client(client
, "FORCERENEW");
1521 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1522 if (a
->address
!= b
->address
)
1525 if (a
->subnet_mask
!= b
->subnet_mask
)
1528 if (a
->router_size
!= b
->router_size
)
1531 for (size_t i
= 0; i
< a
->router_size
; i
++)
1532 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1538 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1539 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1540 _cleanup_free_
char *error_message
= NULL
;
1543 r
= dhcp_lease_new(&lease
);
1547 if (client
->client_id_len
) {
1548 r
= dhcp_lease_set_client_id(lease
,
1549 (uint8_t *) &client
->client_id
,
1550 client
->client_id_len
);
1555 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1556 if (r
== DHCP_NAK
) {
1557 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1558 return -EADDRNOTAVAIL
;
1561 if (r
!= DHCP_ACK
) {
1562 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1566 lease
->next_server
= ack
->siaddr
;
1568 lease
->address
= ack
->yiaddr
;
1570 if (lease
->address
== INADDR_ANY
||
1571 lease
->server_address
== INADDR_ANY
||
1572 lease
->lifetime
== 0) {
1573 log_dhcp_client(client
, "received lease lacks address, server "
1574 "address or lease lifetime, ignoring");
1578 if (lease
->subnet_mask
== INADDR_ANY
) {
1579 r
= dhcp_lease_set_default_subnet_mask(lease
);
1581 log_dhcp_client(client
,
1582 "received lease lacks subnet mask, "
1583 "and a fallback one cannot be generated, ignoring");
1588 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1589 if (client
->lease
) {
1590 if (lease_equal(client
->lease
, lease
))
1591 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1593 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1595 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1598 client
->lease
= TAKE_PTR(lease
);
1600 log_dhcp_client(client
, "ACK");
1605 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1607 assert(client
->request_sent
);
1608 assert(lifetime
> 0);
1615 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1616 + (random_u32() & 0x1fffff);
1619 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1621 uint64_t lifetime_timeout
;
1622 uint64_t t2_timeout
;
1623 uint64_t t1_timeout
;
1624 char time_string
[FORMAT_TIMESPAN_MAX
];
1628 assert(client
->event
);
1629 assert(client
->lease
);
1630 assert(client
->lease
->lifetime
);
1632 /* don't set timers for infinite leases */
1633 if (client
->lease
->lifetime
== 0xffffffff) {
1634 (void) event_source_disable(client
->timeout_t1
);
1635 (void) event_source_disable(client
->timeout_t2
);
1636 (void) event_source_disable(client
->timeout_expire
);
1641 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1644 assert(client
->request_sent
<= time_now
);
1646 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1647 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1648 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1649 /* both T1 and T2 are given */
1650 if (client
->lease
->t1
< client
->lease
->t2
&&
1651 client
->lease
->t2
< client
->lease
->lifetime
) {
1652 /* they are both valid */
1653 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1654 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1657 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1658 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1659 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1660 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1662 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1663 /* only T2 is given, and it is valid */
1664 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1665 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1666 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1667 if (t2_timeout
<= t1_timeout
) {
1668 /* the computed T1 would be invalid, so discard T2 */
1669 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1670 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1672 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1673 /* only T1 is given, and it is valid */
1674 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1675 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1676 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1677 if (t2_timeout
<= t1_timeout
) {
1678 /* the computed T2 would be invalid, so discard T1 */
1679 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1680 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1683 /* fall back to the default timeouts */
1684 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1685 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1686 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1687 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1690 /* arm lifetime timeout */
1691 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1692 clock_boottime_or_monotonic(),
1693 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1694 client_timeout_expire
, client
,
1695 client
->event_priority
, "dhcp4-lifetime", true);
1699 log_dhcp_client(client
, "lease expires in %s",
1700 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1702 /* don't arm earlier timeouts if this has already expired */
1703 if (lifetime_timeout
<= time_now
)
1706 /* arm T2 timeout */
1707 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1708 clock_boottime_or_monotonic(),
1709 t2_timeout
, 10 * USEC_PER_MSEC
,
1710 client_timeout_t2
, client
,
1711 client
->event_priority
, "dhcp4-t2-timeout", true);
1715 log_dhcp_client(client
, "T2 expires in %s",
1716 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1718 /* don't arm earlier timeout if this has already expired */
1719 if (t2_timeout
<= time_now
)
1722 /* arm T1 timeout */
1723 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1724 clock_boottime_or_monotonic(),
1725 t1_timeout
, 10 * USEC_PER_MSEC
,
1726 client_timeout_t1
, client
,
1727 client
->event_priority
, "dhcp4-t1-timer", true);
1731 log_dhcp_client(client
, "T1 expires in %s",
1732 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1737 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1738 DHCP_CLIENT_DONT_DESTROY(client
);
1739 char time_string
[FORMAT_TIMESPAN_MAX
];
1740 int r
= 0, notify_event
= 0;
1743 assert(client
->event
);
1746 switch (client
->state
) {
1747 case DHCP_STATE_SELECTING
:
1749 r
= client_handle_offer(client
, message
, len
);
1752 client
->state
= DHCP_STATE_REQUESTING
;
1753 client
->attempt
= 0;
1755 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1756 clock_boottime_or_monotonic(),
1758 client_timeout_resend
, client
,
1759 client
->event_priority
, "dhcp4-resend-timer", true);
1762 } else if (r
== -ENOMSG
)
1763 /* invalid message, let's ignore it */
1768 case DHCP_STATE_REBOOTING
:
1769 case DHCP_STATE_REQUESTING
:
1770 case DHCP_STATE_RENEWING
:
1771 case DHCP_STATE_REBINDING
:
1773 r
= client_handle_ack(client
, message
, len
);
1775 client
->start_delay
= 0;
1776 (void) event_source_disable(client
->timeout_resend
);
1777 client
->receive_message
=
1778 sd_event_source_unref(client
->receive_message
);
1779 client
->fd
= asynchronous_close(client
->fd
);
1781 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1782 DHCP_STATE_REBOOTING
))
1783 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1784 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1787 client
->state
= DHCP_STATE_BOUND
;
1788 client
->attempt
= 0;
1790 client
->last_addr
= client
->lease
->address
;
1792 r
= client_set_lease_timeouts(client
);
1794 log_dhcp_client(client
, "could not set lease timeouts");
1798 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1800 log_dhcp_client(client
, "could not bind UDP socket");
1806 client_initialize_io_events(client
, client_receive_message_udp
);
1809 client_notify(client
, notify_event
);
1810 if (client
->state
== DHCP_STATE_STOPPED
)
1814 } else if (r
== -EADDRNOTAVAIL
) {
1815 /* got a NAK, let's restart the client */
1816 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1818 r
= client_initialize(client
);
1822 r
= client_start_delayed(client
);
1826 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1827 client
->start_delay
, USEC_PER_SEC
));
1829 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1830 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1833 } else if (r
== -ENOMSG
)
1834 /* invalid message, let's ignore it */
1839 case DHCP_STATE_BOUND
:
1840 r
= client_handle_forcerenew(client
, message
, len
);
1842 r
= client_timeout_t1(NULL
, 0, client
);
1845 } else if (r
== -ENOMSG
)
1846 /* invalid message, let's ignore it */
1851 case DHCP_STATE_INIT
:
1852 case DHCP_STATE_INIT_REBOOT
:
1856 case DHCP_STATE_STOPPED
:
1863 client_stop(client
, r
);
1868 static int client_receive_message_udp(
1874 sd_dhcp_client
*client
= userdata
;
1875 _cleanup_free_ DHCPMessage
*message
= NULL
;
1876 const uint8_t *expected_chaddr
= NULL
;
1877 uint8_t expected_hlen
= 0;
1878 ssize_t len
, buflen
;
1883 buflen
= next_datagram_size_fd(fd
);
1884 if (buflen
== -ENETDOWN
) {
1885 /* the link is down. Don't return an error or the I/O event
1886 source will be disconnected and we won't be able to receive
1887 packets again when the link comes back. */
1893 message
= malloc0(buflen
);
1897 len
= recv(fd
, message
, buflen
, 0);
1899 /* see comment above for why we shouldn't error out on ENETDOWN. */
1900 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1903 return log_dhcp_client_errno(client
, errno
,
1904 "Could not receive message from UDP socket: %m");
1906 if ((size_t) len
< sizeof(DHCPMessage
)) {
1907 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1911 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1912 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1916 if (message
->op
!= BOOTREPLY
) {
1917 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1921 if (message
->htype
!= client
->arp_type
) {
1922 log_dhcp_client(client
, "Packet type does not match client type");
1926 if (client
->arp_type
== ARPHRD_ETHER
) {
1927 expected_hlen
= ETH_ALEN
;
1928 expected_chaddr
= &client
->mac_addr
[0];
1931 if (message
->hlen
!= expected_hlen
) {
1932 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1936 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1937 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1941 if (client
->state
!= DHCP_STATE_BOUND
&&
1942 be32toh(message
->xid
) != client
->xid
) {
1943 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1944 so ignore the xid in this case */
1945 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1946 be32toh(message
->xid
), client
->xid
);
1950 return client_handle_message(client
, message
, len
);
1953 static int client_receive_message_raw(
1959 sd_dhcp_client
*client
= userdata
;
1960 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1961 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
;
1962 struct iovec iov
= {};
1963 struct msghdr msg
= {
1966 .msg_control
= &control
,
1967 .msg_controllen
= sizeof(control
),
1969 struct cmsghdr
*cmsg
;
1970 bool checksum
= true;
1971 ssize_t buflen
, len
;
1977 buflen
= next_datagram_size_fd(fd
);
1978 if (buflen
== -ENETDOWN
)
1983 packet
= malloc0(buflen
);
1987 iov
= IOVEC_MAKE(packet
, buflen
);
1989 len
= recvmsg_safe(fd
, &msg
, 0);
1990 if (IN_SET(len
, -EAGAIN
, -EINTR
, -ENETDOWN
))
1993 return log_dhcp_client_errno(client
, len
,
1994 "Could not receive message from raw socket: %m");
1996 if ((size_t) len
< sizeof(DHCPPacket
))
1999 cmsg
= cmsg_find(&msg
, SOL_PACKET
, PACKET_AUXDATA
, CMSG_LEN(sizeof(struct tpacket_auxdata
)));
2001 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*) CMSG_DATA(cmsg
);
2002 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2005 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
2009 len
-= DHCP_IP_UDP_SIZE
;
2011 return client_handle_message(client
, &packet
->dhcp
, len
);
2014 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2015 assert_return(client
, -EINVAL
);
2016 assert_return(client
->fd
>= 0, -EINVAL
);
2021 client
->start_delay
= 0;
2022 client
->attempt
= 1;
2023 client
->state
= DHCP_STATE_RENEWING
;
2025 return client_initialize_time_events(client
);
2028 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2031 assert_return(client
, -EINVAL
);
2033 r
= client_initialize(client
);
2037 /* RFC7844 section 3.3:
2038 SHOULD perform a complete four-way handshake, starting with a
2039 DHCPDISCOVER, to obtain a new address lease. If the client can
2040 ascertain that this is exactly the same network to which it was
2041 previously connected, and if the link-layer address did not change,
2042 the client MAY issue a DHCPREQUEST to try to reclaim the current
2044 if (client
->last_addr
&& !client
->anonymize
)
2045 client
->state
= DHCP_STATE_INIT_REBOOT
;
2047 r
= client_start(client
);
2049 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2054 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2055 assert_return(client
, -EINVAL
);
2056 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2057 assert_return(client
->lease
, -EUNATCH
);
2059 _cleanup_free_ DHCPPacket
*release
= NULL
;
2060 size_t optoffset
, optlen
;
2063 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2067 /* Fill up release IP and MAC */
2068 release
->dhcp
.ciaddr
= client
->lease
->address
;
2069 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2071 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2072 SD_DHCP_OPTION_END
, 0, NULL
);
2076 r
= dhcp_network_send_udp_socket(client
->fd
,
2077 client
->lease
->server_address
,
2080 sizeof(DHCPMessage
) + optoffset
);
2084 log_dhcp_client(client
, "RELEASE");
2089 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2090 assert_return(client
, -EINVAL
);
2091 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2092 assert_return(client
->lease
, -EUNATCH
);
2094 _cleanup_free_ DHCPPacket
*release
= NULL
;
2095 size_t optoffset
, optlen
;
2098 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2102 release
->dhcp
.ciaddr
= client
->lease
->address
;
2103 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2105 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2106 SD_DHCP_OPTION_END
, 0, NULL
);
2110 r
= dhcp_network_send_udp_socket(client
->fd
,
2111 client
->lease
->server_address
,
2114 sizeof(DHCPMessage
) + optoffset
);
2118 log_dhcp_client(client
, "DECLINE");
2120 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2122 if (client
->state
!= DHCP_STATE_STOPPED
) {
2123 r
= sd_dhcp_client_start(client
);
2131 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2132 DHCP_CLIENT_DONT_DESTROY(client
);
2134 assert_return(client
, -EINVAL
);
2136 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2137 client
->state
= DHCP_STATE_STOPPED
;
2142 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2145 assert_return(client
, -EINVAL
);
2146 assert_return(!client
->event
, -EBUSY
);
2149 client
->event
= sd_event_ref(event
);
2151 r
= sd_event_default(&client
->event
);
2156 client
->event_priority
= priority
;
2161 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2162 assert_return(client
, -EINVAL
);
2164 client
->event
= sd_event_unref(client
->event
);
2169 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2170 assert_return(client
, NULL
);
2172 return client
->event
;
2175 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2179 log_dhcp_client(client
, "FREE");
2181 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2182 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2183 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2184 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2186 client_initialize(client
);
2188 sd_dhcp_client_detach_event(client
);
2190 sd_dhcp_lease_unref(client
->lease
);
2192 free(client
->req_opts
);
2193 free(client
->hostname
);
2194 free(client
->vendor_class_identifier
);
2195 free(client
->mudurl
);
2196 client
->user_class
= strv_free(client
->user_class
);
2197 ordered_hashmap_free(client
->extra_options
);
2198 ordered_hashmap_free(client
->vendor_options
);
2199 return mfree(client
);
2202 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2204 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2205 assert_return(ret
, -EINVAL
);
2207 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2211 *client
= (sd_dhcp_client
) {
2213 .state
= DHCP_STATE_INIT
,
2216 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2217 .port
= DHCP_PORT_CLIENT
,
2218 .anonymize
= !!anonymize
,
2219 .max_attempts
= (uint64_t) -1,
2220 .ip_service_type
= -1,
2222 /* NOTE: this could be moved to a function. */
2224 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2225 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2227 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2228 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2230 if (!client
->req_opts
)
2233 *ret
= TAKE_PTR(client
);