1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
7 #include <net/ethernet.h>
8 #include <net/if_arp.h>
11 #include <sys/ioctl.h>
12 #include <linux/if_infiniband.h>
14 #include "sd-dhcp-client.h"
16 #include "alloc-util.h"
18 #include "dhcp-identifier.h"
19 #include "dhcp-internal.h"
20 #include "dhcp-lease-internal.h"
21 #include "dhcp-protocol.h"
22 #include "dns-domain.h"
23 #include "event-util.h"
24 #include "hostname-util.h"
26 #include "memory-util.h"
27 #include "random-util.h"
28 #include "string-util.h"
31 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
32 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
34 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
35 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
37 struct sd_dhcp_client
{
43 sd_event_source
*timeout_resend
;
47 union sockaddr_union link
;
48 sd_event_source
*receive_message
;
49 bool request_broadcast
;
51 size_t req_opts_allocated
;
55 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
62 /* 0: Generic (non-LL) (RFC 2132) */
63 uint8_t data
[MAX_CLIENT_ID_LEN
];
66 /* 1: Ethernet Link-Layer (RFC 2132) */
67 uint8_t haddr
[ETH_ALEN
];
70 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
74 /* 255: Node-specific (RFC 4361) */
79 uint8_t data
[MAX_CLIENT_ID_LEN
];
85 char *vendor_class_identifier
;
91 uint64_t max_attempts
;
92 OrderedHashmap
*options
;
94 sd_event_source
*timeout_t1
;
95 sd_event_source
*timeout_t2
;
96 sd_event_source
*timeout_expire
;
97 sd_dhcp_client_callback_t callback
;
104 static const uint8_t default_req_opts
[] = {
105 SD_DHCP_OPTION_SUBNET_MASK
,
106 SD_DHCP_OPTION_ROUTER
,
107 SD_DHCP_OPTION_HOST_NAME
,
108 SD_DHCP_OPTION_DOMAIN_NAME
,
109 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
112 /* RFC7844 section 3:
113 MAY contain the Parameter Request List option.
115 The client intending to protect its privacy SHOULD only request a
116 minimal number of options in the PRL and SHOULD also randomly shuffle
117 the ordering of option codes in the PRL. If this random ordering
118 cannot be implemented, the client MAY order the option codes in the
119 PRL by option code number (lowest to highest).
121 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
122 static const uint8_t default_req_opts_anonymize
[] = {
123 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
124 SD_DHCP_OPTION_ROUTER
, /* 3 */
125 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
126 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
127 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
128 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
129 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
130 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
131 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
132 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
133 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
134 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
135 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
138 static int client_receive_message_raw(
143 static int client_receive_message_udp(
148 static void client_stop(sd_dhcp_client
*client
, int error
);
150 int sd_dhcp_client_set_callback(
151 sd_dhcp_client
*client
,
152 sd_dhcp_client_callback_t cb
,
155 assert_return(client
, -EINVAL
);
157 client
->callback
= cb
;
158 client
->userdata
= userdata
;
163 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
164 assert_return(client
, -EINVAL
);
166 client
->request_broadcast
= !!broadcast
;
171 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
174 assert_return(client
, -EINVAL
);
175 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
179 case SD_DHCP_OPTION_PAD
:
180 case SD_DHCP_OPTION_OVERLOAD
:
181 case SD_DHCP_OPTION_MESSAGE_TYPE
:
182 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
183 case SD_DHCP_OPTION_END
:
190 for (i
= 0; i
< client
->req_opts_size
; i
++)
191 if (client
->req_opts
[i
] == option
)
194 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
195 client
->req_opts_size
+ 1))
198 client
->req_opts
[client
->req_opts_size
++] = option
;
203 int sd_dhcp_client_set_request_address(
204 sd_dhcp_client
*client
,
205 const struct in_addr
*last_addr
) {
207 assert_return(client
, -EINVAL
);
208 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
211 client
->last_addr
= last_addr
->s_addr
;
213 client
->last_addr
= INADDR_ANY
;
218 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
220 assert_return(client
, -EINVAL
);
221 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
222 assert_return(ifindex
> 0, -EINVAL
);
224 client
->ifindex
= ifindex
;
228 int sd_dhcp_client_set_mac(
229 sd_dhcp_client
*client
,
234 DHCP_CLIENT_DONT_DESTROY(client
);
235 bool need_restart
= false;
238 assert_return(client
, -EINVAL
);
239 assert_return(addr
, -EINVAL
);
240 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
241 assert_return(arp_type
> 0, -EINVAL
);
243 if (arp_type
== ARPHRD_ETHER
)
244 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
245 else if (arp_type
== ARPHRD_INFINIBAND
)
246 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
250 if (client
->mac_addr_len
== addr_len
&&
251 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
254 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
255 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
257 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
260 memcpy(&client
->mac_addr
, addr
, addr_len
);
261 client
->mac_addr_len
= addr_len
;
262 client
->arp_type
= arp_type
;
264 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
265 r
= sd_dhcp_client_start(client
);
267 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
273 int sd_dhcp_client_get_client_id(
274 sd_dhcp_client
*client
,
276 const uint8_t **data
,
279 assert_return(client
, -EINVAL
);
280 assert_return(type
, -EINVAL
);
281 assert_return(data
, -EINVAL
);
282 assert_return(data_len
, -EINVAL
);
287 if (client
->client_id_len
) {
288 *type
= client
->client_id
.type
;
289 *data
= client
->client_id
.raw
.data
;
290 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
296 int sd_dhcp_client_set_client_id(
297 sd_dhcp_client
*client
,
302 DHCP_CLIENT_DONT_DESTROY(client
);
303 bool need_restart
= false;
306 assert_return(client
, -EINVAL
);
307 assert_return(data
, -EINVAL
);
308 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
310 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
311 client
->client_id
.type
== type
&&
312 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
315 /* For hardware types, log debug message about unexpected data length.
317 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
318 * last last 8 bytes of the address are stable and suitable to put into
319 * the client-id. The caller is advised to account for that. */
320 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
321 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
322 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
323 "unexpected address length %zu",
326 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
327 log_dhcp_client(client
, "Changing client ID on running DHCP "
328 "client, restarting");
330 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
333 client
->client_id
.type
= type
;
334 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
335 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
337 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
338 r
= sd_dhcp_client_start(client
);
340 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
347 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
348 * without further modification. Otherwise, if duid_type is supported, DUID
349 * is set based on that type. Otherwise, an error is returned.
351 static int dhcp_client_set_iaid_duid_internal(
352 sd_dhcp_client
*client
,
361 DHCP_CLIENT_DONT_DESTROY(client
);
365 assert_return(client
, -EINVAL
);
366 assert_return(duid_len
== 0 || duid
, -EINVAL
);
369 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
371 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
374 zero(client
->client_id
);
375 client
->client_id
.type
= 255;
379 client
->client_id
.ns
.iaid
= htobe32(iaid
);
381 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
382 client
->mac_addr_len
,
384 &client
->client_id
.ns
.iaid
);
386 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
391 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
392 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
393 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
397 if (client
->mac_addr_len
== 0)
398 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
400 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
402 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
405 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
407 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
410 if (client
->mac_addr_len
== 0)
411 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
413 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
415 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
418 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
420 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
423 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
426 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
427 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
429 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
430 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
431 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
432 r
= sd_dhcp_client_start(client
);
434 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
440 int sd_dhcp_client_set_iaid_duid(
441 sd_dhcp_client
*client
,
447 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
450 int sd_dhcp_client_set_iaid_duid_llt(
451 sd_dhcp_client
*client
,
455 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
458 int sd_dhcp_client_set_duid(
459 sd_dhcp_client
*client
,
463 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
466 int sd_dhcp_client_set_duid_llt(
467 sd_dhcp_client
*client
,
469 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
472 int sd_dhcp_client_set_hostname(
473 sd_dhcp_client
*client
,
474 const char *hostname
) {
476 assert_return(client
, -EINVAL
);
478 /* Make sure hostnames qualify as DNS and as Linux hostnames */
480 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
483 return free_and_strdup(&client
->hostname
, hostname
);
486 int sd_dhcp_client_set_vendor_class_identifier(
487 sd_dhcp_client
*client
,
490 assert_return(client
, -EINVAL
);
492 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
495 int sd_dhcp_client_set_user_class(
496 sd_dhcp_client
*client
,
497 const char* const* user_class
) {
499 _cleanup_strv_free_
char **s
= NULL
;
502 STRV_FOREACH(p
, (char **) user_class
)
503 if (strlen(*p
) > 255)
504 return -ENAMETOOLONG
;
506 s
= strv_copy((char **) user_class
);
510 client
->user_class
= TAKE_PTR(s
);
515 int sd_dhcp_client_set_client_port(
516 sd_dhcp_client
*client
,
519 assert_return(client
, -EINVAL
);
526 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
527 assert_return(client
, -EINVAL
);
528 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
535 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
536 assert_return(client
, -EINVAL
);
538 client
->max_attempts
= max_attempts
;
543 int sd_dhcp_client_set_dhcp_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
546 assert_return(client
, -EINVAL
);
547 assert_return(v
, -EINVAL
);
549 r
= ordered_hashmap_ensure_allocated(&client
->options
, &dhcp_option_hash_ops
);
553 r
= ordered_hashmap_put(client
->options
, UINT_TO_PTR(v
->option
), v
);
557 sd_dhcp_option_ref(v
);
561 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
562 assert_return(client
, -EINVAL
);
564 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
565 return -EADDRNOTAVAIL
;
568 *ret
= client
->lease
;
573 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
574 assert_return(client
, -EINVAL
);
576 client
->ip_service_type
= type
;
581 static int client_notify(sd_dhcp_client
*client
, int event
) {
584 if (client
->callback
)
585 return client
->callback(client
, event
, client
->userdata
);
590 static int client_initialize(sd_dhcp_client
*client
) {
591 assert_return(client
, -EINVAL
);
593 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
595 client
->fd
= asynchronous_close(client
->fd
);
597 (void) event_source_disable(client
->timeout_resend
);
598 (void) event_source_disable(client
->timeout_t1
);
599 (void) event_source_disable(client
->timeout_t2
);
600 (void) event_source_disable(client
->timeout_expire
);
604 client
->state
= DHCP_STATE_INIT
;
607 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
612 static void client_stop(sd_dhcp_client
*client
, int error
) {
616 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
617 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
618 log_dhcp_client(client
, "STOPPED");
620 log_dhcp_client(client
, "STOPPED: Unknown event");
622 client_notify(client
, error
);
624 client_initialize(client
);
627 static int client_message_init(
628 sd_dhcp_client
*client
,
632 size_t *_optoffset
) {
634 _cleanup_free_ DHCPPacket
*packet
= NULL
;
635 size_t optlen
, optoffset
, size
;
642 assert(client
->start_time
);
646 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
648 optlen
= DHCP_MIN_OPTIONS_SIZE
;
649 size
= sizeof(DHCPPacket
) + optlen
;
651 packet
= malloc0(size
);
655 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
656 client
->arp_type
, optlen
, &optoffset
);
660 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
661 refuse to issue an DHCP lease if 'secs' is set to zero */
662 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
665 assert(time_now
>= client
->start_time
);
667 /* seconds between sending first and last DISCOVER
668 * must always be strictly positive to deal with broken servers */
669 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
670 packet
->dhcp
.secs
= htobe16(secs
);
672 /* RFC2132 section 4.1
673 A client that cannot receive unicast IP datagrams until its protocol
674 software has been configured with an IP address SHOULD set the
675 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
676 DHCPREQUEST messages that client sends. The BROADCAST bit will
677 provide a hint to the DHCP server and BOOTP relay agent to broadcast
678 any messages to the client on the client's subnet.
680 Note: some interfaces needs this to be enabled, but some networks
681 needs this to be disabled as broadcasts are filteretd, so this
682 needs to be configurable */
683 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
684 packet
->dhcp
.flags
= htobe16(0x8000);
686 /* RFC2132 section 4.1.1:
687 The client MUST include its hardware address in the ’chaddr’ field, if
688 necessary for delivery of DHCP reply messages. Non-Ethernet
689 interfaces will leave 'chaddr' empty and use the client identifier
690 instead (eg, RFC 4390 section 2.1).
692 if (client
->arp_type
== ARPHRD_ETHER
)
693 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
695 /* If no client identifier exists, construct an RFC 4361-compliant one */
696 if (client
->client_id_len
== 0) {
699 client
->client_id
.type
= 255;
701 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
702 true, &client
->client_id
.ns
.iaid
);
706 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
710 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
713 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
714 Identifier option is not set */
715 if (client
->client_id_len
) {
716 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
717 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
718 client
->client_id_len
,
724 /* RFC2131 section 3.5:
725 in its initial DHCPDISCOVER or DHCPREQUEST message, a
726 client may provide the server with a list of specific
727 parameters the client is interested in. If the client
728 includes a list of parameters in a DHCPDISCOVER message,
729 it MUST include that list in any subsequent DHCPREQUEST
733 /* RFC7844 section 3:
734 MAY contain the Parameter Request List option. */
735 /* NOTE: in case that there would be an option to do not send
736 * any PRL at all, the size should be checked before sending */
737 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
738 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
739 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
740 client
->req_opts_size
, client
->req_opts
);
745 /* RFC2131 section 3.5:
746 The client SHOULD include the ’maximum DHCP message size’ option to
747 let the server know how large the server may make its DHCP messages.
749 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
750 than the defined default size unless the Maximum Message Size option
753 RFC3442 "Requirements to Avoid Sizing Constraints":
754 Because a full routing table can be quite large, the standard 576
755 octet maximum size for a DHCP message may be too short to contain
756 some legitimate Classless Static Route options. Because of this,
757 clients implementing the Classless Static Route option SHOULD send a
758 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
759 stack is capable of receiving larger IP datagrams. In this case, the
760 client SHOULD set the value of this option to at least the MTU of the
761 interface that the client is configuring. The client MAY set the
762 value of this option higher, up to the size of the largest UDP packet
763 it is prepared to accept. (Note that the value specified in the
764 Maximum DHCP Message Size option is the total maximum packet size,
765 including IP and UDP headers.)
767 /* RFC7844 section 3:
768 SHOULD NOT contain any other option. */
769 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
770 max_size
= htobe16(size
);
771 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
772 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
779 *_optoffset
= optoffset
;
780 *ret
= TAKE_PTR(packet
);
785 static int client_append_fqdn_option(
786 DHCPMessage
*message
,
791 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
794 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
795 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
796 buffer
[1] = 0; /* RCODE1 (deprecated) */
797 buffer
[2] = 0; /* RCODE2 (deprecated) */
799 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
801 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
802 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
807 static int dhcp_client_send_raw(
808 sd_dhcp_client
*client
,
812 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
813 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
815 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
819 static int client_send_discover(sd_dhcp_client
*client
) {
820 _cleanup_free_ DHCPPacket
*discover
= NULL
;
821 size_t optoffset
, optlen
;
827 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
829 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
830 &optlen
, &optoffset
);
834 /* the client may suggest values for the network address
835 and lease time in the DHCPDISCOVER message. The client may include
836 the ’requested IP address’ option to suggest that a particular IP
837 address be assigned, and may include the ’IP address lease time’
838 option to suggest the lease time it would like.
840 /* RFC7844 section 3:
841 SHOULD NOT contain any other option. */
842 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
843 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
844 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
845 4, &client
->last_addr
);
850 if (client
->hostname
) {
851 /* According to RFC 4702 "clients that send the Client FQDN option in
852 their messages MUST NOT also send the Host Name option". Just send
853 one of the two depending on the hostname type.
855 if (dns_name_is_single_label(client
->hostname
)) {
856 /* it is unclear from RFC 2131 if client should send hostname in
857 DHCPDISCOVER but dhclient does and so we do as well
859 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
860 SD_DHCP_OPTION_HOST_NAME
,
861 strlen(client
->hostname
), client
->hostname
);
863 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
869 if (client
->vendor_class_identifier
) {
870 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
871 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
872 strlen(client
->vendor_class_identifier
),
873 client
->vendor_class_identifier
);
878 if (client
->user_class
) {
879 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
880 SD_DHCP_OPTION_USER_CLASS
,
881 strv_length(client
->user_class
),
887 ORDERED_HASHMAP_FOREACH(j
, client
->options
, i
) {
888 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
889 j
->option
, j
->length
, j
->data
);
894 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
895 SD_DHCP_OPTION_END
, 0, NULL
);
899 /* We currently ignore:
900 The client SHOULD wait a random time between one and ten seconds to
901 desynchronize the use of DHCP at startup.
903 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
907 log_dhcp_client(client
, "DISCOVER");
912 static int client_send_request(sd_dhcp_client
*client
) {
913 _cleanup_free_ DHCPPacket
*request
= NULL
;
914 size_t optoffset
, optlen
;
919 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
923 switch (client
->state
) {
924 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
925 SELECTING should be REQUESTING)
928 case DHCP_STATE_REQUESTING
:
929 /* Client inserts the address of the selected server in ’server
930 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
931 filled in with the yiaddr value from the chosen DHCPOFFER.
934 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
935 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
936 4, &client
->lease
->server_address
);
940 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
941 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
942 4, &client
->lease
->address
);
948 case DHCP_STATE_INIT_REBOOT
:
949 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
950 option MUST be filled in with client’s notion of its previously
951 assigned address. ’ciaddr’ MUST be zero.
953 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
954 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
955 4, &client
->last_addr
);
960 case DHCP_STATE_RENEWING
:
961 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
962 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
966 case DHCP_STATE_REBINDING
:
967 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
968 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
971 This message MUST be broadcast to the 0xffffffff IP broadcast address.
973 request
->dhcp
.ciaddr
= client
->lease
->address
;
977 case DHCP_STATE_INIT
:
978 case DHCP_STATE_SELECTING
:
979 case DHCP_STATE_REBOOTING
:
980 case DHCP_STATE_BOUND
:
981 case DHCP_STATE_STOPPED
:
985 if (client
->hostname
) {
986 if (dns_name_is_single_label(client
->hostname
))
987 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
988 SD_DHCP_OPTION_HOST_NAME
,
989 strlen(client
->hostname
), client
->hostname
);
991 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
997 if (client
->vendor_class_identifier
) {
998 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
999 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1000 strlen(client
->vendor_class_identifier
),
1001 client
->vendor_class_identifier
);
1006 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1007 SD_DHCP_OPTION_END
, 0, NULL
);
1011 if (client
->state
== DHCP_STATE_RENEWING
)
1012 r
= dhcp_network_send_udp_socket(client
->fd
,
1013 client
->lease
->server_address
,
1016 sizeof(DHCPMessage
) + optoffset
);
1018 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1022 switch (client
->state
) {
1024 case DHCP_STATE_REQUESTING
:
1025 log_dhcp_client(client
, "REQUEST (requesting)");
1028 case DHCP_STATE_INIT_REBOOT
:
1029 log_dhcp_client(client
, "REQUEST (init-reboot)");
1032 case DHCP_STATE_RENEWING
:
1033 log_dhcp_client(client
, "REQUEST (renewing)");
1036 case DHCP_STATE_REBINDING
:
1037 log_dhcp_client(client
, "REQUEST (rebinding)");
1041 log_dhcp_client(client
, "REQUEST (invalid)");
1048 static int client_start(sd_dhcp_client
*client
);
1050 static int client_timeout_resend(
1055 sd_dhcp_client
*client
= userdata
;
1056 DHCP_CLIENT_DONT_DESTROY(client
);
1057 usec_t next_timeout
= 0;
1064 assert(client
->event
);
1066 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1070 switch (client
->state
) {
1072 case DHCP_STATE_RENEWING
:
1074 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1078 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1082 case DHCP_STATE_REBINDING
:
1084 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1088 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1091 case DHCP_STATE_REBOOTING
:
1092 /* start over as we did not receive a timely ack or nak */
1093 r
= client_initialize(client
);
1097 r
= client_start(client
);
1101 log_dhcp_client(client
, "REBOOTED");
1105 case DHCP_STATE_INIT
:
1106 case DHCP_STATE_INIT_REBOOT
:
1107 case DHCP_STATE_SELECTING
:
1108 case DHCP_STATE_REQUESTING
:
1109 case DHCP_STATE_BOUND
:
1111 if (client
->attempt
< client
->max_attempts
)
1116 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1120 case DHCP_STATE_STOPPED
:
1125 next_timeout
+= (random_u32() & 0x1fffff);
1127 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1128 clock_boottime_or_monotonic(),
1129 next_timeout
, 10 * USEC_PER_MSEC
,
1130 client_timeout_resend
, client
,
1131 client
->event_priority
, "dhcp4-resend-timer", true);
1135 switch (client
->state
) {
1136 case DHCP_STATE_INIT
:
1137 r
= client_send_discover(client
);
1139 client
->state
= DHCP_STATE_SELECTING
;
1140 client
->attempt
= 0;
1141 } else if (client
->attempt
>= client
->max_attempts
)
1146 case DHCP_STATE_SELECTING
:
1147 r
= client_send_discover(client
);
1148 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1153 case DHCP_STATE_INIT_REBOOT
:
1154 case DHCP_STATE_REQUESTING
:
1155 case DHCP_STATE_RENEWING
:
1156 case DHCP_STATE_REBINDING
:
1157 r
= client_send_request(client
);
1158 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1161 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1162 client
->state
= DHCP_STATE_REBOOTING
;
1164 client
->request_sent
= time_now
;
1168 case DHCP_STATE_REBOOTING
:
1169 case DHCP_STATE_BOUND
:
1173 case DHCP_STATE_STOPPED
:
1181 client_stop(client
, r
);
1183 /* Errors were dealt with when stopping the client, don't spill
1184 errors into the event loop handler */
1188 static int client_initialize_io_events(
1189 sd_dhcp_client
*client
,
1190 sd_event_io_handler_t io_callback
) {
1195 assert(client
->event
);
1197 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1198 client
->fd
, EPOLLIN
, io_callback
,
1203 r
= sd_event_source_set_priority(client
->receive_message
,
1204 client
->event_priority
);
1208 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1214 client_stop(client
, r
);
1219 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1224 assert(client
->event
);
1226 if (client
->start_delay
> 0) {
1227 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1228 usec
+= client
->start_delay
;
1231 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1232 clock_boottime_or_monotonic(),
1234 client_timeout_resend
, client
,
1235 client
->event_priority
, "dhcp4-resend-timer", true);
1237 client_stop(client
, r
);
1243 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1244 client_initialize_io_events(client
, io_callback
);
1245 client_initialize_time_events(client
);
1250 static int client_start_delayed(sd_dhcp_client
*client
) {
1253 assert_return(client
, -EINVAL
);
1254 assert_return(client
->event
, -EINVAL
);
1255 assert_return(client
->ifindex
> 0, -EINVAL
);
1256 assert_return(client
->fd
< 0, -EBUSY
);
1257 assert_return(client
->xid
== 0, -EINVAL
);
1258 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1260 client
->xid
= random_u32();
1262 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1263 client
->xid
, client
->mac_addr
,
1264 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1266 client_stop(client
, r
);
1271 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1272 client
->start_time
= now(clock_boottime_or_monotonic());
1274 return client_initialize_events(client
, client_receive_message_raw
);
1277 static int client_start(sd_dhcp_client
*client
) {
1278 client
->start_delay
= 0;
1279 return client_start_delayed(client
);
1282 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1283 sd_dhcp_client
*client
= userdata
;
1284 DHCP_CLIENT_DONT_DESTROY(client
);
1286 log_dhcp_client(client
, "EXPIRED");
1288 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1290 /* lease was lost, start over if not freed or stopped in callback */
1291 if (client
->state
!= DHCP_STATE_STOPPED
) {
1292 client_initialize(client
);
1293 client_start(client
);
1299 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1300 sd_dhcp_client
*client
= userdata
;
1301 DHCP_CLIENT_DONT_DESTROY(client
);
1306 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1307 client
->fd
= asynchronous_close(client
->fd
);
1309 client
->state
= DHCP_STATE_REBINDING
;
1310 client
->attempt
= 0;
1312 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1313 client
->xid
, client
->mac_addr
,
1314 client
->mac_addr_len
, client
->arp_type
,
1317 client_stop(client
, r
);
1322 return client_initialize_events(client
, client_receive_message_raw
);
1325 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1326 sd_dhcp_client
*client
= userdata
;
1327 DHCP_CLIENT_DONT_DESTROY(client
);
1329 client
->state
= DHCP_STATE_RENEWING
;
1330 client
->attempt
= 0;
1332 return client_initialize_time_events(client
);
1335 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1336 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1339 r
= dhcp_lease_new(&lease
);
1343 if (client
->client_id_len
) {
1344 r
= dhcp_lease_set_client_id(lease
,
1345 (uint8_t *) &client
->client_id
,
1346 client
->client_id_len
);
1351 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1352 if (r
!= DHCP_OFFER
) {
1353 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1357 lease
->next_server
= offer
->siaddr
;
1358 lease
->address
= offer
->yiaddr
;
1360 if (lease
->address
== 0 ||
1361 lease
->server_address
== 0 ||
1362 lease
->lifetime
== 0) {
1363 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1367 if (!lease
->have_subnet_mask
) {
1368 r
= dhcp_lease_set_default_subnet_mask(lease
);
1370 log_dhcp_client(client
,
1371 "received lease lacks subnet mask, "
1372 "and a fallback one cannot be generated, ignoring");
1377 sd_dhcp_lease_unref(client
->lease
);
1378 client
->lease
= TAKE_PTR(lease
);
1380 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1383 log_dhcp_client(client
, "OFFER");
1388 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1391 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1392 if (r
!= DHCP_FORCERENEW
)
1395 log_dhcp_client(client
, "FORCERENEW");
1400 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1401 if (a
->address
!= b
->address
)
1404 if (a
->subnet_mask
!= b
->subnet_mask
)
1407 if (a
->router_size
!= b
->router_size
)
1410 for (size_t i
= 0; i
< a
->router_size
; i
++)
1411 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1417 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1418 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1419 _cleanup_free_
char *error_message
= NULL
;
1422 r
= dhcp_lease_new(&lease
);
1426 if (client
->client_id_len
) {
1427 r
= dhcp_lease_set_client_id(lease
,
1428 (uint8_t *) &client
->client_id
,
1429 client
->client_id_len
);
1434 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1435 if (r
== DHCP_NAK
) {
1436 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1437 return -EADDRNOTAVAIL
;
1440 if (r
!= DHCP_ACK
) {
1441 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1445 lease
->next_server
= ack
->siaddr
;
1447 lease
->address
= ack
->yiaddr
;
1449 if (lease
->address
== INADDR_ANY
||
1450 lease
->server_address
== INADDR_ANY
||
1451 lease
->lifetime
== 0) {
1452 log_dhcp_client(client
, "received lease lacks address, server "
1453 "address or lease lifetime, ignoring");
1457 if (lease
->subnet_mask
== INADDR_ANY
) {
1458 r
= dhcp_lease_set_default_subnet_mask(lease
);
1460 log_dhcp_client(client
,
1461 "received lease lacks subnet mask, "
1462 "and a fallback one cannot be generated, ignoring");
1467 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1468 if (client
->lease
) {
1469 if (lease_equal(client
->lease
, lease
))
1470 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1472 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1474 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1477 client
->lease
= TAKE_PTR(lease
);
1479 log_dhcp_client(client
, "ACK");
1484 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1486 assert(client
->request_sent
);
1487 assert(lifetime
> 0);
1494 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1495 + (random_u32() & 0x1fffff);
1498 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1500 uint64_t lifetime_timeout
;
1501 uint64_t t2_timeout
;
1502 uint64_t t1_timeout
;
1503 char time_string
[FORMAT_TIMESPAN_MAX
];
1507 assert(client
->event
);
1508 assert(client
->lease
);
1509 assert(client
->lease
->lifetime
);
1511 /* don't set timers for infinite leases */
1512 if (client
->lease
->lifetime
== 0xffffffff) {
1513 (void) event_source_disable(client
->timeout_t1
);
1514 (void) event_source_disable(client
->timeout_t2
);
1515 (void) event_source_disable(client
->timeout_expire
);
1520 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1523 assert(client
->request_sent
<= time_now
);
1525 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1526 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1527 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1528 /* both T1 and T2 are given */
1529 if (client
->lease
->t1
< client
->lease
->t2
&&
1530 client
->lease
->t2
< client
->lease
->lifetime
) {
1531 /* they are both valid */
1532 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1533 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1536 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1537 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1538 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1539 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1541 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1542 /* only T2 is given, and it is valid */
1543 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1544 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1545 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1546 if (t2_timeout
<= t1_timeout
) {
1547 /* the computed T1 would be invalid, so discard T2 */
1548 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1549 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1551 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1552 /* only T1 is given, and it is valid */
1553 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1554 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1555 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1556 if (t2_timeout
<= t1_timeout
) {
1557 /* the computed T2 would be invalid, so discard T1 */
1558 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1559 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1562 /* fall back to the default timeouts */
1563 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1564 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1565 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1566 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1569 /* arm lifetime timeout */
1570 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1571 clock_boottime_or_monotonic(),
1572 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1573 client_timeout_expire
, client
,
1574 client
->event_priority
, "dhcp4-lifetime", true);
1578 log_dhcp_client(client
, "lease expires in %s",
1579 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1581 /* don't arm earlier timeouts if this has already expired */
1582 if (lifetime_timeout
<= time_now
)
1585 /* arm T2 timeout */
1586 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1587 clock_boottime_or_monotonic(),
1588 t2_timeout
, 10 * USEC_PER_MSEC
,
1589 client_timeout_t2
, client
,
1590 client
->event_priority
, "dhcp4-t2-timeout", true);
1594 log_dhcp_client(client
, "T2 expires in %s",
1595 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1597 /* don't arm earlier timeout if this has already expired */
1598 if (t2_timeout
<= time_now
)
1601 /* arm T1 timeout */
1602 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1603 clock_boottime_or_monotonic(),
1604 t1_timeout
, 10 * USEC_PER_MSEC
,
1605 client_timeout_t1
, client
,
1606 client
->event_priority
, "dhcp4-t1-timer", true);
1610 log_dhcp_client(client
, "T1 expires in %s",
1611 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1616 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1617 DHCP_CLIENT_DONT_DESTROY(client
);
1618 char time_string
[FORMAT_TIMESPAN_MAX
];
1619 int r
= 0, notify_event
= 0;
1622 assert(client
->event
);
1625 switch (client
->state
) {
1626 case DHCP_STATE_SELECTING
:
1628 r
= client_handle_offer(client
, message
, len
);
1631 client
->state
= DHCP_STATE_REQUESTING
;
1632 client
->attempt
= 0;
1634 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1635 clock_boottime_or_monotonic(),
1637 client_timeout_resend
, client
,
1638 client
->event_priority
, "dhcp4-resend-timer", true);
1641 } else if (r
== -ENOMSG
)
1642 /* invalid message, let's ignore it */
1647 case DHCP_STATE_REBOOTING
:
1648 case DHCP_STATE_REQUESTING
:
1649 case DHCP_STATE_RENEWING
:
1650 case DHCP_STATE_REBINDING
:
1652 r
= client_handle_ack(client
, message
, len
);
1654 client
->start_delay
= 0;
1655 (void) event_source_disable(client
->timeout_resend
);
1656 client
->receive_message
=
1657 sd_event_source_unref(client
->receive_message
);
1658 client
->fd
= asynchronous_close(client
->fd
);
1660 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1661 DHCP_STATE_REBOOTING
))
1662 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1663 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1666 client
->state
= DHCP_STATE_BOUND
;
1667 client
->attempt
= 0;
1669 client
->last_addr
= client
->lease
->address
;
1671 r
= client_set_lease_timeouts(client
);
1673 log_dhcp_client(client
, "could not set lease timeouts");
1677 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1679 log_dhcp_client(client
, "could not bind UDP socket");
1685 client_initialize_io_events(client
, client_receive_message_udp
);
1688 client_notify(client
, notify_event
);
1689 if (client
->state
== DHCP_STATE_STOPPED
)
1693 } else if (r
== -EADDRNOTAVAIL
) {
1694 /* got a NAK, let's restart the client */
1695 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1697 r
= client_initialize(client
);
1701 r
= client_start_delayed(client
);
1705 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1706 client
->start_delay
, USEC_PER_SEC
));
1708 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1709 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1712 } else if (r
== -ENOMSG
)
1713 /* invalid message, let's ignore it */
1718 case DHCP_STATE_BOUND
:
1719 r
= client_handle_forcerenew(client
, message
, len
);
1721 r
= client_timeout_t1(NULL
, 0, client
);
1724 } else if (r
== -ENOMSG
)
1725 /* invalid message, let's ignore it */
1730 case DHCP_STATE_INIT
:
1731 case DHCP_STATE_INIT_REBOOT
:
1735 case DHCP_STATE_STOPPED
:
1742 client_stop(client
, r
);
1747 static int client_receive_message_udp(
1753 sd_dhcp_client
*client
= userdata
;
1754 _cleanup_free_ DHCPMessage
*message
= NULL
;
1755 const uint8_t *expected_chaddr
= NULL
;
1756 uint8_t expected_hlen
= 0;
1757 ssize_t len
, buflen
;
1762 buflen
= next_datagram_size_fd(fd
);
1763 if (buflen
== -ENETDOWN
) {
1764 /* the link is down. Don't return an error or the I/O event
1765 source will be disconnected and we won't be able to receive
1766 packets again when the link comes back. */
1772 message
= malloc0(buflen
);
1776 len
= recv(fd
, message
, buflen
, 0);
1778 /* see comment above for why we shouldn't error out on ENETDOWN. */
1779 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1782 return log_dhcp_client_errno(client
, errno
,
1783 "Could not receive message from UDP socket: %m");
1785 if ((size_t) len
< sizeof(DHCPMessage
)) {
1786 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1790 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1791 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1795 if (message
->op
!= BOOTREPLY
) {
1796 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1800 if (message
->htype
!= client
->arp_type
) {
1801 log_dhcp_client(client
, "Packet type does not match client type");
1805 if (client
->arp_type
== ARPHRD_ETHER
) {
1806 expected_hlen
= ETH_ALEN
;
1807 expected_chaddr
= &client
->mac_addr
[0];
1810 if (message
->hlen
!= expected_hlen
) {
1811 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1815 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1816 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1820 if (client
->state
!= DHCP_STATE_BOUND
&&
1821 be32toh(message
->xid
) != client
->xid
) {
1822 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1823 so ignore the xid in this case */
1824 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1825 be32toh(message
->xid
), client
->xid
);
1829 return client_handle_message(client
, message
, len
);
1832 static int client_receive_message_raw(
1838 sd_dhcp_client
*client
= userdata
;
1839 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1840 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1841 struct iovec iov
= {};
1842 struct msghdr msg
= {
1845 .msg_control
= cmsgbuf
,
1846 .msg_controllen
= sizeof(cmsgbuf
),
1848 struct cmsghdr
*cmsg
;
1849 bool checksum
= true;
1850 ssize_t buflen
, len
;
1856 buflen
= next_datagram_size_fd(fd
);
1857 if (buflen
== -ENETDOWN
)
1862 packet
= malloc0(buflen
);
1866 iov
= IOVEC_MAKE(packet
, buflen
);
1868 len
= recvmsg(fd
, &msg
, 0);
1870 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1873 return log_dhcp_client_errno(client
, errno
,
1874 "Could not receive message from raw socket: %m");
1875 } else if ((size_t)len
< sizeof(DHCPPacket
))
1878 CMSG_FOREACH(cmsg
, &msg
)
1879 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1880 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1881 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1882 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1884 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1888 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1892 len
-= DHCP_IP_UDP_SIZE
;
1894 return client_handle_message(client
, &packet
->dhcp
, len
);
1897 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1898 assert_return(client
, -EINVAL
);
1899 assert_return(client
->fd
>= 0, -EINVAL
);
1901 client
->start_delay
= 0;
1902 client
->attempt
= 1;
1903 client
->state
= DHCP_STATE_RENEWING
;
1905 return client_initialize_time_events(client
);
1908 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1911 assert_return(client
, -EINVAL
);
1913 r
= client_initialize(client
);
1917 /* RFC7844 section 3.3:
1918 SHOULD perform a complete four-way handshake, starting with a
1919 DHCPDISCOVER, to obtain a new address lease. If the client can
1920 ascertain that this is exactly the same network to which it was
1921 previously connected, and if the link-layer address did not change,
1922 the client MAY issue a DHCPREQUEST to try to reclaim the current
1924 if (client
->last_addr
&& !client
->anonymize
)
1925 client
->state
= DHCP_STATE_INIT_REBOOT
;
1927 r
= client_start(client
);
1929 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1934 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1935 assert_return(client
, -EINVAL
);
1936 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1937 assert_return(client
->lease
, -EUNATCH
);
1939 _cleanup_free_ DHCPPacket
*release
= NULL
;
1940 size_t optoffset
, optlen
;
1943 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
1947 /* Fill up release IP and MAC */
1948 release
->dhcp
.ciaddr
= client
->lease
->address
;
1949 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1951 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1952 SD_DHCP_OPTION_END
, 0, NULL
);
1956 r
= dhcp_network_send_udp_socket(client
->fd
,
1957 client
->lease
->server_address
,
1960 sizeof(DHCPMessage
) + optoffset
);
1964 log_dhcp_client(client
, "RELEASE");
1969 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
1970 assert_return(client
, -EINVAL
);
1971 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1972 assert_return(client
->lease
, -EUNATCH
);
1974 _cleanup_free_ DHCPPacket
*release
= NULL
;
1975 size_t optoffset
, optlen
;
1978 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
1982 release
->dhcp
.ciaddr
= client
->lease
->address
;
1983 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1985 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1986 SD_DHCP_OPTION_END
, 0, NULL
);
1990 r
= dhcp_network_send_udp_socket(client
->fd
,
1991 client
->lease
->server_address
,
1994 sizeof(DHCPMessage
) + optoffset
);
1998 log_dhcp_client(client
, "DECLINE");
2000 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2002 if (client
->state
!= DHCP_STATE_STOPPED
) {
2003 r
= sd_dhcp_client_start(client
);
2011 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2012 DHCP_CLIENT_DONT_DESTROY(client
);
2014 assert_return(client
, -EINVAL
);
2016 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2017 client
->state
= DHCP_STATE_STOPPED
;
2022 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2025 assert_return(client
, -EINVAL
);
2026 assert_return(!client
->event
, -EBUSY
);
2029 client
->event
= sd_event_ref(event
);
2031 r
= sd_event_default(&client
->event
);
2036 client
->event_priority
= priority
;
2041 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2042 assert_return(client
, -EINVAL
);
2044 client
->event
= sd_event_unref(client
->event
);
2049 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2050 assert_return(client
, NULL
);
2052 return client
->event
;
2055 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2059 log_dhcp_client(client
, "FREE");
2061 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2062 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2063 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2064 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2066 client_initialize(client
);
2068 sd_dhcp_client_detach_event(client
);
2070 sd_dhcp_lease_unref(client
->lease
);
2072 free(client
->req_opts
);
2073 free(client
->hostname
);
2074 free(client
->vendor_class_identifier
);
2075 client
->user_class
= strv_free(client
->user_class
);
2076 ordered_hashmap_free(client
->options
);
2077 return mfree(client
);
2080 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2082 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2083 assert_return(ret
, -EINVAL
);
2085 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2089 *client
= (sd_dhcp_client
) {
2091 .state
= DHCP_STATE_INIT
,
2094 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2095 .port
= DHCP_PORT_CLIENT
,
2096 .anonymize
= !!anonymize
,
2097 .max_attempts
= (uint64_t) -1,
2098 .ip_service_type
= -1,
2100 /* NOTE: this could be moved to a function. */
2102 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2103 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2105 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2106 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2108 if (!client
->req_opts
)
2111 *ret
= TAKE_PTR(client
);