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_option
{
45 struct sd_dhcp_client
{
51 sd_event_source
*timeout_resend
;
55 union sockaddr_union link
;
56 sd_event_source
*receive_message
;
57 bool request_broadcast
;
59 size_t req_opts_allocated
;
63 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
70 /* 0: Generic (non-LL) (RFC 2132) */
71 uint8_t data
[MAX_CLIENT_ID_LEN
];
74 /* 1: Ethernet Link-Layer (RFC 2132) */
75 uint8_t haddr
[ETH_ALEN
];
78 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
82 /* 255: Node-specific (RFC 4361) */
87 uint8_t data
[MAX_CLIENT_ID_LEN
];
93 char *vendor_class_identifier
;
99 uint64_t max_attempts
;
100 OrderedHashmap
*options
;
102 sd_event_source
*timeout_t1
;
103 sd_event_source
*timeout_t2
;
104 sd_event_source
*timeout_expire
;
105 sd_dhcp_client_callback_t callback
;
107 sd_dhcp_lease
*lease
;
112 static const uint8_t default_req_opts
[] = {
113 SD_DHCP_OPTION_SUBNET_MASK
,
114 SD_DHCP_OPTION_ROUTER
,
115 SD_DHCP_OPTION_HOST_NAME
,
116 SD_DHCP_OPTION_DOMAIN_NAME
,
117 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
120 /* RFC7844 section 3:
121 MAY contain the Parameter Request List option.
123 The client intending to protect its privacy SHOULD only request a
124 minimal number of options in the PRL and SHOULD also randomly shuffle
125 the ordering of option codes in the PRL. If this random ordering
126 cannot be implemented, the client MAY order the option codes in the
127 PRL by option code number (lowest to highest).
129 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
130 static const uint8_t default_req_opts_anonymize
[] = {
131 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
132 SD_DHCP_OPTION_ROUTER
, /* 3 */
133 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
134 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
135 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
136 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
137 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
138 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
139 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
140 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
141 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
142 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
143 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
146 static int client_receive_message_raw(
151 static int client_receive_message_udp(
156 static void client_stop(sd_dhcp_client
*client
, int error
);
158 int sd_dhcp_client_set_callback(
159 sd_dhcp_client
*client
,
160 sd_dhcp_client_callback_t cb
,
163 assert_return(client
, -EINVAL
);
165 client
->callback
= cb
;
166 client
->userdata
= userdata
;
171 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
172 assert_return(client
, -EINVAL
);
174 client
->request_broadcast
= !!broadcast
;
179 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
182 assert_return(client
, -EINVAL
);
183 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
187 case SD_DHCP_OPTION_PAD
:
188 case SD_DHCP_OPTION_OVERLOAD
:
189 case SD_DHCP_OPTION_MESSAGE_TYPE
:
190 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
191 case SD_DHCP_OPTION_END
:
198 for (i
= 0; i
< client
->req_opts_size
; i
++)
199 if (client
->req_opts
[i
] == option
)
202 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
203 client
->req_opts_size
+ 1))
206 client
->req_opts
[client
->req_opts_size
++] = option
;
211 int sd_dhcp_client_set_request_address(
212 sd_dhcp_client
*client
,
213 const struct in_addr
*last_addr
) {
215 assert_return(client
, -EINVAL
);
216 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
219 client
->last_addr
= last_addr
->s_addr
;
221 client
->last_addr
= INADDR_ANY
;
226 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
228 assert_return(client
, -EINVAL
);
229 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
230 assert_return(ifindex
> 0, -EINVAL
);
232 client
->ifindex
= ifindex
;
236 int sd_dhcp_client_set_mac(
237 sd_dhcp_client
*client
,
242 DHCP_CLIENT_DONT_DESTROY(client
);
243 bool need_restart
= false;
246 assert_return(client
, -EINVAL
);
247 assert_return(addr
, -EINVAL
);
248 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
249 assert_return(arp_type
> 0, -EINVAL
);
251 if (arp_type
== ARPHRD_ETHER
)
252 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
253 else if (arp_type
== ARPHRD_INFINIBAND
)
254 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
258 if (client
->mac_addr_len
== addr_len
&&
259 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
262 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
263 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
265 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
268 memcpy(&client
->mac_addr
, addr
, addr_len
);
269 client
->mac_addr_len
= addr_len
;
270 client
->arp_type
= arp_type
;
272 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
273 r
= sd_dhcp_client_start(client
);
275 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
281 int sd_dhcp_client_get_client_id(
282 sd_dhcp_client
*client
,
284 const uint8_t **data
,
287 assert_return(client
, -EINVAL
);
288 assert_return(type
, -EINVAL
);
289 assert_return(data
, -EINVAL
);
290 assert_return(data_len
, -EINVAL
);
295 if (client
->client_id_len
) {
296 *type
= client
->client_id
.type
;
297 *data
= client
->client_id
.raw
.data
;
298 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
304 int sd_dhcp_client_set_client_id(
305 sd_dhcp_client
*client
,
310 DHCP_CLIENT_DONT_DESTROY(client
);
311 bool need_restart
= false;
314 assert_return(client
, -EINVAL
);
315 assert_return(data
, -EINVAL
);
316 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
318 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
319 client
->client_id
.type
== type
&&
320 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
323 /* For hardware types, log debug message about unexpected data length.
325 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
326 * last last 8 bytes of the address are stable and suitable to put into
327 * the client-id. The caller is advised to account for that. */
328 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
329 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
330 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
331 "unexpected address length %zu",
334 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
335 log_dhcp_client(client
, "Changing client ID on running DHCP "
336 "client, restarting");
338 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
341 client
->client_id
.type
= type
;
342 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
343 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
345 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
346 r
= sd_dhcp_client_start(client
);
348 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
355 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
356 * without further modification. Otherwise, if duid_type is supported, DUID
357 * is set based on that type. Otherwise, an error is returned.
359 static int dhcp_client_set_iaid_duid_internal(
360 sd_dhcp_client
*client
,
369 DHCP_CLIENT_DONT_DESTROY(client
);
373 assert_return(client
, -EINVAL
);
374 assert_return(duid_len
== 0 || duid
, -EINVAL
);
377 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
379 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
382 zero(client
->client_id
);
383 client
->client_id
.type
= 255;
387 client
->client_id
.ns
.iaid
= htobe32(iaid
);
389 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
390 client
->mac_addr_len
,
392 &client
->client_id
.ns
.iaid
);
394 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
399 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
400 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
401 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
405 if (client
->mac_addr_len
== 0)
406 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
408 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
410 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
413 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
415 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
418 if (client
->mac_addr_len
== 0)
419 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
421 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
423 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
426 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
428 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
431 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
434 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
435 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
437 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
438 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
439 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
440 r
= sd_dhcp_client_start(client
);
442 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
448 int sd_dhcp_client_set_iaid_duid(
449 sd_dhcp_client
*client
,
455 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
458 int sd_dhcp_client_set_iaid_duid_llt(
459 sd_dhcp_client
*client
,
463 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
466 int sd_dhcp_client_set_duid(
467 sd_dhcp_client
*client
,
471 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
474 int sd_dhcp_client_set_duid_llt(
475 sd_dhcp_client
*client
,
477 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
480 int sd_dhcp_client_set_hostname(
481 sd_dhcp_client
*client
,
482 const char *hostname
) {
484 assert_return(client
, -EINVAL
);
486 /* Make sure hostnames qualify as DNS and as Linux hostnames */
488 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
491 return free_and_strdup(&client
->hostname
, hostname
);
494 int sd_dhcp_client_set_vendor_class_identifier(
495 sd_dhcp_client
*client
,
498 assert_return(client
, -EINVAL
);
500 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
503 int sd_dhcp_client_set_user_class(
504 sd_dhcp_client
*client
,
505 const char* const* user_class
) {
507 _cleanup_strv_free_
char **s
= NULL
;
510 STRV_FOREACH(p
, (char **) user_class
)
511 if (strlen(*p
) > 255)
512 return -ENAMETOOLONG
;
514 s
= strv_copy((char **) user_class
);
518 client
->user_class
= TAKE_PTR(s
);
523 int sd_dhcp_client_set_client_port(
524 sd_dhcp_client
*client
,
527 assert_return(client
, -EINVAL
);
534 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
535 assert_return(client
, -EINVAL
);
536 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
543 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
544 assert_return(client
, -EINVAL
);
546 client
->max_attempts
= max_attempts
;
551 static sd_dhcp_option
* dhcp_option_free(sd_dhcp_option
*i
) {
559 int sd_dhcp_option_new(uint8_t option
, void *data
, size_t length
, sd_dhcp_option
**ret
) {
560 assert_return(ret
, -EINVAL
);
561 assert_return(length
== 0 || data
, -EINVAL
);
563 _cleanup_free_
void *q
= memdup(data
, length
);
567 sd_dhcp_option
*p
= new(sd_dhcp_option
, 1);
571 *p
= (sd_dhcp_option
) {
582 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option
, sd_dhcp_option
, dhcp_option_free
);
583 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
584 dhcp_option_hash_ops
,
587 trivial_compare_func
,
589 sd_dhcp_option_unref
);
591 int sd_dhcp_client_set_dhcp_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
594 assert_return(client
, -EINVAL
);
595 assert_return(v
, -EINVAL
);
597 r
= ordered_hashmap_ensure_allocated(&client
->options
, &dhcp_option_hash_ops
);
601 r
= ordered_hashmap_put(client
->options
, UINT_TO_PTR(v
->option
), v
);
605 sd_dhcp_option_ref(v
);
609 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
610 assert_return(client
, -EINVAL
);
612 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
613 return -EADDRNOTAVAIL
;
616 *ret
= client
->lease
;
621 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
622 assert_return(client
, -EINVAL
);
624 client
->ip_service_type
= type
;
629 static int client_notify(sd_dhcp_client
*client
, int event
) {
632 if (client
->callback
)
633 return client
->callback(client
, event
, client
->userdata
);
638 static int client_initialize(sd_dhcp_client
*client
) {
639 assert_return(client
, -EINVAL
);
641 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
643 client
->fd
= asynchronous_close(client
->fd
);
645 (void) event_source_disable(client
->timeout_resend
);
646 (void) event_source_disable(client
->timeout_t1
);
647 (void) event_source_disable(client
->timeout_t2
);
648 (void) event_source_disable(client
->timeout_expire
);
652 client
->state
= DHCP_STATE_INIT
;
655 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
660 static void client_stop(sd_dhcp_client
*client
, int error
) {
664 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
665 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
666 log_dhcp_client(client
, "STOPPED");
668 log_dhcp_client(client
, "STOPPED: Unknown event");
670 client_notify(client
, error
);
672 client_initialize(client
);
675 static int client_message_init(
676 sd_dhcp_client
*client
,
680 size_t *_optoffset
) {
682 _cleanup_free_ DHCPPacket
*packet
= NULL
;
683 size_t optlen
, optoffset
, size
;
690 assert(client
->start_time
);
694 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
));
696 optlen
= DHCP_MIN_OPTIONS_SIZE
;
697 size
= sizeof(DHCPPacket
) + optlen
;
699 packet
= malloc0(size
);
703 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
704 client
->arp_type
, optlen
, &optoffset
);
708 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
709 refuse to issue an DHCP lease if 'secs' is set to zero */
710 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
713 assert(time_now
>= client
->start_time
);
715 /* seconds between sending first and last DISCOVER
716 * must always be strictly positive to deal with broken servers */
717 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
718 packet
->dhcp
.secs
= htobe16(secs
);
720 /* RFC2132 section 4.1
721 A client that cannot receive unicast IP datagrams until its protocol
722 software has been configured with an IP address SHOULD set the
723 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
724 DHCPREQUEST messages that client sends. The BROADCAST bit will
725 provide a hint to the DHCP server and BOOTP relay agent to broadcast
726 any messages to the client on the client's subnet.
728 Note: some interfaces needs this to be enabled, but some networks
729 needs this to be disabled as broadcasts are filteretd, so this
730 needs to be configurable */
731 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
732 packet
->dhcp
.flags
= htobe16(0x8000);
734 /* RFC2132 section 4.1.1:
735 The client MUST include its hardware address in the ’chaddr’ field, if
736 necessary for delivery of DHCP reply messages. Non-Ethernet
737 interfaces will leave 'chaddr' empty and use the client identifier
738 instead (eg, RFC 4390 section 2.1).
740 if (client
->arp_type
== ARPHRD_ETHER
)
741 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
743 /* If no client identifier exists, construct an RFC 4361-compliant one */
744 if (client
->client_id_len
== 0) {
747 client
->client_id
.type
= 255;
749 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
750 true, &client
->client_id
.ns
.iaid
);
754 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
758 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
761 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
762 Identifier option is not set */
763 if (client
->client_id_len
) {
764 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
765 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
766 client
->client_id_len
,
772 /* RFC2131 section 3.5:
773 in its initial DHCPDISCOVER or DHCPREQUEST message, a
774 client may provide the server with a list of specific
775 parameters the client is interested in. If the client
776 includes a list of parameters in a DHCPDISCOVER message,
777 it MUST include that list in any subsequent DHCPREQUEST
781 /* RFC7844 section 3:
782 MAY contain the Parameter Request List option. */
783 /* NOTE: in case that there would be an option to do not send
784 * any PRL at all, the size should be checked before sending */
785 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
786 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
787 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
788 client
->req_opts_size
, client
->req_opts
);
793 /* RFC2131 section 3.5:
794 The client SHOULD include the ’maximum DHCP message size’ option to
795 let the server know how large the server may make its DHCP messages.
797 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
798 than the defined default size unless the Maximum Message Size option
801 RFC3442 "Requirements to Avoid Sizing Constraints":
802 Because a full routing table can be quite large, the standard 576
803 octet maximum size for a DHCP message may be too short to contain
804 some legitimate Classless Static Route options. Because of this,
805 clients implementing the Classless Static Route option SHOULD send a
806 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
807 stack is capable of receiving larger IP datagrams. In this case, the
808 client SHOULD set the value of this option to at least the MTU of the
809 interface that the client is configuring. The client MAY set the
810 value of this option higher, up to the size of the largest UDP packet
811 it is prepared to accept. (Note that the value specified in the
812 Maximum DHCP Message Size option is the total maximum packet size,
813 including IP and UDP headers.)
815 /* RFC7844 section 3:
816 SHOULD NOT contain any other option. */
817 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
818 max_size
= htobe16(size
);
819 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
820 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
827 *_optoffset
= optoffset
;
828 *ret
= TAKE_PTR(packet
);
833 static int client_append_fqdn_option(
834 DHCPMessage
*message
,
839 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
842 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
843 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
844 buffer
[1] = 0; /* RCODE1 (deprecated) */
845 buffer
[2] = 0; /* RCODE2 (deprecated) */
847 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
849 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
850 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
855 static int dhcp_client_send_raw(
856 sd_dhcp_client
*client
,
860 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
861 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
863 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
867 static int client_send_discover(sd_dhcp_client
*client
) {
868 _cleanup_free_ DHCPPacket
*discover
= NULL
;
869 size_t optoffset
, optlen
;
875 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
877 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
878 &optlen
, &optoffset
);
882 /* the client may suggest values for the network address
883 and lease time in the DHCPDISCOVER message. The client may include
884 the ’requested IP address’ option to suggest that a particular IP
885 address be assigned, and may include the ’IP address lease time’
886 option to suggest the lease time it would like.
888 if (client
->last_addr
!= INADDR_ANY
) {
889 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
890 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
891 4, &client
->last_addr
);
896 if (client
->hostname
) {
897 /* According to RFC 4702 "clients that send the Client FQDN option in
898 their messages MUST NOT also send the Host Name option". Just send
899 one of the two depending on the hostname type.
901 if (dns_name_is_single_label(client
->hostname
)) {
902 /* it is unclear from RFC 2131 if client should send hostname in
903 DHCPDISCOVER but dhclient does and so we do as well
905 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
906 SD_DHCP_OPTION_HOST_NAME
,
907 strlen(client
->hostname
), client
->hostname
);
909 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
915 if (client
->vendor_class_identifier
) {
916 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
917 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
918 strlen(client
->vendor_class_identifier
),
919 client
->vendor_class_identifier
);
924 if (client
->user_class
) {
925 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
926 SD_DHCP_OPTION_USER_CLASS
,
927 strv_length(client
->user_class
),
933 ORDERED_HASHMAP_FOREACH(j
, client
->options
, i
) {
934 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
935 j
->option
, j
->length
, j
->data
);
940 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
941 SD_DHCP_OPTION_END
, 0, NULL
);
945 /* We currently ignore:
946 The client SHOULD wait a random time between one and ten seconds to
947 desynchronize the use of DHCP at startup.
949 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
953 log_dhcp_client(client
, "DISCOVER");
958 static int client_send_request(sd_dhcp_client
*client
) {
959 _cleanup_free_ DHCPPacket
*request
= NULL
;
960 size_t optoffset
, optlen
;
965 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
969 switch (client
->state
) {
970 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
971 SELECTING should be REQUESTING)
974 case DHCP_STATE_REQUESTING
:
975 /* Client inserts the address of the selected server in ’server
976 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
977 filled in with the yiaddr value from the chosen DHCPOFFER.
980 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
981 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
982 4, &client
->lease
->server_address
);
986 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
987 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
988 4, &client
->lease
->address
);
994 case DHCP_STATE_INIT_REBOOT
:
995 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
996 option MUST be filled in with client’s notion of its previously
997 assigned address. ’ciaddr’ MUST be zero.
999 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1000 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1001 4, &client
->last_addr
);
1006 case DHCP_STATE_RENEWING
:
1007 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1008 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1009 client’s IP address.
1012 case DHCP_STATE_REBINDING
:
1013 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1014 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1015 client’s IP address.
1017 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1019 request
->dhcp
.ciaddr
= client
->lease
->address
;
1023 case DHCP_STATE_INIT
:
1024 case DHCP_STATE_SELECTING
:
1025 case DHCP_STATE_REBOOTING
:
1026 case DHCP_STATE_BOUND
:
1027 case DHCP_STATE_STOPPED
:
1031 if (client
->hostname
) {
1032 if (dns_name_is_single_label(client
->hostname
))
1033 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1034 SD_DHCP_OPTION_HOST_NAME
,
1035 strlen(client
->hostname
), client
->hostname
);
1037 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
1043 if (client
->vendor_class_identifier
) {
1044 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1045 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1046 strlen(client
->vendor_class_identifier
),
1047 client
->vendor_class_identifier
);
1052 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1053 SD_DHCP_OPTION_END
, 0, NULL
);
1057 if (client
->state
== DHCP_STATE_RENEWING
)
1058 r
= dhcp_network_send_udp_socket(client
->fd
,
1059 client
->lease
->server_address
,
1062 sizeof(DHCPMessage
) + optoffset
);
1064 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1068 switch (client
->state
) {
1070 case DHCP_STATE_REQUESTING
:
1071 log_dhcp_client(client
, "REQUEST (requesting)");
1074 case DHCP_STATE_INIT_REBOOT
:
1075 log_dhcp_client(client
, "REQUEST (init-reboot)");
1078 case DHCP_STATE_RENEWING
:
1079 log_dhcp_client(client
, "REQUEST (renewing)");
1082 case DHCP_STATE_REBINDING
:
1083 log_dhcp_client(client
, "REQUEST (rebinding)");
1087 log_dhcp_client(client
, "REQUEST (invalid)");
1094 static int client_start(sd_dhcp_client
*client
);
1096 static int client_timeout_resend(
1101 sd_dhcp_client
*client
= userdata
;
1102 DHCP_CLIENT_DONT_DESTROY(client
);
1103 usec_t next_timeout
= 0;
1110 assert(client
->event
);
1112 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1116 switch (client
->state
) {
1118 case DHCP_STATE_RENEWING
:
1120 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1124 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1128 case DHCP_STATE_REBINDING
:
1130 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1134 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1137 case DHCP_STATE_REBOOTING
:
1138 /* start over as we did not receive a timely ack or nak */
1139 r
= client_initialize(client
);
1143 r
= client_start(client
);
1147 log_dhcp_client(client
, "REBOOTED");
1151 case DHCP_STATE_INIT
:
1152 case DHCP_STATE_INIT_REBOOT
:
1153 case DHCP_STATE_SELECTING
:
1154 case DHCP_STATE_REQUESTING
:
1155 case DHCP_STATE_BOUND
:
1157 if (client
->attempt
< client
->max_attempts
)
1162 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1166 case DHCP_STATE_STOPPED
:
1171 next_timeout
+= (random_u32() & 0x1fffff);
1173 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1174 clock_boottime_or_monotonic(),
1175 next_timeout
, 10 * USEC_PER_MSEC
,
1176 client_timeout_resend
, client
,
1177 client
->event_priority
, "dhcp4-resend-timer", true);
1181 switch (client
->state
) {
1182 case DHCP_STATE_INIT
:
1183 r
= client_send_discover(client
);
1185 client
->state
= DHCP_STATE_SELECTING
;
1186 client
->attempt
= 0;
1187 } else if (client
->attempt
>= client
->max_attempts
)
1192 case DHCP_STATE_SELECTING
:
1193 r
= client_send_discover(client
);
1194 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1199 case DHCP_STATE_INIT_REBOOT
:
1200 case DHCP_STATE_REQUESTING
:
1201 case DHCP_STATE_RENEWING
:
1202 case DHCP_STATE_REBINDING
:
1203 r
= client_send_request(client
);
1204 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1207 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1208 client
->state
= DHCP_STATE_REBOOTING
;
1210 client
->request_sent
= time_now
;
1214 case DHCP_STATE_REBOOTING
:
1215 case DHCP_STATE_BOUND
:
1219 case DHCP_STATE_STOPPED
:
1227 client_stop(client
, r
);
1229 /* Errors were dealt with when stopping the client, don't spill
1230 errors into the event loop handler */
1234 static int client_initialize_io_events(
1235 sd_dhcp_client
*client
,
1236 sd_event_io_handler_t io_callback
) {
1241 assert(client
->event
);
1243 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1244 client
->fd
, EPOLLIN
, io_callback
,
1249 r
= sd_event_source_set_priority(client
->receive_message
,
1250 client
->event_priority
);
1254 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1260 client_stop(client
, r
);
1265 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1270 assert(client
->event
);
1272 if (client
->start_delay
> 0) {
1273 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1274 usec
+= client
->start_delay
;
1277 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1278 clock_boottime_or_monotonic(),
1280 client_timeout_resend
, client
,
1281 client
->event_priority
, "dhcp4-resend-timer", true);
1283 client_stop(client
, r
);
1289 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1290 client_initialize_io_events(client
, io_callback
);
1291 client_initialize_time_events(client
);
1296 static int client_start_delayed(sd_dhcp_client
*client
) {
1299 assert_return(client
, -EINVAL
);
1300 assert_return(client
->event
, -EINVAL
);
1301 assert_return(client
->ifindex
> 0, -EINVAL
);
1302 assert_return(client
->fd
< 0, -EBUSY
);
1303 assert_return(client
->xid
== 0, -EINVAL
);
1304 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1306 client
->xid
= random_u32();
1308 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1309 client
->xid
, client
->mac_addr
,
1310 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1312 client_stop(client
, r
);
1317 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1318 client
->start_time
= now(clock_boottime_or_monotonic());
1320 return client_initialize_events(client
, client_receive_message_raw
);
1323 static int client_start(sd_dhcp_client
*client
) {
1324 client
->start_delay
= 0;
1325 return client_start_delayed(client
);
1328 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1329 sd_dhcp_client
*client
= userdata
;
1330 DHCP_CLIENT_DONT_DESTROY(client
);
1332 log_dhcp_client(client
, "EXPIRED");
1334 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1336 /* lease was lost, start over if not freed or stopped in callback */
1337 if (client
->state
!= DHCP_STATE_STOPPED
) {
1338 client_initialize(client
);
1339 client_start(client
);
1345 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1346 sd_dhcp_client
*client
= userdata
;
1347 DHCP_CLIENT_DONT_DESTROY(client
);
1352 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1353 client
->fd
= asynchronous_close(client
->fd
);
1355 client
->state
= DHCP_STATE_REBINDING
;
1356 client
->attempt
= 0;
1358 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1359 client
->xid
, client
->mac_addr
,
1360 client
->mac_addr_len
, client
->arp_type
,
1363 client_stop(client
, r
);
1368 return client_initialize_events(client
, client_receive_message_raw
);
1371 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1372 sd_dhcp_client
*client
= userdata
;
1373 DHCP_CLIENT_DONT_DESTROY(client
);
1375 client
->state
= DHCP_STATE_RENEWING
;
1376 client
->attempt
= 0;
1378 return client_initialize_time_events(client
);
1381 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1382 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1385 r
= dhcp_lease_new(&lease
);
1389 if (client
->client_id_len
) {
1390 r
= dhcp_lease_set_client_id(lease
,
1391 (uint8_t *) &client
->client_id
,
1392 client
->client_id_len
);
1397 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1398 if (r
!= DHCP_OFFER
) {
1399 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1403 lease
->next_server
= offer
->siaddr
;
1404 lease
->address
= offer
->yiaddr
;
1406 if (lease
->address
== 0 ||
1407 lease
->server_address
== 0 ||
1408 lease
->lifetime
== 0) {
1409 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1413 if (!lease
->have_subnet_mask
) {
1414 r
= dhcp_lease_set_default_subnet_mask(lease
);
1416 log_dhcp_client(client
,
1417 "received lease lacks subnet mask, "
1418 "and a fallback one cannot be generated, ignoring");
1423 sd_dhcp_lease_unref(client
->lease
);
1424 client
->lease
= TAKE_PTR(lease
);
1426 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1429 log_dhcp_client(client
, "OFFER");
1434 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1437 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1438 if (r
!= DHCP_FORCERENEW
)
1441 log_dhcp_client(client
, "FORCERENEW");
1446 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1447 if (a
->address
!= b
->address
)
1450 if (a
->subnet_mask
!= b
->subnet_mask
)
1453 if (a
->router_size
!= b
->router_size
)
1456 for (size_t i
= 0; i
< a
->router_size
; i
++)
1457 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1463 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1464 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1465 _cleanup_free_
char *error_message
= NULL
;
1468 r
= dhcp_lease_new(&lease
);
1472 if (client
->client_id_len
) {
1473 r
= dhcp_lease_set_client_id(lease
,
1474 (uint8_t *) &client
->client_id
,
1475 client
->client_id_len
);
1480 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1481 if (r
== DHCP_NAK
) {
1482 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1483 return -EADDRNOTAVAIL
;
1486 if (r
!= DHCP_ACK
) {
1487 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1491 lease
->next_server
= ack
->siaddr
;
1493 lease
->address
= ack
->yiaddr
;
1495 if (lease
->address
== INADDR_ANY
||
1496 lease
->server_address
== INADDR_ANY
||
1497 lease
->lifetime
== 0) {
1498 log_dhcp_client(client
, "received lease lacks address, server "
1499 "address or lease lifetime, ignoring");
1503 if (lease
->subnet_mask
== INADDR_ANY
) {
1504 r
= dhcp_lease_set_default_subnet_mask(lease
);
1506 log_dhcp_client(client
,
1507 "received lease lacks subnet mask, "
1508 "and a fallback one cannot be generated, ignoring");
1513 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1514 if (client
->lease
) {
1515 if (lease_equal(client
->lease
, lease
))
1516 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1518 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1520 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1523 client
->lease
= TAKE_PTR(lease
);
1525 log_dhcp_client(client
, "ACK");
1530 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1532 assert(client
->request_sent
);
1533 assert(lifetime
> 0);
1540 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1541 + (random_u32() & 0x1fffff);
1544 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1546 uint64_t lifetime_timeout
;
1547 uint64_t t2_timeout
;
1548 uint64_t t1_timeout
;
1549 char time_string
[FORMAT_TIMESPAN_MAX
];
1553 assert(client
->event
);
1554 assert(client
->lease
);
1555 assert(client
->lease
->lifetime
);
1557 /* don't set timers for infinite leases */
1558 if (client
->lease
->lifetime
== 0xffffffff) {
1559 (void) event_source_disable(client
->timeout_t1
);
1560 (void) event_source_disable(client
->timeout_t2
);
1561 (void) event_source_disable(client
->timeout_expire
);
1566 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1569 assert(client
->request_sent
<= time_now
);
1571 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1572 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1573 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1574 /* both T1 and T2 are given */
1575 if (client
->lease
->t1
< client
->lease
->t2
&&
1576 client
->lease
->t2
< client
->lease
->lifetime
) {
1577 /* they are both valid */
1578 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1579 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1582 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1583 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1584 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1585 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1587 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1588 /* only T2 is given, and it is valid */
1589 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1590 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1591 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1592 if (t2_timeout
<= t1_timeout
) {
1593 /* the computed T1 would be invalid, so discard T2 */
1594 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1595 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1597 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1598 /* only T1 is given, and it is valid */
1599 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1600 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1601 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1602 if (t2_timeout
<= t1_timeout
) {
1603 /* the computed T2 would be invalid, so discard T1 */
1604 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1605 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1608 /* fall back to the default timeouts */
1609 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1610 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1611 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1612 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1615 /* arm lifetime timeout */
1616 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1617 clock_boottime_or_monotonic(),
1618 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1619 client_timeout_expire
, client
,
1620 client
->event_priority
, "dhcp4-lifetime", true);
1624 log_dhcp_client(client
, "lease expires in %s",
1625 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1627 /* don't arm earlier timeouts if this has already expired */
1628 if (lifetime_timeout
<= time_now
)
1631 /* arm T2 timeout */
1632 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1633 clock_boottime_or_monotonic(),
1634 t2_timeout
, 10 * USEC_PER_MSEC
,
1635 client_timeout_t2
, client
,
1636 client
->event_priority
, "dhcp4-t2-timeout", true);
1640 log_dhcp_client(client
, "T2 expires in %s",
1641 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1643 /* don't arm earlier timeout if this has already expired */
1644 if (t2_timeout
<= time_now
)
1647 /* arm T1 timeout */
1648 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1649 clock_boottime_or_monotonic(),
1650 t1_timeout
, 10 * USEC_PER_MSEC
,
1651 client_timeout_t1
, client
,
1652 client
->event_priority
, "dhcp4-t1-timer", true);
1656 log_dhcp_client(client
, "T1 expires in %s",
1657 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1662 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1663 DHCP_CLIENT_DONT_DESTROY(client
);
1664 char time_string
[FORMAT_TIMESPAN_MAX
];
1665 int r
= 0, notify_event
= 0;
1668 assert(client
->event
);
1671 switch (client
->state
) {
1672 case DHCP_STATE_SELECTING
:
1674 r
= client_handle_offer(client
, message
, len
);
1677 client
->state
= DHCP_STATE_REQUESTING
;
1678 client
->attempt
= 0;
1680 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1681 clock_boottime_or_monotonic(),
1683 client_timeout_resend
, client
,
1684 client
->event_priority
, "dhcp4-resend-timer", true);
1687 } else if (r
== -ENOMSG
)
1688 /* invalid message, let's ignore it */
1693 case DHCP_STATE_REBOOTING
:
1694 case DHCP_STATE_REQUESTING
:
1695 case DHCP_STATE_RENEWING
:
1696 case DHCP_STATE_REBINDING
:
1698 r
= client_handle_ack(client
, message
, len
);
1700 client
->start_delay
= 0;
1701 (void) event_source_disable(client
->timeout_resend
);
1702 client
->receive_message
=
1703 sd_event_source_unref(client
->receive_message
);
1704 client
->fd
= asynchronous_close(client
->fd
);
1706 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1707 DHCP_STATE_REBOOTING
))
1708 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1709 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1712 client
->state
= DHCP_STATE_BOUND
;
1713 client
->attempt
= 0;
1715 client
->last_addr
= client
->lease
->address
;
1717 r
= client_set_lease_timeouts(client
);
1719 log_dhcp_client(client
, "could not set lease timeouts");
1723 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1725 log_dhcp_client(client
, "could not bind UDP socket");
1731 client_initialize_io_events(client
, client_receive_message_udp
);
1734 client_notify(client
, notify_event
);
1735 if (client
->state
== DHCP_STATE_STOPPED
)
1739 } else if (r
== -EADDRNOTAVAIL
) {
1740 /* got a NAK, let's restart the client */
1741 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1743 r
= client_initialize(client
);
1747 r
= client_start_delayed(client
);
1751 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1752 client
->start_delay
, USEC_PER_SEC
));
1754 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1755 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1758 } else if (r
== -ENOMSG
)
1759 /* invalid message, let's ignore it */
1764 case DHCP_STATE_BOUND
:
1765 r
= client_handle_forcerenew(client
, message
, len
);
1767 r
= client_timeout_t1(NULL
, 0, client
);
1770 } else if (r
== -ENOMSG
)
1771 /* invalid message, let's ignore it */
1776 case DHCP_STATE_INIT
:
1777 case DHCP_STATE_INIT_REBOOT
:
1781 case DHCP_STATE_STOPPED
:
1788 client_stop(client
, r
);
1793 static int client_receive_message_udp(
1799 sd_dhcp_client
*client
= userdata
;
1800 _cleanup_free_ DHCPMessage
*message
= NULL
;
1801 const uint8_t *expected_chaddr
= NULL
;
1802 uint8_t expected_hlen
= 0;
1803 ssize_t len
, buflen
;
1808 buflen
= next_datagram_size_fd(fd
);
1809 if (buflen
== -ENETDOWN
) {
1810 /* the link is down. Don't return an error or the I/O event
1811 source will be disconnected and we won't be able to receive
1812 packets again when the link comes back. */
1818 message
= malloc0(buflen
);
1822 len
= recv(fd
, message
, buflen
, 0);
1824 /* see comment above for why we shouldn't error out on ENETDOWN. */
1825 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1828 return log_dhcp_client_errno(client
, errno
,
1829 "Could not receive message from UDP socket: %m");
1831 if ((size_t) len
< sizeof(DHCPMessage
)) {
1832 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1836 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1837 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1841 if (message
->op
!= BOOTREPLY
) {
1842 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1846 if (message
->htype
!= client
->arp_type
) {
1847 log_dhcp_client(client
, "Packet type does not match client type");
1851 if (client
->arp_type
== ARPHRD_ETHER
) {
1852 expected_hlen
= ETH_ALEN
;
1853 expected_chaddr
= &client
->mac_addr
[0];
1856 if (message
->hlen
!= expected_hlen
) {
1857 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1861 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1862 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1866 if (client
->state
!= DHCP_STATE_BOUND
&&
1867 be32toh(message
->xid
) != client
->xid
) {
1868 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1869 so ignore the xid in this case */
1870 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1871 be32toh(message
->xid
), client
->xid
);
1875 return client_handle_message(client
, message
, len
);
1878 static int client_receive_message_raw(
1884 sd_dhcp_client
*client
= userdata
;
1885 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1886 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1887 struct iovec iov
= {};
1888 struct msghdr msg
= {
1891 .msg_control
= cmsgbuf
,
1892 .msg_controllen
= sizeof(cmsgbuf
),
1894 struct cmsghdr
*cmsg
;
1895 bool checksum
= true;
1896 ssize_t buflen
, len
;
1902 buflen
= next_datagram_size_fd(fd
);
1903 if (buflen
== -ENETDOWN
)
1908 packet
= malloc0(buflen
);
1912 iov
= IOVEC_MAKE(packet
, buflen
);
1914 len
= recvmsg(fd
, &msg
, 0);
1916 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1919 return log_dhcp_client_errno(client
, errno
,
1920 "Could not receive message from raw socket: %m");
1921 } else if ((size_t)len
< sizeof(DHCPPacket
))
1924 CMSG_FOREACH(cmsg
, &msg
)
1925 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1926 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1927 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1928 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1930 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1934 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1938 len
-= DHCP_IP_UDP_SIZE
;
1940 return client_handle_message(client
, &packet
->dhcp
, len
);
1943 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1944 assert_return(client
, -EINVAL
);
1945 assert_return(client
->fd
>= 0, -EINVAL
);
1947 client
->start_delay
= 0;
1948 client
->attempt
= 1;
1949 client
->state
= DHCP_STATE_RENEWING
;
1951 return client_initialize_time_events(client
);
1954 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1957 assert_return(client
, -EINVAL
);
1959 r
= client_initialize(client
);
1963 /* RFC7844 section 3.3:
1964 SHOULD perform a complete four-way handshake, starting with a
1965 DHCPDISCOVER, to obtain a new address lease. If the client can
1966 ascertain that this is exactly the same network to which it was
1967 previously connected, and if the link-layer address did not change,
1968 the client MAY issue a DHCPREQUEST to try to reclaim the current
1970 if (client
->last_addr
&& !client
->anonymize
)
1971 client
->state
= DHCP_STATE_INIT_REBOOT
;
1973 r
= client_start(client
);
1975 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1980 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1981 assert_return(client
, -EINVAL
);
1982 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1983 assert_return(client
->lease
, -EUNATCH
);
1985 _cleanup_free_ DHCPPacket
*release
= NULL
;
1986 size_t optoffset
, optlen
;
1989 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
1993 /* Fill up release IP and MAC */
1994 release
->dhcp
.ciaddr
= client
->lease
->address
;
1995 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1997 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1998 SD_DHCP_OPTION_END
, 0, NULL
);
2002 r
= dhcp_network_send_udp_socket(client
->fd
,
2003 client
->lease
->server_address
,
2006 sizeof(DHCPMessage
) + optoffset
);
2010 log_dhcp_client(client
, "RELEASE");
2015 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2016 DHCP_CLIENT_DONT_DESTROY(client
);
2018 assert_return(client
, -EINVAL
);
2020 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2021 client
->state
= DHCP_STATE_STOPPED
;
2026 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2029 assert_return(client
, -EINVAL
);
2030 assert_return(!client
->event
, -EBUSY
);
2033 client
->event
= sd_event_ref(event
);
2035 r
= sd_event_default(&client
->event
);
2040 client
->event_priority
= priority
;
2045 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2046 assert_return(client
, -EINVAL
);
2048 client
->event
= sd_event_unref(client
->event
);
2053 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2054 assert_return(client
, NULL
);
2056 return client
->event
;
2059 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2063 log_dhcp_client(client
, "FREE");
2065 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2066 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2067 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2068 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2070 client_initialize(client
);
2072 sd_dhcp_client_detach_event(client
);
2074 sd_dhcp_lease_unref(client
->lease
);
2076 free(client
->req_opts
);
2077 free(client
->hostname
);
2078 free(client
->vendor_class_identifier
);
2079 client
->user_class
= strv_free(client
->user_class
);
2080 ordered_hashmap_free(client
->options
);
2081 return mfree(client
);
2084 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2086 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2087 assert_return(ret
, -EINVAL
);
2089 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2093 *client
= (sd_dhcp_client
) {
2095 .state
= DHCP_STATE_INIT
,
2098 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2099 .port
= DHCP_PORT_CLIENT
,
2100 .anonymize
= !!anonymize
,
2101 .max_attempts
= (uint64_t) -1,
2102 .ip_service_type
= -1,
2104 /* NOTE: this could be moved to a function. */
2106 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2107 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2109 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2110 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2112 if (!client
->req_opts
)
2115 *ret
= TAKE_PTR(client
);