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"
31 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
32 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
34 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
35 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
37 struct sd_dhcp_client
{
43 sd_event_source
*timeout_resend
;
47 union sockaddr_union link
;
48 sd_event_source
*receive_message
;
49 bool request_broadcast
;
51 size_t req_opts_allocated
;
55 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
62 /* 0: Generic (non-LL) (RFC 2132) */
63 uint8_t data
[MAX_CLIENT_ID_LEN
];
66 /* 1: Ethernet Link-Layer (RFC 2132) */
67 uint8_t haddr
[ETH_ALEN
];
70 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
74 /* 255: Node-specific (RFC 4361) */
79 uint8_t data
[MAX_CLIENT_ID_LEN
];
85 char *vendor_class_identifier
;
91 uint64_t max_attempts
;
92 OrderedHashmap
*extra_options
;
93 OrderedHashmap
*vendor_options
;
95 sd_event_source
*timeout_t1
;
96 sd_event_source
*timeout_t2
;
97 sd_event_source
*timeout_expire
;
98 sd_dhcp_client_callback_t callback
;
100 sd_dhcp_lease
*lease
;
105 static const uint8_t default_req_opts
[] = {
106 SD_DHCP_OPTION_SUBNET_MASK
,
107 SD_DHCP_OPTION_ROUTER
,
108 SD_DHCP_OPTION_HOST_NAME
,
109 SD_DHCP_OPTION_DOMAIN_NAME
,
110 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
113 /* RFC7844 section 3:
114 MAY contain the Parameter Request List option.
116 The client intending to protect its privacy SHOULD only request a
117 minimal number of options in the PRL and SHOULD also randomly shuffle
118 the ordering of option codes in the PRL. If this random ordering
119 cannot be implemented, the client MAY order the option codes in the
120 PRL by option code number (lowest to highest).
122 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
123 static const uint8_t default_req_opts_anonymize
[] = {
124 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
125 SD_DHCP_OPTION_ROUTER
, /* 3 */
126 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
127 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
128 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
129 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
130 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
131 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
132 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
133 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
134 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
135 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
136 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
139 static int client_receive_message_raw(
144 static int client_receive_message_udp(
149 static void client_stop(sd_dhcp_client
*client
, int error
);
151 int sd_dhcp_client_set_callback(
152 sd_dhcp_client
*client
,
153 sd_dhcp_client_callback_t cb
,
156 assert_return(client
, -EINVAL
);
158 client
->callback
= cb
;
159 client
->userdata
= userdata
;
164 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
165 assert_return(client
, -EINVAL
);
167 client
->request_broadcast
= !!broadcast
;
172 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
175 assert_return(client
, -EINVAL
);
176 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
180 case SD_DHCP_OPTION_PAD
:
181 case SD_DHCP_OPTION_OVERLOAD
:
182 case SD_DHCP_OPTION_MESSAGE_TYPE
:
183 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
184 case SD_DHCP_OPTION_END
:
191 for (i
= 0; i
< client
->req_opts_size
; i
++)
192 if (client
->req_opts
[i
] == option
)
195 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
196 client
->req_opts_size
+ 1))
199 client
->req_opts
[client
->req_opts_size
++] = option
;
204 int sd_dhcp_client_set_request_address(
205 sd_dhcp_client
*client
,
206 const struct in_addr
*last_addr
) {
208 assert_return(client
, -EINVAL
);
209 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
212 client
->last_addr
= last_addr
->s_addr
;
214 client
->last_addr
= INADDR_ANY
;
219 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
221 assert_return(client
, -EINVAL
);
222 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
223 assert_return(ifindex
> 0, -EINVAL
);
225 client
->ifindex
= ifindex
;
229 int sd_dhcp_client_set_mac(
230 sd_dhcp_client
*client
,
235 DHCP_CLIENT_DONT_DESTROY(client
);
236 bool need_restart
= false;
239 assert_return(client
, -EINVAL
);
240 assert_return(addr
, -EINVAL
);
241 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
242 assert_return(arp_type
> 0, -EINVAL
);
244 if (arp_type
== ARPHRD_ETHER
)
245 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
246 else if (arp_type
== ARPHRD_INFINIBAND
)
247 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
251 if (client
->mac_addr_len
== addr_len
&&
252 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
255 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
256 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
258 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
261 memcpy(&client
->mac_addr
, addr
, addr_len
);
262 client
->mac_addr_len
= addr_len
;
263 client
->arp_type
= arp_type
;
265 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
266 r
= sd_dhcp_client_start(client
);
268 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
274 int sd_dhcp_client_get_client_id(
275 sd_dhcp_client
*client
,
277 const uint8_t **data
,
280 assert_return(client
, -EINVAL
);
281 assert_return(type
, -EINVAL
);
282 assert_return(data
, -EINVAL
);
283 assert_return(data_len
, -EINVAL
);
288 if (client
->client_id_len
) {
289 *type
= client
->client_id
.type
;
290 *data
= client
->client_id
.raw
.data
;
291 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
297 int sd_dhcp_client_set_client_id(
298 sd_dhcp_client
*client
,
303 DHCP_CLIENT_DONT_DESTROY(client
);
304 bool need_restart
= false;
307 assert_return(client
, -EINVAL
);
308 assert_return(data
, -EINVAL
);
309 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
311 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
312 client
->client_id
.type
== type
&&
313 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
316 /* For hardware types, log debug message about unexpected data length.
318 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
319 * last last 8 bytes of the address are stable and suitable to put into
320 * the client-id. The caller is advised to account for that. */
321 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
322 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
323 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
324 "unexpected address length %zu",
327 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
328 log_dhcp_client(client
, "Changing client ID on running DHCP "
329 "client, restarting");
331 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
334 client
->client_id
.type
= type
;
335 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
336 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
338 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
339 r
= sd_dhcp_client_start(client
);
341 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
348 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
349 * without further modification. Otherwise, if duid_type is supported, DUID
350 * is set based on that type. Otherwise, an error is returned.
352 static int dhcp_client_set_iaid_duid_internal(
353 sd_dhcp_client
*client
,
362 DHCP_CLIENT_DONT_DESTROY(client
);
366 assert_return(client
, -EINVAL
);
367 assert_return(duid_len
== 0 || duid
, -EINVAL
);
370 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
372 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
375 zero(client
->client_id
);
376 client
->client_id
.type
= 255;
380 client
->client_id
.ns
.iaid
= htobe32(iaid
);
382 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
383 client
->mac_addr_len
,
385 &client
->client_id
.ns
.iaid
);
387 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
392 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
393 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
394 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
398 if (client
->mac_addr_len
== 0)
399 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
401 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
403 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
406 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
408 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
411 if (client
->mac_addr_len
== 0)
412 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
414 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
416 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
419 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
421 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
424 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
427 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
428 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
430 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
431 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
432 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
433 r
= sd_dhcp_client_start(client
);
435 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
441 int sd_dhcp_client_set_iaid_duid(
442 sd_dhcp_client
*client
,
448 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
451 int sd_dhcp_client_set_iaid_duid_llt(
452 sd_dhcp_client
*client
,
456 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
459 int sd_dhcp_client_set_duid(
460 sd_dhcp_client
*client
,
464 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
467 int sd_dhcp_client_set_duid_llt(
468 sd_dhcp_client
*client
,
470 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
473 int sd_dhcp_client_set_hostname(
474 sd_dhcp_client
*client
,
475 const char *hostname
) {
477 assert_return(client
, -EINVAL
);
479 /* Make sure hostnames qualify as DNS and as Linux hostnames */
481 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
484 return free_and_strdup(&client
->hostname
, hostname
);
487 int sd_dhcp_client_set_vendor_class_identifier(
488 sd_dhcp_client
*client
,
491 assert_return(client
, -EINVAL
);
493 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
496 int sd_dhcp_client_set_user_class(
497 sd_dhcp_client
*client
,
498 const char* const* user_class
) {
500 _cleanup_strv_free_
char **s
= NULL
;
503 STRV_FOREACH(p
, (char **) user_class
)
504 if (strlen(*p
) > 255)
505 return -ENAMETOOLONG
;
507 s
= strv_copy((char **) user_class
);
511 client
->user_class
= TAKE_PTR(s
);
516 int sd_dhcp_client_set_client_port(
517 sd_dhcp_client
*client
,
520 assert_return(client
, -EINVAL
);
527 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
528 assert_return(client
, -EINVAL
);
529 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
536 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
537 assert_return(client
, -EINVAL
);
539 client
->max_attempts
= max_attempts
;
544 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
547 assert_return(client
, -EINVAL
);
548 assert_return(v
, -EINVAL
);
550 r
= ordered_hashmap_ensure_allocated(&client
->extra_options
, &dhcp_option_hash_ops
);
554 r
= ordered_hashmap_put(client
->extra_options
, UINT_TO_PTR(v
->option
), v
);
558 sd_dhcp_option_ref(v
);
562 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
565 assert_return(client
, -EINVAL
);
566 assert_return(v
, -EINVAL
);
568 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
572 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
576 sd_dhcp_option_ref(v
);
581 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
582 assert_return(client
, -EINVAL
);
584 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
585 return -EADDRNOTAVAIL
;
588 *ret
= client
->lease
;
593 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
594 assert_return(client
, -EINVAL
);
596 client
->ip_service_type
= type
;
601 static int client_notify(sd_dhcp_client
*client
, int event
) {
604 if (client
->callback
)
605 return client
->callback(client
, event
, client
->userdata
);
610 static int client_initialize(sd_dhcp_client
*client
) {
611 assert_return(client
, -EINVAL
);
613 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
615 client
->fd
= asynchronous_close(client
->fd
);
617 (void) event_source_disable(client
->timeout_resend
);
618 (void) event_source_disable(client
->timeout_t1
);
619 (void) event_source_disable(client
->timeout_t2
);
620 (void) event_source_disable(client
->timeout_expire
);
624 client
->state
= DHCP_STATE_INIT
;
627 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
632 static void client_stop(sd_dhcp_client
*client
, int error
) {
636 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
637 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
638 log_dhcp_client(client
, "STOPPED");
640 log_dhcp_client(client
, "STOPPED: Unknown event");
642 client_notify(client
, error
);
644 client_initialize(client
);
647 static int client_message_init(
648 sd_dhcp_client
*client
,
652 size_t *_optoffset
) {
654 _cleanup_free_ DHCPPacket
*packet
= NULL
;
655 size_t optlen
, optoffset
, size
;
662 assert(client
->start_time
);
666 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
668 optlen
= DHCP_MIN_OPTIONS_SIZE
;
669 size
= sizeof(DHCPPacket
) + optlen
;
671 packet
= malloc0(size
);
675 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
676 client
->arp_type
, optlen
, &optoffset
);
680 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
681 refuse to issue an DHCP lease if 'secs' is set to zero */
682 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
685 assert(time_now
>= client
->start_time
);
687 /* seconds between sending first and last DISCOVER
688 * must always be strictly positive to deal with broken servers */
689 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
690 packet
->dhcp
.secs
= htobe16(secs
);
692 /* RFC2132 section 4.1
693 A client that cannot receive unicast IP datagrams until its protocol
694 software has been configured with an IP address SHOULD set the
695 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
696 DHCPREQUEST messages that client sends. The BROADCAST bit will
697 provide a hint to the DHCP server and BOOTP relay agent to broadcast
698 any messages to the client on the client's subnet.
700 Note: some interfaces needs this to be enabled, but some networks
701 needs this to be disabled as broadcasts are filteretd, so this
702 needs to be configurable */
703 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
704 packet
->dhcp
.flags
= htobe16(0x8000);
706 /* RFC2132 section 4.1.1:
707 The client MUST include its hardware address in the ’chaddr’ field, if
708 necessary for delivery of DHCP reply messages. Non-Ethernet
709 interfaces will leave 'chaddr' empty and use the client identifier
710 instead (eg, RFC 4390 section 2.1).
712 if (client
->arp_type
== ARPHRD_ETHER
)
713 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
715 /* If no client identifier exists, construct an RFC 4361-compliant one */
716 if (client
->client_id_len
== 0) {
719 client
->client_id
.type
= 255;
721 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
722 true, &client
->client_id
.ns
.iaid
);
726 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
730 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
733 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
734 Identifier option is not set */
735 if (client
->client_id_len
) {
736 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
737 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
738 client
->client_id_len
,
744 /* RFC2131 section 3.5:
745 in its initial DHCPDISCOVER or DHCPREQUEST message, a
746 client may provide the server with a list of specific
747 parameters the client is interested in. If the client
748 includes a list of parameters in a DHCPDISCOVER message,
749 it MUST include that list in any subsequent DHCPREQUEST
753 /* RFC7844 section 3:
754 MAY contain the Parameter Request List option. */
755 /* NOTE: in case that there would be an option to do not send
756 * any PRL at all, the size should be checked before sending */
757 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
758 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
759 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
760 client
->req_opts_size
, client
->req_opts
);
765 /* RFC2131 section 3.5:
766 The client SHOULD include the ’maximum DHCP message size’ option to
767 let the server know how large the server may make its DHCP messages.
769 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
770 than the defined default size unless the Maximum Message Size option
773 RFC3442 "Requirements to Avoid Sizing Constraints":
774 Because a full routing table can be quite large, the standard 576
775 octet maximum size for a DHCP message may be too short to contain
776 some legitimate Classless Static Route options. Because of this,
777 clients implementing the Classless Static Route option SHOULD send a
778 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
779 stack is capable of receiving larger IP datagrams. In this case, the
780 client SHOULD set the value of this option to at least the MTU of the
781 interface that the client is configuring. The client MAY set the
782 value of this option higher, up to the size of the largest UDP packet
783 it is prepared to accept. (Note that the value specified in the
784 Maximum DHCP Message Size option is the total maximum packet size,
785 including IP and UDP headers.)
787 /* RFC7844 section 3:
788 SHOULD NOT contain any other option. */
789 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
790 max_size
= htobe16(size
);
791 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
792 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
799 *_optoffset
= optoffset
;
800 *ret
= TAKE_PTR(packet
);
805 static int client_append_fqdn_option(
806 DHCPMessage
*message
,
811 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
814 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
815 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
816 buffer
[1] = 0; /* RCODE1 (deprecated) */
817 buffer
[2] = 0; /* RCODE2 (deprecated) */
819 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
821 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
822 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
827 static int dhcp_client_send_raw(
828 sd_dhcp_client
*client
,
832 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
833 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
835 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
839 static int client_send_discover(sd_dhcp_client
*client
) {
840 _cleanup_free_ DHCPPacket
*discover
= NULL
;
841 size_t optoffset
, optlen
;
847 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
849 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
850 &optlen
, &optoffset
);
854 /* the client may suggest values for the network address
855 and lease time in the DHCPDISCOVER message. The client may include
856 the ’requested IP address’ option to suggest that a particular IP
857 address be assigned, and may include the ’IP address lease time’
858 option to suggest the lease time it would like.
860 /* RFC7844 section 3:
861 SHOULD NOT contain any other option. */
862 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
863 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
864 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
865 4, &client
->last_addr
);
870 if (client
->hostname
) {
871 /* According to RFC 4702 "clients that send the Client FQDN option in
872 their messages MUST NOT also send the Host Name option". Just send
873 one of the two depending on the hostname type.
875 if (dns_name_is_single_label(client
->hostname
)) {
876 /* it is unclear from RFC 2131 if client should send hostname in
877 DHCPDISCOVER but dhclient does and so we do as well
879 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
880 SD_DHCP_OPTION_HOST_NAME
,
881 strlen(client
->hostname
), client
->hostname
);
883 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
889 if (client
->vendor_class_identifier
) {
890 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
891 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
892 strlen(client
->vendor_class_identifier
),
893 client
->vendor_class_identifier
);
898 if (client
->user_class
) {
899 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
900 SD_DHCP_OPTION_USER_CLASS
,
901 strv_length(client
->user_class
),
907 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
, i
) {
908 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
909 j
->option
, j
->length
, j
->data
);
914 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
915 r
= dhcp_option_append(
916 &discover
->dhcp
, optlen
, &optoffset
, 0,
917 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
918 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
923 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
924 SD_DHCP_OPTION_END
, 0, NULL
);
928 /* We currently ignore:
929 The client SHOULD wait a random time between one and ten seconds to
930 desynchronize the use of DHCP at startup.
932 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
936 log_dhcp_client(client
, "DISCOVER");
941 static int client_send_request(sd_dhcp_client
*client
) {
942 _cleanup_free_ DHCPPacket
*request
= NULL
;
943 size_t optoffset
, optlen
;
948 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
952 switch (client
->state
) {
953 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
954 SELECTING should be REQUESTING)
957 case DHCP_STATE_REQUESTING
:
958 /* Client inserts the address of the selected server in ’server
959 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
960 filled in with the yiaddr value from the chosen DHCPOFFER.
963 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
964 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
965 4, &client
->lease
->server_address
);
969 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
970 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
971 4, &client
->lease
->address
);
977 case DHCP_STATE_INIT_REBOOT
:
978 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
979 option MUST be filled in with client’s notion of its previously
980 assigned address. ’ciaddr’ MUST be zero.
982 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
983 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
984 4, &client
->last_addr
);
989 case DHCP_STATE_RENEWING
:
990 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
991 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
995 case DHCP_STATE_REBINDING
:
996 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
997 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1000 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1002 request
->dhcp
.ciaddr
= client
->lease
->address
;
1006 case DHCP_STATE_INIT
:
1007 case DHCP_STATE_SELECTING
:
1008 case DHCP_STATE_REBOOTING
:
1009 case DHCP_STATE_BOUND
:
1010 case DHCP_STATE_STOPPED
:
1014 if (client
->hostname
) {
1015 if (dns_name_is_single_label(client
->hostname
))
1016 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1017 SD_DHCP_OPTION_HOST_NAME
,
1018 strlen(client
->hostname
), client
->hostname
);
1020 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
1026 if (client
->vendor_class_identifier
) {
1027 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1028 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1029 strlen(client
->vendor_class_identifier
),
1030 client
->vendor_class_identifier
);
1035 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1036 SD_DHCP_OPTION_END
, 0, NULL
);
1040 if (client
->state
== DHCP_STATE_RENEWING
)
1041 r
= dhcp_network_send_udp_socket(client
->fd
,
1042 client
->lease
->server_address
,
1045 sizeof(DHCPMessage
) + optoffset
);
1047 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1051 switch (client
->state
) {
1053 case DHCP_STATE_REQUESTING
:
1054 log_dhcp_client(client
, "REQUEST (requesting)");
1057 case DHCP_STATE_INIT_REBOOT
:
1058 log_dhcp_client(client
, "REQUEST (init-reboot)");
1061 case DHCP_STATE_RENEWING
:
1062 log_dhcp_client(client
, "REQUEST (renewing)");
1065 case DHCP_STATE_REBINDING
:
1066 log_dhcp_client(client
, "REQUEST (rebinding)");
1070 log_dhcp_client(client
, "REQUEST (invalid)");
1077 static int client_start(sd_dhcp_client
*client
);
1079 static int client_timeout_resend(
1084 sd_dhcp_client
*client
= userdata
;
1085 DHCP_CLIENT_DONT_DESTROY(client
);
1086 usec_t next_timeout
= 0;
1093 assert(client
->event
);
1095 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1099 switch (client
->state
) {
1101 case DHCP_STATE_RENEWING
:
1103 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1107 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1111 case DHCP_STATE_REBINDING
:
1113 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1117 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1120 case DHCP_STATE_REBOOTING
:
1121 /* start over as we did not receive a timely ack or nak */
1122 r
= client_initialize(client
);
1126 r
= client_start(client
);
1130 log_dhcp_client(client
, "REBOOTED");
1134 case DHCP_STATE_INIT
:
1135 case DHCP_STATE_INIT_REBOOT
:
1136 case DHCP_STATE_SELECTING
:
1137 case DHCP_STATE_REQUESTING
:
1138 case DHCP_STATE_BOUND
:
1140 if (client
->attempt
< client
->max_attempts
)
1145 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1149 case DHCP_STATE_STOPPED
:
1154 next_timeout
+= (random_u32() & 0x1fffff);
1156 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1157 clock_boottime_or_monotonic(),
1158 next_timeout
, 10 * USEC_PER_MSEC
,
1159 client_timeout_resend
, client
,
1160 client
->event_priority
, "dhcp4-resend-timer", true);
1164 switch (client
->state
) {
1165 case DHCP_STATE_INIT
:
1166 r
= client_send_discover(client
);
1168 client
->state
= DHCP_STATE_SELECTING
;
1169 client
->attempt
= 0;
1170 } else if (client
->attempt
>= client
->max_attempts
)
1175 case DHCP_STATE_SELECTING
:
1176 r
= client_send_discover(client
);
1177 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1182 case DHCP_STATE_INIT_REBOOT
:
1183 case DHCP_STATE_REQUESTING
:
1184 case DHCP_STATE_RENEWING
:
1185 case DHCP_STATE_REBINDING
:
1186 r
= client_send_request(client
);
1187 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1190 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1191 client
->state
= DHCP_STATE_REBOOTING
;
1193 client
->request_sent
= time_now
;
1197 case DHCP_STATE_REBOOTING
:
1198 case DHCP_STATE_BOUND
:
1202 case DHCP_STATE_STOPPED
:
1210 client_stop(client
, r
);
1212 /* Errors were dealt with when stopping the client, don't spill
1213 errors into the event loop handler */
1217 static int client_initialize_io_events(
1218 sd_dhcp_client
*client
,
1219 sd_event_io_handler_t io_callback
) {
1224 assert(client
->event
);
1226 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1227 client
->fd
, EPOLLIN
, io_callback
,
1232 r
= sd_event_source_set_priority(client
->receive_message
,
1233 client
->event_priority
);
1237 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1243 client_stop(client
, r
);
1248 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1253 assert(client
->event
);
1255 if (client
->start_delay
> 0) {
1256 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1257 usec
+= client
->start_delay
;
1260 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1261 clock_boottime_or_monotonic(),
1263 client_timeout_resend
, client
,
1264 client
->event_priority
, "dhcp4-resend-timer", true);
1266 client_stop(client
, r
);
1272 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1273 client_initialize_io_events(client
, io_callback
);
1274 client_initialize_time_events(client
);
1279 static int client_start_delayed(sd_dhcp_client
*client
) {
1282 assert_return(client
, -EINVAL
);
1283 assert_return(client
->event
, -EINVAL
);
1284 assert_return(client
->ifindex
> 0, -EINVAL
);
1285 assert_return(client
->fd
< 0, -EBUSY
);
1286 assert_return(client
->xid
== 0, -EINVAL
);
1287 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1289 client
->xid
= random_u32();
1291 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1292 client
->xid
, client
->mac_addr
,
1293 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1295 client_stop(client
, r
);
1300 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1301 client
->start_time
= now(clock_boottime_or_monotonic());
1303 return client_initialize_events(client
, client_receive_message_raw
);
1306 static int client_start(sd_dhcp_client
*client
) {
1307 client
->start_delay
= 0;
1308 return client_start_delayed(client
);
1311 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1312 sd_dhcp_client
*client
= userdata
;
1313 DHCP_CLIENT_DONT_DESTROY(client
);
1315 log_dhcp_client(client
, "EXPIRED");
1317 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1319 /* lease was lost, start over if not freed or stopped in callback */
1320 if (client
->state
!= DHCP_STATE_STOPPED
) {
1321 client_initialize(client
);
1322 client_start(client
);
1328 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1329 sd_dhcp_client
*client
= userdata
;
1330 DHCP_CLIENT_DONT_DESTROY(client
);
1335 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1336 client
->fd
= asynchronous_close(client
->fd
);
1338 client
->state
= DHCP_STATE_REBINDING
;
1339 client
->attempt
= 0;
1341 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1342 client
->xid
, client
->mac_addr
,
1343 client
->mac_addr_len
, client
->arp_type
,
1346 client_stop(client
, r
);
1351 return client_initialize_events(client
, client_receive_message_raw
);
1354 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1355 sd_dhcp_client
*client
= userdata
;
1356 DHCP_CLIENT_DONT_DESTROY(client
);
1358 client
->state
= DHCP_STATE_RENEWING
;
1359 client
->attempt
= 0;
1361 return client_initialize_time_events(client
);
1364 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1365 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1368 r
= dhcp_lease_new(&lease
);
1372 if (client
->client_id_len
) {
1373 r
= dhcp_lease_set_client_id(lease
,
1374 (uint8_t *) &client
->client_id
,
1375 client
->client_id_len
);
1380 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1381 if (r
!= DHCP_OFFER
) {
1382 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1386 lease
->next_server
= offer
->siaddr
;
1387 lease
->address
= offer
->yiaddr
;
1389 if (lease
->address
== 0 ||
1390 lease
->server_address
== 0 ||
1391 lease
->lifetime
== 0) {
1392 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1396 if (!lease
->have_subnet_mask
) {
1397 r
= dhcp_lease_set_default_subnet_mask(lease
);
1399 log_dhcp_client(client
,
1400 "received lease lacks subnet mask, "
1401 "and a fallback one cannot be generated, ignoring");
1406 sd_dhcp_lease_unref(client
->lease
);
1407 client
->lease
= TAKE_PTR(lease
);
1409 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1412 log_dhcp_client(client
, "OFFER");
1417 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1420 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1421 if (r
!= DHCP_FORCERENEW
)
1424 log_dhcp_client(client
, "FORCERENEW");
1429 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1430 if (a
->address
!= b
->address
)
1433 if (a
->subnet_mask
!= b
->subnet_mask
)
1436 if (a
->router_size
!= b
->router_size
)
1439 for (size_t i
= 0; i
< a
->router_size
; i
++)
1440 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1446 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1447 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1448 _cleanup_free_
char *error_message
= NULL
;
1451 r
= dhcp_lease_new(&lease
);
1455 if (client
->client_id_len
) {
1456 r
= dhcp_lease_set_client_id(lease
,
1457 (uint8_t *) &client
->client_id
,
1458 client
->client_id_len
);
1463 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1464 if (r
== DHCP_NAK
) {
1465 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1466 return -EADDRNOTAVAIL
;
1469 if (r
!= DHCP_ACK
) {
1470 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1474 lease
->next_server
= ack
->siaddr
;
1476 lease
->address
= ack
->yiaddr
;
1478 if (lease
->address
== INADDR_ANY
||
1479 lease
->server_address
== INADDR_ANY
||
1480 lease
->lifetime
== 0) {
1481 log_dhcp_client(client
, "received lease lacks address, server "
1482 "address or lease lifetime, ignoring");
1486 if (lease
->subnet_mask
== INADDR_ANY
) {
1487 r
= dhcp_lease_set_default_subnet_mask(lease
);
1489 log_dhcp_client(client
,
1490 "received lease lacks subnet mask, "
1491 "and a fallback one cannot be generated, ignoring");
1496 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1497 if (client
->lease
) {
1498 if (lease_equal(client
->lease
, lease
))
1499 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1501 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1503 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1506 client
->lease
= TAKE_PTR(lease
);
1508 log_dhcp_client(client
, "ACK");
1513 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1515 assert(client
->request_sent
);
1516 assert(lifetime
> 0);
1523 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1524 + (random_u32() & 0x1fffff);
1527 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1529 uint64_t lifetime_timeout
;
1530 uint64_t t2_timeout
;
1531 uint64_t t1_timeout
;
1532 char time_string
[FORMAT_TIMESPAN_MAX
];
1536 assert(client
->event
);
1537 assert(client
->lease
);
1538 assert(client
->lease
->lifetime
);
1540 /* don't set timers for infinite leases */
1541 if (client
->lease
->lifetime
== 0xffffffff) {
1542 (void) event_source_disable(client
->timeout_t1
);
1543 (void) event_source_disable(client
->timeout_t2
);
1544 (void) event_source_disable(client
->timeout_expire
);
1549 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1552 assert(client
->request_sent
<= time_now
);
1554 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1555 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1556 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1557 /* both T1 and T2 are given */
1558 if (client
->lease
->t1
< client
->lease
->t2
&&
1559 client
->lease
->t2
< client
->lease
->lifetime
) {
1560 /* they are both valid */
1561 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1562 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1565 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1566 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1567 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1568 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1570 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1571 /* only T2 is given, and it is valid */
1572 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1573 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1574 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1575 if (t2_timeout
<= t1_timeout
) {
1576 /* the computed T1 would be invalid, so discard T2 */
1577 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1578 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1580 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1581 /* only T1 is given, and it is valid */
1582 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1583 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1584 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1585 if (t2_timeout
<= t1_timeout
) {
1586 /* the computed T2 would be invalid, so discard T1 */
1587 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1588 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1591 /* fall back to the default timeouts */
1592 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1593 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1594 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1595 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1598 /* arm lifetime timeout */
1599 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1600 clock_boottime_or_monotonic(),
1601 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1602 client_timeout_expire
, client
,
1603 client
->event_priority
, "dhcp4-lifetime", true);
1607 log_dhcp_client(client
, "lease expires in %s",
1608 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1610 /* don't arm earlier timeouts if this has already expired */
1611 if (lifetime_timeout
<= time_now
)
1614 /* arm T2 timeout */
1615 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1616 clock_boottime_or_monotonic(),
1617 t2_timeout
, 10 * USEC_PER_MSEC
,
1618 client_timeout_t2
, client
,
1619 client
->event_priority
, "dhcp4-t2-timeout", true);
1623 log_dhcp_client(client
, "T2 expires in %s",
1624 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1626 /* don't arm earlier timeout if this has already expired */
1627 if (t2_timeout
<= time_now
)
1630 /* arm T1 timeout */
1631 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1632 clock_boottime_or_monotonic(),
1633 t1_timeout
, 10 * USEC_PER_MSEC
,
1634 client_timeout_t1
, client
,
1635 client
->event_priority
, "dhcp4-t1-timer", true);
1639 log_dhcp_client(client
, "T1 expires in %s",
1640 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1645 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1646 DHCP_CLIENT_DONT_DESTROY(client
);
1647 char time_string
[FORMAT_TIMESPAN_MAX
];
1648 int r
= 0, notify_event
= 0;
1651 assert(client
->event
);
1654 switch (client
->state
) {
1655 case DHCP_STATE_SELECTING
:
1657 r
= client_handle_offer(client
, message
, len
);
1660 client
->state
= DHCP_STATE_REQUESTING
;
1661 client
->attempt
= 0;
1663 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1664 clock_boottime_or_monotonic(),
1666 client_timeout_resend
, client
,
1667 client
->event_priority
, "dhcp4-resend-timer", true);
1670 } else if (r
== -ENOMSG
)
1671 /* invalid message, let's ignore it */
1676 case DHCP_STATE_REBOOTING
:
1677 case DHCP_STATE_REQUESTING
:
1678 case DHCP_STATE_RENEWING
:
1679 case DHCP_STATE_REBINDING
:
1681 r
= client_handle_ack(client
, message
, len
);
1683 client
->start_delay
= 0;
1684 (void) event_source_disable(client
->timeout_resend
);
1685 client
->receive_message
=
1686 sd_event_source_unref(client
->receive_message
);
1687 client
->fd
= asynchronous_close(client
->fd
);
1689 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1690 DHCP_STATE_REBOOTING
))
1691 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1692 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1695 client
->state
= DHCP_STATE_BOUND
;
1696 client
->attempt
= 0;
1698 client
->last_addr
= client
->lease
->address
;
1700 r
= client_set_lease_timeouts(client
);
1702 log_dhcp_client(client
, "could not set lease timeouts");
1706 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1708 log_dhcp_client(client
, "could not bind UDP socket");
1714 client_initialize_io_events(client
, client_receive_message_udp
);
1717 client_notify(client
, notify_event
);
1718 if (client
->state
== DHCP_STATE_STOPPED
)
1722 } else if (r
== -EADDRNOTAVAIL
) {
1723 /* got a NAK, let's restart the client */
1724 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1726 r
= client_initialize(client
);
1730 r
= client_start_delayed(client
);
1734 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1735 client
->start_delay
, USEC_PER_SEC
));
1737 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1738 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1741 } else if (r
== -ENOMSG
)
1742 /* invalid message, let's ignore it */
1747 case DHCP_STATE_BOUND
:
1748 r
= client_handle_forcerenew(client
, message
, len
);
1750 r
= client_timeout_t1(NULL
, 0, client
);
1753 } else if (r
== -ENOMSG
)
1754 /* invalid message, let's ignore it */
1759 case DHCP_STATE_INIT
:
1760 case DHCP_STATE_INIT_REBOOT
:
1764 case DHCP_STATE_STOPPED
:
1771 client_stop(client
, r
);
1776 static int client_receive_message_udp(
1782 sd_dhcp_client
*client
= userdata
;
1783 _cleanup_free_ DHCPMessage
*message
= NULL
;
1784 const uint8_t *expected_chaddr
= NULL
;
1785 uint8_t expected_hlen
= 0;
1786 ssize_t len
, buflen
;
1791 buflen
= next_datagram_size_fd(fd
);
1792 if (buflen
== -ENETDOWN
) {
1793 /* the link is down. Don't return an error or the I/O event
1794 source will be disconnected and we won't be able to receive
1795 packets again when the link comes back. */
1801 message
= malloc0(buflen
);
1805 len
= recv(fd
, message
, buflen
, 0);
1807 /* see comment above for why we shouldn't error out on ENETDOWN. */
1808 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1811 return log_dhcp_client_errno(client
, errno
,
1812 "Could not receive message from UDP socket: %m");
1814 if ((size_t) len
< sizeof(DHCPMessage
)) {
1815 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1819 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1820 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1824 if (message
->op
!= BOOTREPLY
) {
1825 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1829 if (message
->htype
!= client
->arp_type
) {
1830 log_dhcp_client(client
, "Packet type does not match client type");
1834 if (client
->arp_type
== ARPHRD_ETHER
) {
1835 expected_hlen
= ETH_ALEN
;
1836 expected_chaddr
= &client
->mac_addr
[0];
1839 if (message
->hlen
!= expected_hlen
) {
1840 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1844 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1845 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1849 if (client
->state
!= DHCP_STATE_BOUND
&&
1850 be32toh(message
->xid
) != client
->xid
) {
1851 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1852 so ignore the xid in this case */
1853 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1854 be32toh(message
->xid
), client
->xid
);
1858 return client_handle_message(client
, message
, len
);
1861 static int client_receive_message_raw(
1867 sd_dhcp_client
*client
= userdata
;
1868 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1869 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1870 struct iovec iov
= {};
1871 struct msghdr msg
= {
1874 .msg_control
= cmsgbuf
,
1875 .msg_controllen
= sizeof(cmsgbuf
),
1877 struct cmsghdr
*cmsg
;
1878 bool checksum
= true;
1879 ssize_t buflen
, len
;
1885 buflen
= next_datagram_size_fd(fd
);
1886 if (buflen
== -ENETDOWN
)
1891 packet
= malloc0(buflen
);
1895 iov
= IOVEC_MAKE(packet
, buflen
);
1897 len
= recvmsg(fd
, &msg
, 0);
1899 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1902 return log_dhcp_client_errno(client
, errno
,
1903 "Could not receive message from raw socket: %m");
1904 } else if ((size_t)len
< sizeof(DHCPPacket
))
1907 CMSG_FOREACH(cmsg
, &msg
)
1908 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1909 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1910 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1911 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1913 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1917 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1921 len
-= DHCP_IP_UDP_SIZE
;
1923 return client_handle_message(client
, &packet
->dhcp
, len
);
1926 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1927 assert_return(client
, -EINVAL
);
1928 assert_return(client
->fd
>= 0, -EINVAL
);
1930 client
->start_delay
= 0;
1931 client
->attempt
= 1;
1932 client
->state
= DHCP_STATE_RENEWING
;
1934 return client_initialize_time_events(client
);
1937 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1940 assert_return(client
, -EINVAL
);
1942 r
= client_initialize(client
);
1946 /* RFC7844 section 3.3:
1947 SHOULD perform a complete four-way handshake, starting with a
1948 DHCPDISCOVER, to obtain a new address lease. If the client can
1949 ascertain that this is exactly the same network to which it was
1950 previously connected, and if the link-layer address did not change,
1951 the client MAY issue a DHCPREQUEST to try to reclaim the current
1953 if (client
->last_addr
&& !client
->anonymize
)
1954 client
->state
= DHCP_STATE_INIT_REBOOT
;
1956 r
= client_start(client
);
1958 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1963 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1964 assert_return(client
, -EINVAL
);
1965 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1966 assert_return(client
->lease
, -EUNATCH
);
1968 _cleanup_free_ DHCPPacket
*release
= NULL
;
1969 size_t optoffset
, optlen
;
1972 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
1976 /* Fill up release IP and MAC */
1977 release
->dhcp
.ciaddr
= client
->lease
->address
;
1978 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1980 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1981 SD_DHCP_OPTION_END
, 0, NULL
);
1985 r
= dhcp_network_send_udp_socket(client
->fd
,
1986 client
->lease
->server_address
,
1989 sizeof(DHCPMessage
) + optoffset
);
1993 log_dhcp_client(client
, "RELEASE");
1998 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
1999 assert_return(client
, -EINVAL
);
2000 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2001 assert_return(client
->lease
, -EUNATCH
);
2003 _cleanup_free_ DHCPPacket
*release
= NULL
;
2004 size_t optoffset
, optlen
;
2007 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2011 release
->dhcp
.ciaddr
= client
->lease
->address
;
2012 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2014 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2015 SD_DHCP_OPTION_END
, 0, NULL
);
2019 r
= dhcp_network_send_udp_socket(client
->fd
,
2020 client
->lease
->server_address
,
2023 sizeof(DHCPMessage
) + optoffset
);
2027 log_dhcp_client(client
, "DECLINE");
2029 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2031 if (client
->state
!= DHCP_STATE_STOPPED
) {
2032 r
= sd_dhcp_client_start(client
);
2040 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2041 DHCP_CLIENT_DONT_DESTROY(client
);
2043 assert_return(client
, -EINVAL
);
2045 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2046 client
->state
= DHCP_STATE_STOPPED
;
2051 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2054 assert_return(client
, -EINVAL
);
2055 assert_return(!client
->event
, -EBUSY
);
2058 client
->event
= sd_event_ref(event
);
2060 r
= sd_event_default(&client
->event
);
2065 client
->event_priority
= priority
;
2070 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2071 assert_return(client
, -EINVAL
);
2073 client
->event
= sd_event_unref(client
->event
);
2078 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2079 assert_return(client
, NULL
);
2081 return client
->event
;
2084 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2088 log_dhcp_client(client
, "FREE");
2090 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2091 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2092 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2093 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2095 client_initialize(client
);
2097 sd_dhcp_client_detach_event(client
);
2099 sd_dhcp_lease_unref(client
->lease
);
2101 free(client
->req_opts
);
2102 free(client
->hostname
);
2103 free(client
->vendor_class_identifier
);
2104 client
->user_class
= strv_free(client
->user_class
);
2105 ordered_hashmap_free(client
->extra_options
);
2106 ordered_hashmap_free(client
->vendor_options
);
2107 return mfree(client
);
2110 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2112 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2113 assert_return(ret
, -EINVAL
);
2115 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2119 *client
= (sd_dhcp_client
) {
2121 .state
= DHCP_STATE_INIT
,
2124 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2125 .port
= DHCP_PORT_CLIENT
,
2126 .anonymize
= !!anonymize
,
2127 .max_attempts
= (uint64_t) -1,
2128 .ip_service_type
= -1,
2130 /* NOTE: this could be moved to a function. */
2132 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2133 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2135 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2136 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2138 if (!client
->req_opts
)
2141 *ret
= TAKE_PTR(client
);