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"
32 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
33 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
35 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
36 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
38 struct sd_dhcp_client
{
44 sd_event_source
*timeout_resend
;
48 union sockaddr_union link
;
49 sd_event_source
*receive_message
;
50 bool request_broadcast
;
52 size_t req_opts_allocated
;
56 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
63 /* 0: Generic (non-LL) (RFC 2132) */
64 uint8_t data
[MAX_CLIENT_ID_LEN
];
67 /* 1: Ethernet Link-Layer (RFC 2132) */
68 uint8_t haddr
[ETH_ALEN
];
71 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
75 /* 255: Node-specific (RFC 4361) */
80 uint8_t data
[MAX_CLIENT_ID_LEN
];
86 char *vendor_class_identifier
;
90 uint32_t fallback_lease_lifetime
;
94 uint64_t max_attempts
;
95 OrderedHashmap
*extra_options
;
96 OrderedHashmap
*vendor_options
;
98 sd_event_source
*timeout_t1
;
99 sd_event_source
*timeout_t2
;
100 sd_event_source
*timeout_expire
;
101 sd_dhcp_client_callback_t callback
;
103 sd_dhcp_lease
*lease
;
108 static const uint8_t default_req_opts
[] = {
109 SD_DHCP_OPTION_SUBNET_MASK
,
110 SD_DHCP_OPTION_ROUTER
,
111 SD_DHCP_OPTION_HOST_NAME
,
112 SD_DHCP_OPTION_DOMAIN_NAME
,
113 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
116 /* RFC7844 section 3:
117 MAY contain the Parameter Request List option.
119 The client intending to protect its privacy SHOULD only request a
120 minimal number of options in the PRL and SHOULD also randomly shuffle
121 the ordering of option codes in the PRL. If this random ordering
122 cannot be implemented, the client MAY order the option codes in the
123 PRL by option code number (lowest to highest).
125 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
126 static const uint8_t default_req_opts_anonymize
[] = {
127 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
128 SD_DHCP_OPTION_ROUTER
, /* 3 */
129 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
130 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
131 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
132 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
133 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
134 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
135 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
136 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
137 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
138 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
139 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
142 static int client_receive_message_raw(
147 static int client_receive_message_udp(
152 static void client_stop(sd_dhcp_client
*client
, int error
);
154 int sd_dhcp_client_set_callback(
155 sd_dhcp_client
*client
,
156 sd_dhcp_client_callback_t cb
,
159 assert_return(client
, -EINVAL
);
161 client
->callback
= cb
;
162 client
->userdata
= userdata
;
167 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
168 assert_return(client
, -EINVAL
);
170 client
->request_broadcast
= !!broadcast
;
175 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
178 assert_return(client
, -EINVAL
);
179 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
183 case SD_DHCP_OPTION_PAD
:
184 case SD_DHCP_OPTION_OVERLOAD
:
185 case SD_DHCP_OPTION_MESSAGE_TYPE
:
186 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
187 case SD_DHCP_OPTION_END
:
194 for (i
= 0; i
< client
->req_opts_size
; i
++)
195 if (client
->req_opts
[i
] == option
)
198 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
199 client
->req_opts_size
+ 1))
202 client
->req_opts
[client
->req_opts_size
++] = option
;
207 int sd_dhcp_client_set_request_address(
208 sd_dhcp_client
*client
,
209 const struct in_addr
*last_addr
) {
211 assert_return(client
, -EINVAL
);
212 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
215 client
->last_addr
= last_addr
->s_addr
;
217 client
->last_addr
= INADDR_ANY
;
222 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
224 assert_return(client
, -EINVAL
);
225 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
226 assert_return(ifindex
> 0, -EINVAL
);
228 client
->ifindex
= ifindex
;
232 int sd_dhcp_client_set_mac(
233 sd_dhcp_client
*client
,
238 DHCP_CLIENT_DONT_DESTROY(client
);
239 bool need_restart
= false;
242 assert_return(client
, -EINVAL
);
243 assert_return(addr
, -EINVAL
);
244 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
245 assert_return(arp_type
> 0, -EINVAL
);
247 if (arp_type
== ARPHRD_ETHER
)
248 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
249 else if (arp_type
== ARPHRD_INFINIBAND
)
250 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
254 if (client
->mac_addr_len
== addr_len
&&
255 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
258 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
259 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
261 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
264 memcpy(&client
->mac_addr
, addr
, addr_len
);
265 client
->mac_addr_len
= addr_len
;
266 client
->arp_type
= arp_type
;
268 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
269 r
= sd_dhcp_client_start(client
);
271 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
277 int sd_dhcp_client_get_client_id(
278 sd_dhcp_client
*client
,
280 const uint8_t **data
,
283 assert_return(client
, -EINVAL
);
284 assert_return(type
, -EINVAL
);
285 assert_return(data
, -EINVAL
);
286 assert_return(data_len
, -EINVAL
);
291 if (client
->client_id_len
) {
292 *type
= client
->client_id
.type
;
293 *data
= client
->client_id
.raw
.data
;
294 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
300 int sd_dhcp_client_set_client_id(
301 sd_dhcp_client
*client
,
306 DHCP_CLIENT_DONT_DESTROY(client
);
307 bool need_restart
= false;
310 assert_return(client
, -EINVAL
);
311 assert_return(data
, -EINVAL
);
312 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
314 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
315 client
->client_id
.type
== type
&&
316 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
319 /* For hardware types, log debug message about unexpected data length.
321 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
322 * last last 8 bytes of the address are stable and suitable to put into
323 * the client-id. The caller is advised to account for that. */
324 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
325 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
326 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
327 "unexpected address length %zu",
330 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
331 log_dhcp_client(client
, "Changing client ID on running DHCP "
332 "client, restarting");
334 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
337 client
->client_id
.type
= type
;
338 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
339 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
341 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
342 r
= sd_dhcp_client_start(client
);
344 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
351 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
352 * without further modification. Otherwise, if duid_type is supported, DUID
353 * is set based on that type. Otherwise, an error is returned.
355 static int dhcp_client_set_iaid_duid_internal(
356 sd_dhcp_client
*client
,
365 DHCP_CLIENT_DONT_DESTROY(client
);
369 assert_return(client
, -EINVAL
);
370 assert_return(duid_len
== 0 || duid
, -EINVAL
);
373 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
375 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
378 zero(client
->client_id
);
379 client
->client_id
.type
= 255;
383 client
->client_id
.ns
.iaid
= htobe32(iaid
);
385 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
386 client
->mac_addr_len
,
388 &client
->client_id
.ns
.iaid
);
390 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
395 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
396 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
397 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
401 if (client
->mac_addr_len
== 0)
402 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
404 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
406 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
409 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
411 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
414 if (client
->mac_addr_len
== 0)
415 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
417 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
419 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
422 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
424 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
427 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
430 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
431 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
433 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
434 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
435 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
436 r
= sd_dhcp_client_start(client
);
438 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
444 int sd_dhcp_client_set_iaid_duid(
445 sd_dhcp_client
*client
,
451 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
454 int sd_dhcp_client_set_iaid_duid_llt(
455 sd_dhcp_client
*client
,
459 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
462 int sd_dhcp_client_set_duid(
463 sd_dhcp_client
*client
,
467 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
470 int sd_dhcp_client_set_duid_llt(
471 sd_dhcp_client
*client
,
473 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
476 int sd_dhcp_client_set_hostname(
477 sd_dhcp_client
*client
,
478 const char *hostname
) {
480 assert_return(client
, -EINVAL
);
482 /* Make sure hostnames qualify as DNS and as Linux hostnames */
484 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
487 return free_and_strdup(&client
->hostname
, hostname
);
490 int sd_dhcp_client_set_vendor_class_identifier(
491 sd_dhcp_client
*client
,
494 assert_return(client
, -EINVAL
);
496 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
499 int sd_dhcp_client_set_mud_url(
500 sd_dhcp_client
*client
,
501 const char *mudurl
) {
503 assert_return(client
, -EINVAL
);
504 assert_return(mudurl
, -EINVAL
);
505 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
506 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
508 return free_and_strdup(&client
->mudurl
, mudurl
);
511 int sd_dhcp_client_set_user_class(
512 sd_dhcp_client
*client
,
513 const char* const* user_class
) {
515 _cleanup_strv_free_
char **s
= NULL
;
518 STRV_FOREACH(p
, (char **) user_class
)
519 if (strlen(*p
) > 255)
520 return -ENAMETOOLONG
;
522 s
= strv_copy((char **) user_class
);
526 client
->user_class
= TAKE_PTR(s
);
531 int sd_dhcp_client_set_client_port(
532 sd_dhcp_client
*client
,
535 assert_return(client
, -EINVAL
);
542 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
543 assert_return(client
, -EINVAL
);
544 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
551 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
552 assert_return(client
, -EINVAL
);
554 client
->max_attempts
= max_attempts
;
559 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
562 assert_return(client
, -EINVAL
);
563 assert_return(v
, -EINVAL
);
565 r
= ordered_hashmap_ensure_allocated(&client
->extra_options
, &dhcp_option_hash_ops
);
569 r
= ordered_hashmap_put(client
->extra_options
, UINT_TO_PTR(v
->option
), v
);
573 sd_dhcp_option_ref(v
);
577 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
580 assert_return(client
, -EINVAL
);
581 assert_return(v
, -EINVAL
);
583 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
587 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
591 sd_dhcp_option_ref(v
);
596 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
597 assert_return(client
, -EINVAL
);
599 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
600 return -EADDRNOTAVAIL
;
603 *ret
= client
->lease
;
608 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
609 assert_return(client
, -EINVAL
);
611 client
->ip_service_type
= type
;
616 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint32_t fallback_lease_lifetime
) {
617 assert_return(client
, -EINVAL
);
618 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
620 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
625 static int client_notify(sd_dhcp_client
*client
, int event
) {
628 if (client
->callback
)
629 return client
->callback(client
, event
, client
->userdata
);
634 static int client_initialize(sd_dhcp_client
*client
) {
635 assert_return(client
, -EINVAL
);
637 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
639 client
->fd
= asynchronous_close(client
->fd
);
641 (void) event_source_disable(client
->timeout_resend
);
642 (void) event_source_disable(client
->timeout_t1
);
643 (void) event_source_disable(client
->timeout_t2
);
644 (void) event_source_disable(client
->timeout_expire
);
648 client
->state
= DHCP_STATE_INIT
;
651 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
656 static void client_stop(sd_dhcp_client
*client
, int error
) {
660 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
661 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
662 log_dhcp_client(client
, "STOPPED");
664 log_dhcp_client(client
, "STOPPED: Unknown event");
666 client_notify(client
, error
);
668 client_initialize(client
);
671 static int client_message_init(
672 sd_dhcp_client
*client
,
676 size_t *_optoffset
) {
678 _cleanup_free_ DHCPPacket
*packet
= NULL
;
679 size_t optlen
, optoffset
, size
;
686 assert(client
->start_time
);
690 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
692 optlen
= DHCP_MIN_OPTIONS_SIZE
;
693 size
= sizeof(DHCPPacket
) + optlen
;
695 packet
= malloc0(size
);
699 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
700 client
->arp_type
, optlen
, &optoffset
);
704 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
705 refuse to issue an DHCP lease if 'secs' is set to zero */
706 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
709 assert(time_now
>= client
->start_time
);
711 /* seconds between sending first and last DISCOVER
712 * must always be strictly positive to deal with broken servers */
713 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
714 packet
->dhcp
.secs
= htobe16(secs
);
716 /* RFC2132 section 4.1
717 A client that cannot receive unicast IP datagrams until its protocol
718 software has been configured with an IP address SHOULD set the
719 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
720 DHCPREQUEST messages that client sends. The BROADCAST bit will
721 provide a hint to the DHCP server and BOOTP relay agent to broadcast
722 any messages to the client on the client's subnet.
724 Note: some interfaces needs this to be enabled, but some networks
725 needs this to be disabled as broadcasts are filteretd, so this
726 needs to be configurable */
727 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
728 packet
->dhcp
.flags
= htobe16(0x8000);
730 /* RFC2132 section 4.1.1:
731 The client MUST include its hardware address in the ’chaddr’ field, if
732 necessary for delivery of DHCP reply messages. Non-Ethernet
733 interfaces will leave 'chaddr' empty and use the client identifier
734 instead (eg, RFC 4390 section 2.1).
736 if (client
->arp_type
== ARPHRD_ETHER
)
737 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
739 /* If no client identifier exists, construct an RFC 4361-compliant one */
740 if (client
->client_id_len
== 0) {
743 client
->client_id
.type
= 255;
745 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
746 true, &client
->client_id
.ns
.iaid
);
750 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
754 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
757 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
758 Identifier option is not set */
759 if (client
->client_id_len
) {
760 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
761 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
762 client
->client_id_len
,
768 /* RFC2131 section 3.5:
769 in its initial DHCPDISCOVER or DHCPREQUEST message, a
770 client may provide the server with a list of specific
771 parameters the client is interested in. If the client
772 includes a list of parameters in a DHCPDISCOVER message,
773 it MUST include that list in any subsequent DHCPREQUEST
777 /* RFC7844 section 3:
778 MAY contain the Parameter Request List option. */
779 /* NOTE: in case that there would be an option to do not send
780 * any PRL at all, the size should be checked before sending */
781 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
782 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
783 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
784 client
->req_opts_size
, client
->req_opts
);
789 /* RFC2131 section 3.5:
790 The client SHOULD include the ’maximum DHCP message size’ option to
791 let the server know how large the server may make its DHCP messages.
793 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
794 than the defined default size unless the Maximum Message Size option
797 RFC3442 "Requirements to Avoid Sizing Constraints":
798 Because a full routing table can be quite large, the standard 576
799 octet maximum size for a DHCP message may be too short to contain
800 some legitimate Classless Static Route options. Because of this,
801 clients implementing the Classless Static Route option SHOULD send a
802 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
803 stack is capable of receiving larger IP datagrams. In this case, the
804 client SHOULD set the value of this option to at least the MTU of the
805 interface that the client is configuring. The client MAY set the
806 value of this option higher, up to the size of the largest UDP packet
807 it is prepared to accept. (Note that the value specified in the
808 Maximum DHCP Message Size option is the total maximum packet size,
809 including IP and UDP headers.)
811 /* RFC7844 section 3:
812 SHOULD NOT contain any other option. */
813 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
814 max_size
= htobe16(size
);
815 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
816 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
823 *_optoffset
= optoffset
;
824 *ret
= TAKE_PTR(packet
);
829 static int client_append_fqdn_option(
830 DHCPMessage
*message
,
835 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
838 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
839 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
840 buffer
[1] = 0; /* RCODE1 (deprecated) */
841 buffer
[2] = 0; /* RCODE2 (deprecated) */
843 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
845 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
846 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
851 static int dhcp_client_send_raw(
852 sd_dhcp_client
*client
,
856 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
857 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
859 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
863 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
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(&packet
->dhcp
, optlen
, optoffset
, 0,
880 SD_DHCP_OPTION_HOST_NAME
,
881 strlen(client
->hostname
), client
->hostname
);
883 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
889 if (client
->vendor_class_identifier
) {
890 r
= dhcp_option_append(&packet
->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
->mudurl
) {
899 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
900 SD_DHCP_OPTION_MUD_URL
,
901 strlen(client
->mudurl
),
907 if (client
->user_class
) {
908 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
909 SD_DHCP_OPTION_USER_CLASS
,
910 strv_length(client
->user_class
),
916 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
, i
) {
917 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
918 j
->option
, j
->length
, j
->data
);
923 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
924 r
= dhcp_option_append(
925 &packet
->dhcp
, optlen
, optoffset
, 0,
926 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
927 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
936 static int client_send_discover(sd_dhcp_client
*client
) {
937 _cleanup_free_ DHCPPacket
*discover
= NULL
;
938 size_t optoffset
, optlen
;
942 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
944 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
945 &optlen
, &optoffset
);
949 /* the client may suggest values for the network address
950 and lease time in the DHCPDISCOVER message. The client may include
951 the ’requested IP address’ option to suggest that a particular IP
952 address be assigned, and may include the ’IP address lease time’
953 option to suggest the lease time it would like.
955 /* RFC7844 section 3:
956 SHOULD NOT contain any other option. */
957 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
958 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
959 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
960 4, &client
->last_addr
);
965 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
969 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
970 SD_DHCP_OPTION_END
, 0, NULL
);
974 /* We currently ignore:
975 The client SHOULD wait a random time between one and ten seconds to
976 desynchronize the use of DHCP at startup.
978 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
982 log_dhcp_client(client
, "DISCOVER");
987 static int client_send_request(sd_dhcp_client
*client
) {
988 _cleanup_free_ DHCPPacket
*request
= NULL
;
989 size_t optoffset
, optlen
;
994 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
998 switch (client
->state
) {
999 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1000 SELECTING should be REQUESTING)
1003 case DHCP_STATE_REQUESTING
:
1004 /* Client inserts the address of the selected server in ’server
1005 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1006 filled in with the yiaddr value from the chosen DHCPOFFER.
1009 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1010 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1011 4, &client
->lease
->server_address
);
1015 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1016 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1017 4, &client
->lease
->address
);
1023 case DHCP_STATE_INIT_REBOOT
:
1024 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1025 option MUST be filled in with client’s notion of its previously
1026 assigned address. ’ciaddr’ MUST be zero.
1028 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1029 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1030 4, &client
->last_addr
);
1035 case DHCP_STATE_RENEWING
:
1036 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1037 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1038 client’s IP address.
1041 case DHCP_STATE_REBINDING
:
1042 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1043 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1044 client’s IP address.
1046 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1048 request
->dhcp
.ciaddr
= client
->lease
->address
;
1052 case DHCP_STATE_INIT
:
1053 case DHCP_STATE_SELECTING
:
1054 case DHCP_STATE_REBOOTING
:
1055 case DHCP_STATE_BOUND
:
1056 case DHCP_STATE_STOPPED
:
1060 r
= client_append_common_discover_request_options(client
, request
, &optoffset
, optlen
);
1064 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1065 SD_DHCP_OPTION_END
, 0, NULL
);
1069 if (client
->state
== DHCP_STATE_RENEWING
)
1070 r
= dhcp_network_send_udp_socket(client
->fd
,
1071 client
->lease
->server_address
,
1074 sizeof(DHCPMessage
) + optoffset
);
1076 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1080 switch (client
->state
) {
1082 case DHCP_STATE_REQUESTING
:
1083 log_dhcp_client(client
, "REQUEST (requesting)");
1086 case DHCP_STATE_INIT_REBOOT
:
1087 log_dhcp_client(client
, "REQUEST (init-reboot)");
1090 case DHCP_STATE_RENEWING
:
1091 log_dhcp_client(client
, "REQUEST (renewing)");
1094 case DHCP_STATE_REBINDING
:
1095 log_dhcp_client(client
, "REQUEST (rebinding)");
1099 log_dhcp_client(client
, "REQUEST (invalid)");
1106 static int client_start(sd_dhcp_client
*client
);
1108 static int client_timeout_resend(
1113 sd_dhcp_client
*client
= userdata
;
1114 DHCP_CLIENT_DONT_DESTROY(client
);
1115 usec_t next_timeout
= 0;
1122 assert(client
->event
);
1124 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1128 switch (client
->state
) {
1130 case DHCP_STATE_RENEWING
:
1132 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1136 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1140 case DHCP_STATE_REBINDING
:
1142 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1146 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1149 case DHCP_STATE_REBOOTING
:
1150 /* start over as we did not receive a timely ack or nak */
1151 r
= client_initialize(client
);
1155 r
= client_start(client
);
1159 log_dhcp_client(client
, "REBOOTED");
1163 case DHCP_STATE_INIT
:
1164 case DHCP_STATE_INIT_REBOOT
:
1165 case DHCP_STATE_SELECTING
:
1166 case DHCP_STATE_REQUESTING
:
1167 case DHCP_STATE_BOUND
:
1169 if (client
->attempt
< client
->max_attempts
)
1174 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1178 case DHCP_STATE_STOPPED
:
1183 next_timeout
+= (random_u32() & 0x1fffff);
1185 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1186 clock_boottime_or_monotonic(),
1187 next_timeout
, 10 * USEC_PER_MSEC
,
1188 client_timeout_resend
, client
,
1189 client
->event_priority
, "dhcp4-resend-timer", true);
1193 switch (client
->state
) {
1194 case DHCP_STATE_INIT
:
1195 r
= client_send_discover(client
);
1197 client
->state
= DHCP_STATE_SELECTING
;
1198 client
->attempt
= 0;
1199 } else if (client
->attempt
>= client
->max_attempts
)
1204 case DHCP_STATE_SELECTING
:
1205 r
= client_send_discover(client
);
1206 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1211 case DHCP_STATE_INIT_REBOOT
:
1212 case DHCP_STATE_REQUESTING
:
1213 case DHCP_STATE_RENEWING
:
1214 case DHCP_STATE_REBINDING
:
1215 r
= client_send_request(client
);
1216 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1219 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1220 client
->state
= DHCP_STATE_REBOOTING
;
1222 client
->request_sent
= time_now
;
1226 case DHCP_STATE_REBOOTING
:
1227 case DHCP_STATE_BOUND
:
1231 case DHCP_STATE_STOPPED
:
1239 client_stop(client
, r
);
1241 /* Errors were dealt with when stopping the client, don't spill
1242 errors into the event loop handler */
1246 static int client_initialize_io_events(
1247 sd_dhcp_client
*client
,
1248 sd_event_io_handler_t io_callback
) {
1253 assert(client
->event
);
1255 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1256 client
->fd
, EPOLLIN
, io_callback
,
1261 r
= sd_event_source_set_priority(client
->receive_message
,
1262 client
->event_priority
);
1266 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1272 client_stop(client
, r
);
1277 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1282 assert(client
->event
);
1284 if (client
->start_delay
> 0) {
1285 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1286 usec
+= client
->start_delay
;
1289 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1290 clock_boottime_or_monotonic(),
1292 client_timeout_resend
, client
,
1293 client
->event_priority
, "dhcp4-resend-timer", true);
1295 client_stop(client
, r
);
1301 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1302 client_initialize_io_events(client
, io_callback
);
1303 client_initialize_time_events(client
);
1308 static int client_start_delayed(sd_dhcp_client
*client
) {
1311 assert_return(client
, -EINVAL
);
1312 assert_return(client
->event
, -EINVAL
);
1313 assert_return(client
->ifindex
> 0, -EINVAL
);
1314 assert_return(client
->fd
< 0, -EBUSY
);
1315 assert_return(client
->xid
== 0, -EINVAL
);
1316 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1318 client
->xid
= random_u32();
1320 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1321 client
->xid
, client
->mac_addr
,
1322 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1324 client_stop(client
, r
);
1329 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1330 client
->start_time
= now(clock_boottime_or_monotonic());
1332 return client_initialize_events(client
, client_receive_message_raw
);
1335 static int client_start(sd_dhcp_client
*client
) {
1336 client
->start_delay
= 0;
1337 return client_start_delayed(client
);
1340 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1341 sd_dhcp_client
*client
= userdata
;
1342 DHCP_CLIENT_DONT_DESTROY(client
);
1344 log_dhcp_client(client
, "EXPIRED");
1346 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1348 /* lease was lost, start over if not freed or stopped in callback */
1349 if (client
->state
!= DHCP_STATE_STOPPED
) {
1350 client_initialize(client
);
1351 client_start(client
);
1357 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1358 sd_dhcp_client
*client
= userdata
;
1359 DHCP_CLIENT_DONT_DESTROY(client
);
1364 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1365 client
->fd
= asynchronous_close(client
->fd
);
1367 client
->state
= DHCP_STATE_REBINDING
;
1368 client
->attempt
= 0;
1370 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1371 client
->xid
, client
->mac_addr
,
1372 client
->mac_addr_len
, client
->arp_type
,
1375 client_stop(client
, r
);
1380 return client_initialize_events(client
, client_receive_message_raw
);
1383 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1384 sd_dhcp_client
*client
= userdata
;
1385 DHCP_CLIENT_DONT_DESTROY(client
);
1387 client
->state
= DHCP_STATE_RENEWING
;
1388 client
->attempt
= 0;
1390 return client_initialize_time_events(client
);
1393 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1394 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1397 r
= dhcp_lease_new(&lease
);
1401 if (client
->client_id_len
) {
1402 r
= dhcp_lease_set_client_id(lease
,
1403 (uint8_t *) &client
->client_id
,
1404 client
->client_id_len
);
1409 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1410 if (r
!= DHCP_OFFER
) {
1411 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1415 lease
->next_server
= offer
->siaddr
;
1416 lease
->address
= offer
->yiaddr
;
1418 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1419 lease
->lifetime
= client
->fallback_lease_lifetime
;
1421 if (lease
->address
== 0 ||
1422 lease
->server_address
== 0 ||
1423 lease
->lifetime
== 0) {
1424 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1428 if (!lease
->have_subnet_mask
) {
1429 r
= dhcp_lease_set_default_subnet_mask(lease
);
1431 log_dhcp_client(client
,
1432 "received lease lacks subnet mask, "
1433 "and a fallback one cannot be generated, ignoring");
1438 sd_dhcp_lease_unref(client
->lease
);
1439 client
->lease
= TAKE_PTR(lease
);
1441 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1444 log_dhcp_client(client
, "OFFER");
1449 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1452 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1453 if (r
!= DHCP_FORCERENEW
)
1456 log_dhcp_client(client
, "FORCERENEW");
1461 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1462 if (a
->address
!= b
->address
)
1465 if (a
->subnet_mask
!= b
->subnet_mask
)
1468 if (a
->router_size
!= b
->router_size
)
1471 for (size_t i
= 0; i
< a
->router_size
; i
++)
1472 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1478 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1479 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1480 _cleanup_free_
char *error_message
= NULL
;
1483 r
= dhcp_lease_new(&lease
);
1487 if (client
->client_id_len
) {
1488 r
= dhcp_lease_set_client_id(lease
,
1489 (uint8_t *) &client
->client_id
,
1490 client
->client_id_len
);
1495 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1496 if (r
== DHCP_NAK
) {
1497 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1498 return -EADDRNOTAVAIL
;
1501 if (r
!= DHCP_ACK
) {
1502 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1506 lease
->next_server
= ack
->siaddr
;
1508 lease
->address
= ack
->yiaddr
;
1510 if (lease
->address
== INADDR_ANY
||
1511 lease
->server_address
== INADDR_ANY
||
1512 lease
->lifetime
== 0) {
1513 log_dhcp_client(client
, "received lease lacks address, server "
1514 "address or lease lifetime, ignoring");
1518 if (lease
->subnet_mask
== INADDR_ANY
) {
1519 r
= dhcp_lease_set_default_subnet_mask(lease
);
1521 log_dhcp_client(client
,
1522 "received lease lacks subnet mask, "
1523 "and a fallback one cannot be generated, ignoring");
1528 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1529 if (client
->lease
) {
1530 if (lease_equal(client
->lease
, lease
))
1531 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1533 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1535 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1538 client
->lease
= TAKE_PTR(lease
);
1540 log_dhcp_client(client
, "ACK");
1545 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1547 assert(client
->request_sent
);
1548 assert(lifetime
> 0);
1555 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1556 + (random_u32() & 0x1fffff);
1559 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1561 uint64_t lifetime_timeout
;
1562 uint64_t t2_timeout
;
1563 uint64_t t1_timeout
;
1564 char time_string
[FORMAT_TIMESPAN_MAX
];
1568 assert(client
->event
);
1569 assert(client
->lease
);
1570 assert(client
->lease
->lifetime
);
1572 /* don't set timers for infinite leases */
1573 if (client
->lease
->lifetime
== 0xffffffff) {
1574 (void) event_source_disable(client
->timeout_t1
);
1575 (void) event_source_disable(client
->timeout_t2
);
1576 (void) event_source_disable(client
->timeout_expire
);
1581 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1584 assert(client
->request_sent
<= time_now
);
1586 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1587 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1588 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1589 /* both T1 and T2 are given */
1590 if (client
->lease
->t1
< client
->lease
->t2
&&
1591 client
->lease
->t2
< client
->lease
->lifetime
) {
1592 /* they are both valid */
1593 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1594 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1597 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1598 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1599 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1600 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1602 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1603 /* only T2 is given, and it is valid */
1604 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1605 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1606 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1607 if (t2_timeout
<= t1_timeout
) {
1608 /* the computed T1 would be invalid, so discard T2 */
1609 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1610 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1612 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1613 /* only T1 is given, and it is valid */
1614 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1615 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1616 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1617 if (t2_timeout
<= t1_timeout
) {
1618 /* the computed T2 would be invalid, so discard T1 */
1619 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1620 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1623 /* fall back to the default timeouts */
1624 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1625 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1626 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1627 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1630 /* arm lifetime timeout */
1631 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1632 clock_boottime_or_monotonic(),
1633 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1634 client_timeout_expire
, client
,
1635 client
->event_priority
, "dhcp4-lifetime", true);
1639 log_dhcp_client(client
, "lease expires in %s",
1640 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1642 /* don't arm earlier timeouts if this has already expired */
1643 if (lifetime_timeout
<= time_now
)
1646 /* arm T2 timeout */
1647 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1648 clock_boottime_or_monotonic(),
1649 t2_timeout
, 10 * USEC_PER_MSEC
,
1650 client_timeout_t2
, client
,
1651 client
->event_priority
, "dhcp4-t2-timeout", true);
1655 log_dhcp_client(client
, "T2 expires in %s",
1656 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1658 /* don't arm earlier timeout if this has already expired */
1659 if (t2_timeout
<= time_now
)
1662 /* arm T1 timeout */
1663 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1664 clock_boottime_or_monotonic(),
1665 t1_timeout
, 10 * USEC_PER_MSEC
,
1666 client_timeout_t1
, client
,
1667 client
->event_priority
, "dhcp4-t1-timer", true);
1671 log_dhcp_client(client
, "T1 expires in %s",
1672 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1677 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1678 DHCP_CLIENT_DONT_DESTROY(client
);
1679 char time_string
[FORMAT_TIMESPAN_MAX
];
1680 int r
= 0, notify_event
= 0;
1683 assert(client
->event
);
1686 switch (client
->state
) {
1687 case DHCP_STATE_SELECTING
:
1689 r
= client_handle_offer(client
, message
, len
);
1692 client
->state
= DHCP_STATE_REQUESTING
;
1693 client
->attempt
= 0;
1695 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1696 clock_boottime_or_monotonic(),
1698 client_timeout_resend
, client
,
1699 client
->event_priority
, "dhcp4-resend-timer", true);
1702 } else if (r
== -ENOMSG
)
1703 /* invalid message, let's ignore it */
1708 case DHCP_STATE_REBOOTING
:
1709 case DHCP_STATE_REQUESTING
:
1710 case DHCP_STATE_RENEWING
:
1711 case DHCP_STATE_REBINDING
:
1713 r
= client_handle_ack(client
, message
, len
);
1715 client
->start_delay
= 0;
1716 (void) event_source_disable(client
->timeout_resend
);
1717 client
->receive_message
=
1718 sd_event_source_unref(client
->receive_message
);
1719 client
->fd
= asynchronous_close(client
->fd
);
1721 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1722 DHCP_STATE_REBOOTING
))
1723 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1724 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1727 client
->state
= DHCP_STATE_BOUND
;
1728 client
->attempt
= 0;
1730 client
->last_addr
= client
->lease
->address
;
1732 r
= client_set_lease_timeouts(client
);
1734 log_dhcp_client(client
, "could not set lease timeouts");
1738 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1740 log_dhcp_client(client
, "could not bind UDP socket");
1746 client_initialize_io_events(client
, client_receive_message_udp
);
1749 client_notify(client
, notify_event
);
1750 if (client
->state
== DHCP_STATE_STOPPED
)
1754 } else if (r
== -EADDRNOTAVAIL
) {
1755 /* got a NAK, let's restart the client */
1756 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1758 r
= client_initialize(client
);
1762 r
= client_start_delayed(client
);
1766 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1767 client
->start_delay
, USEC_PER_SEC
));
1769 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1770 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1773 } else if (r
== -ENOMSG
)
1774 /* invalid message, let's ignore it */
1779 case DHCP_STATE_BOUND
:
1780 r
= client_handle_forcerenew(client
, message
, len
);
1782 r
= client_timeout_t1(NULL
, 0, client
);
1785 } else if (r
== -ENOMSG
)
1786 /* invalid message, let's ignore it */
1791 case DHCP_STATE_INIT
:
1792 case DHCP_STATE_INIT_REBOOT
:
1796 case DHCP_STATE_STOPPED
:
1803 client_stop(client
, r
);
1808 static int client_receive_message_udp(
1814 sd_dhcp_client
*client
= userdata
;
1815 _cleanup_free_ DHCPMessage
*message
= NULL
;
1816 const uint8_t *expected_chaddr
= NULL
;
1817 uint8_t expected_hlen
= 0;
1818 ssize_t len
, buflen
;
1823 buflen
= next_datagram_size_fd(fd
);
1824 if (buflen
== -ENETDOWN
) {
1825 /* the link is down. Don't return an error or the I/O event
1826 source will be disconnected and we won't be able to receive
1827 packets again when the link comes back. */
1833 message
= malloc0(buflen
);
1837 len
= recv(fd
, message
, buflen
, 0);
1839 /* see comment above for why we shouldn't error out on ENETDOWN. */
1840 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1843 return log_dhcp_client_errno(client
, errno
,
1844 "Could not receive message from UDP socket: %m");
1846 if ((size_t) len
< sizeof(DHCPMessage
)) {
1847 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1851 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1852 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1856 if (message
->op
!= BOOTREPLY
) {
1857 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1861 if (message
->htype
!= client
->arp_type
) {
1862 log_dhcp_client(client
, "Packet type does not match client type");
1866 if (client
->arp_type
== ARPHRD_ETHER
) {
1867 expected_hlen
= ETH_ALEN
;
1868 expected_chaddr
= &client
->mac_addr
[0];
1871 if (message
->hlen
!= expected_hlen
) {
1872 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1876 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1877 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1881 if (client
->state
!= DHCP_STATE_BOUND
&&
1882 be32toh(message
->xid
) != client
->xid
) {
1883 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1884 so ignore the xid in this case */
1885 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1886 be32toh(message
->xid
), client
->xid
);
1890 return client_handle_message(client
, message
, len
);
1893 static int client_receive_message_raw(
1899 sd_dhcp_client
*client
= userdata
;
1900 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1901 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
;
1902 struct iovec iov
= {};
1903 struct msghdr msg
= {
1906 .msg_control
= &control
,
1907 .msg_controllen
= sizeof(control
),
1909 struct cmsghdr
*cmsg
;
1910 bool checksum
= true;
1911 ssize_t buflen
, len
;
1917 buflen
= next_datagram_size_fd(fd
);
1918 if (buflen
== -ENETDOWN
)
1923 packet
= malloc0(buflen
);
1927 iov
= IOVEC_MAKE(packet
, buflen
);
1929 len
= recvmsg_safe(fd
, &msg
, 0);
1930 if (IN_SET(len
, -EAGAIN
, -EINTR
, -ENETDOWN
))
1933 return log_dhcp_client_errno(client
, len
,
1934 "Could not receive message from raw socket: %m");
1936 if ((size_t) len
< sizeof(DHCPPacket
))
1939 cmsg
= cmsg_find(&msg
, SOL_PACKET
, PACKET_AUXDATA
, CMSG_LEN(sizeof(struct tpacket_auxdata
)));
1941 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*) CMSG_DATA(cmsg
);
1942 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1945 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1949 len
-= DHCP_IP_UDP_SIZE
;
1951 return client_handle_message(client
, &packet
->dhcp
, len
);
1954 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1955 assert_return(client
, -EINVAL
);
1956 assert_return(client
->fd
>= 0, -EINVAL
);
1958 client
->start_delay
= 0;
1959 client
->attempt
= 1;
1960 client
->state
= DHCP_STATE_RENEWING
;
1962 return client_initialize_time_events(client
);
1965 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1968 assert_return(client
, -EINVAL
);
1970 r
= client_initialize(client
);
1974 /* RFC7844 section 3.3:
1975 SHOULD perform a complete four-way handshake, starting with a
1976 DHCPDISCOVER, to obtain a new address lease. If the client can
1977 ascertain that this is exactly the same network to which it was
1978 previously connected, and if the link-layer address did not change,
1979 the client MAY issue a DHCPREQUEST to try to reclaim the current
1981 if (client
->last_addr
&& !client
->anonymize
)
1982 client
->state
= DHCP_STATE_INIT_REBOOT
;
1984 r
= client_start(client
);
1986 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1991 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1992 assert_return(client
, -EINVAL
);
1993 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1994 assert_return(client
->lease
, -EUNATCH
);
1996 _cleanup_free_ DHCPPacket
*release
= NULL
;
1997 size_t optoffset
, optlen
;
2000 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2004 /* Fill up release IP and MAC */
2005 release
->dhcp
.ciaddr
= client
->lease
->address
;
2006 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2008 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2009 SD_DHCP_OPTION_END
, 0, NULL
);
2013 r
= dhcp_network_send_udp_socket(client
->fd
,
2014 client
->lease
->server_address
,
2017 sizeof(DHCPMessage
) + optoffset
);
2021 log_dhcp_client(client
, "RELEASE");
2026 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2027 assert_return(client
, -EINVAL
);
2028 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2029 assert_return(client
->lease
, -EUNATCH
);
2031 _cleanup_free_ DHCPPacket
*release
= NULL
;
2032 size_t optoffset
, optlen
;
2035 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2039 release
->dhcp
.ciaddr
= client
->lease
->address
;
2040 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2042 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2043 SD_DHCP_OPTION_END
, 0, NULL
);
2047 r
= dhcp_network_send_udp_socket(client
->fd
,
2048 client
->lease
->server_address
,
2051 sizeof(DHCPMessage
) + optoffset
);
2055 log_dhcp_client(client
, "DECLINE");
2057 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2059 if (client
->state
!= DHCP_STATE_STOPPED
) {
2060 r
= sd_dhcp_client_start(client
);
2068 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2069 DHCP_CLIENT_DONT_DESTROY(client
);
2071 assert_return(client
, -EINVAL
);
2073 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2074 client
->state
= DHCP_STATE_STOPPED
;
2079 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2082 assert_return(client
, -EINVAL
);
2083 assert_return(!client
->event
, -EBUSY
);
2086 client
->event
= sd_event_ref(event
);
2088 r
= sd_event_default(&client
->event
);
2093 client
->event_priority
= priority
;
2098 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2099 assert_return(client
, -EINVAL
);
2101 client
->event
= sd_event_unref(client
->event
);
2106 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2107 assert_return(client
, NULL
);
2109 return client
->event
;
2112 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2116 log_dhcp_client(client
, "FREE");
2118 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2119 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2120 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2121 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2123 client_initialize(client
);
2125 sd_dhcp_client_detach_event(client
);
2127 sd_dhcp_lease_unref(client
->lease
);
2129 free(client
->req_opts
);
2130 free(client
->hostname
);
2131 free(client
->vendor_class_identifier
);
2132 free(client
->mudurl
);
2133 client
->user_class
= strv_free(client
->user_class
);
2134 ordered_hashmap_free(client
->extra_options
);
2135 ordered_hashmap_free(client
->vendor_options
);
2136 return mfree(client
);
2139 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2141 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2142 assert_return(ret
, -EINVAL
);
2144 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2148 *client
= (sd_dhcp_client
) {
2150 .state
= DHCP_STATE_INIT
,
2153 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2154 .port
= DHCP_PORT_CLIENT
,
2155 .anonymize
= !!anonymize
,
2156 .max_attempts
= (uint64_t) -1,
2157 .ip_service_type
= -1,
2159 /* NOTE: this could be moved to a function. */
2161 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2162 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2164 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2165 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2167 if (!client
->req_opts
)
2170 *ret
= TAKE_PTR(client
);