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>
12 #include <sys/ioctl.h>
13 #include <linux/if_infiniband.h>
15 #include "sd-dhcp-client.h"
17 #include "alloc-util.h"
19 #include "dhcp-identifier.h"
20 #include "dhcp-internal.h"
21 #include "dhcp-lease-internal.h"
22 #include "dhcp-protocol.h"
23 #include "dns-domain.h"
24 #include "event-util.h"
25 #include "hostname-util.h"
27 #include "memory-util.h"
28 #include "random-util.h"
29 #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_option
{
46 struct sd_dhcp_client
{
52 sd_event_source
*timeout_resend
;
56 union sockaddr_union link
;
57 sd_event_source
*receive_message
;
58 bool request_broadcast
;
60 size_t req_opts_allocated
;
64 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
71 /* 0: Generic (non-LL) (RFC 2132) */
72 uint8_t data
[MAX_CLIENT_ID_LEN
];
75 /* 1: Ethernet Link-Layer (RFC 2132) */
76 uint8_t haddr
[ETH_ALEN
];
79 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
83 /* 255: Node-specific (RFC 4361) */
88 uint8_t data
[MAX_CLIENT_ID_LEN
];
94 char *vendor_class_identifier
;
100 uint64_t max_attempts
;
101 OrderedHashmap
*options
;
103 sd_event_source
*timeout_t1
;
104 sd_event_source
*timeout_t2
;
105 sd_event_source
*timeout_expire
;
106 sd_dhcp_client_callback_t callback
;
108 sd_dhcp_lease
*lease
;
113 static const uint8_t default_req_opts
[] = {
114 SD_DHCP_OPTION_SUBNET_MASK
,
115 SD_DHCP_OPTION_ROUTER
,
116 SD_DHCP_OPTION_HOST_NAME
,
117 SD_DHCP_OPTION_DOMAIN_NAME
,
118 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
121 /* RFC7844 section 3:
122 MAY contain the Parameter Request List option.
124 The client intending to protect its privacy SHOULD only request a
125 minimal number of options in the PRL and SHOULD also randomly shuffle
126 the ordering of option codes in the PRL. If this random ordering
127 cannot be implemented, the client MAY order the option codes in the
128 PRL by option code number (lowest to highest).
130 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
131 static const uint8_t default_req_opts_anonymize
[] = {
132 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
133 SD_DHCP_OPTION_ROUTER
, /* 3 */
134 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
135 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
136 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
137 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
138 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
139 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
140 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
141 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
142 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
143 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
144 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
147 static int client_receive_message_raw(
152 static int client_receive_message_udp(
157 static void client_stop(sd_dhcp_client
*client
, int error
);
159 int sd_dhcp_client_set_callback(
160 sd_dhcp_client
*client
,
161 sd_dhcp_client_callback_t cb
,
164 assert_return(client
, -EINVAL
);
166 client
->callback
= cb
;
167 client
->userdata
= userdata
;
172 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
173 assert_return(client
, -EINVAL
);
175 client
->request_broadcast
= !!broadcast
;
180 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
183 assert_return(client
, -EINVAL
);
184 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
188 case SD_DHCP_OPTION_PAD
:
189 case SD_DHCP_OPTION_OVERLOAD
:
190 case SD_DHCP_OPTION_MESSAGE_TYPE
:
191 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
192 case SD_DHCP_OPTION_END
:
199 for (i
= 0; i
< client
->req_opts_size
; i
++)
200 if (client
->req_opts
[i
] == option
)
203 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
204 client
->req_opts_size
+ 1))
207 client
->req_opts
[client
->req_opts_size
++] = option
;
212 int sd_dhcp_client_set_request_address(
213 sd_dhcp_client
*client
,
214 const struct in_addr
*last_addr
) {
216 assert_return(client
, -EINVAL
);
217 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
220 client
->last_addr
= last_addr
->s_addr
;
222 client
->last_addr
= INADDR_ANY
;
227 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
229 assert_return(client
, -EINVAL
);
230 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
231 assert_return(ifindex
> 0, -EINVAL
);
233 client
->ifindex
= ifindex
;
237 int sd_dhcp_client_set_mac(
238 sd_dhcp_client
*client
,
243 DHCP_CLIENT_DONT_DESTROY(client
);
244 bool need_restart
= false;
246 assert_return(client
, -EINVAL
);
247 assert_return(addr
, -EINVAL
);
248 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
249 assert_return(arp_type
> 0, -EINVAL
);
251 if (arp_type
== ARPHRD_ETHER
)
252 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
253 else if (arp_type
== ARPHRD_INFINIBAND
)
254 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
258 if (client
->mac_addr_len
== addr_len
&&
259 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
262 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
263 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
265 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
268 memcpy(&client
->mac_addr
, addr
, addr_len
);
269 client
->mac_addr_len
= addr_len
;
270 client
->arp_type
= arp_type
;
272 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
273 sd_dhcp_client_start(client
);
278 int sd_dhcp_client_get_client_id(
279 sd_dhcp_client
*client
,
281 const uint8_t **data
,
284 assert_return(client
, -EINVAL
);
285 assert_return(type
, -EINVAL
);
286 assert_return(data
, -EINVAL
);
287 assert_return(data_len
, -EINVAL
);
292 if (client
->client_id_len
) {
293 *type
= client
->client_id
.type
;
294 *data
= client
->client_id
.raw
.data
;
295 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
301 int sd_dhcp_client_set_client_id(
302 sd_dhcp_client
*client
,
307 DHCP_CLIENT_DONT_DESTROY(client
);
308 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 sd_dhcp_client_start(client
);
348 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
349 * without further modification. Otherwise, if duid_type is supported, DUID
350 * is set based on that type. Otherwise, an error is returned.
352 static int dhcp_client_set_iaid_duid_internal(
353 sd_dhcp_client
*client
,
362 DHCP_CLIENT_DONT_DESTROY(client
);
366 assert_return(client
, -EINVAL
);
367 assert_return(duid_len
== 0 || duid
, -EINVAL
);
370 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
375 zero(client
->client_id
);
376 client
->client_id
.type
= 255;
380 client
->client_id
.ns
.iaid
= htobe32(iaid
);
382 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
383 client
->mac_addr_len
,
385 &client
->client_id
.ns
.iaid
);
392 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
393 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
394 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
398 if (client
->mac_addr_len
== 0)
401 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
406 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
411 if (client
->mac_addr_len
== 0)
414 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
419 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
427 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
428 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
430 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
431 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
432 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
433 sd_dhcp_client_start(client
);
439 int sd_dhcp_client_set_iaid_duid(
440 sd_dhcp_client
*client
,
446 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
449 int sd_dhcp_client_set_iaid_duid_llt(
450 sd_dhcp_client
*client
,
454 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
457 int sd_dhcp_client_set_duid(
458 sd_dhcp_client
*client
,
462 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
465 int sd_dhcp_client_set_duid_llt(
466 sd_dhcp_client
*client
,
468 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
471 int sd_dhcp_client_set_hostname(
472 sd_dhcp_client
*client
,
473 const char *hostname
) {
475 assert_return(client
, -EINVAL
);
477 /* Make sure hostnames qualify as DNS and as Linux hostnames */
479 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
482 return free_and_strdup(&client
->hostname
, hostname
);
485 int sd_dhcp_client_set_vendor_class_identifier(
486 sd_dhcp_client
*client
,
489 assert_return(client
, -EINVAL
);
491 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
494 int sd_dhcp_client_set_user_class(
495 sd_dhcp_client
*client
,
496 const char* const* user_class
) {
498 _cleanup_strv_free_
char **s
= NULL
;
501 STRV_FOREACH(p
, (char **) user_class
)
502 if (strlen(*p
) > 255)
503 return -ENAMETOOLONG
;
505 s
= strv_copy((char **) user_class
);
509 client
->user_class
= TAKE_PTR(s
);
514 int sd_dhcp_client_set_client_port(
515 sd_dhcp_client
*client
,
518 assert_return(client
, -EINVAL
);
525 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
526 assert_return(client
, -EINVAL
);
527 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
534 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
535 assert_return(client
, -EINVAL
);
537 client
->max_attempts
= max_attempts
;
542 static sd_dhcp_option
* dhcp_option_free(sd_dhcp_option
*i
) {
550 int sd_dhcp_option_new(uint8_t option
, void *data
, size_t length
, sd_dhcp_option
**ret
) {
551 assert_return(ret
, -EINVAL
);
552 assert_return(length
== 0 || data
, -EINVAL
);
554 _cleanup_free_
void *q
= memdup(data
, length
);
558 sd_dhcp_option
*p
= new(sd_dhcp_option
, 1);
562 *p
= (sd_dhcp_option
) {
573 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option
, sd_dhcp_option
, dhcp_option_free
);
574 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
575 dhcp_option_hash_ops
,
578 trivial_compare_func
,
580 sd_dhcp_option_unref
);
582 int sd_dhcp_client_set_dhcp_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
585 assert_return(client
, -EINVAL
);
586 assert_return(v
, -EINVAL
);
588 r
= ordered_hashmap_ensure_allocated(&client
->options
, &dhcp_option_hash_ops
);
592 r
= ordered_hashmap_put(client
->options
, UINT_TO_PTR(v
->option
), v
);
596 sd_dhcp_option_ref(v
);
600 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
601 assert_return(client
, -EINVAL
);
603 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
604 return -EADDRNOTAVAIL
;
607 *ret
= client
->lease
;
612 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
613 assert_return(client
, -EINVAL
);
615 client
->ip_service_type
= type
;
620 static int client_notify(sd_dhcp_client
*client
, int event
) {
623 if (client
->callback
)
624 return client
->callback(client
, event
, client
->userdata
);
629 static int client_initialize(sd_dhcp_client
*client
) {
630 assert_return(client
, -EINVAL
);
632 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
634 client
->fd
= asynchronous_close(client
->fd
);
636 (void) event_source_disable(client
->timeout_resend
);
637 (void) event_source_disable(client
->timeout_t1
);
638 (void) event_source_disable(client
->timeout_t2
);
639 (void) event_source_disable(client
->timeout_expire
);
643 client
->state
= DHCP_STATE_INIT
;
646 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
651 static void client_stop(sd_dhcp_client
*client
, int error
) {
655 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
656 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
657 log_dhcp_client(client
, "STOPPED");
659 log_dhcp_client(client
, "STOPPED: Unknown event");
661 client_notify(client
, error
);
663 client_initialize(client
);
666 static int client_message_init(
667 sd_dhcp_client
*client
,
671 size_t *_optoffset
) {
673 _cleanup_free_ DHCPPacket
*packet
= NULL
;
674 size_t optlen
, optoffset
, size
;
681 assert(client
->start_time
);
685 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
));
687 optlen
= DHCP_MIN_OPTIONS_SIZE
;
688 size
= sizeof(DHCPPacket
) + optlen
;
690 packet
= malloc0(size
);
694 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
695 client
->arp_type
, optlen
, &optoffset
);
699 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
700 refuse to issue an DHCP lease if 'secs' is set to zero */
701 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
704 assert(time_now
>= client
->start_time
);
706 /* seconds between sending first and last DISCOVER
707 * must always be strictly positive to deal with broken servers */
708 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
709 packet
->dhcp
.secs
= htobe16(secs
);
711 /* RFC2132 section 4.1
712 A client that cannot receive unicast IP datagrams until its protocol
713 software has been configured with an IP address SHOULD set the
714 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
715 DHCPREQUEST messages that client sends. The BROADCAST bit will
716 provide a hint to the DHCP server and BOOTP relay agent to broadcast
717 any messages to the client on the client's subnet.
719 Note: some interfaces needs this to be enabled, but some networks
720 needs this to be disabled as broadcasts are filteretd, so this
721 needs to be configurable */
722 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
723 packet
->dhcp
.flags
= htobe16(0x8000);
725 /* RFC2132 section 4.1.1:
726 The client MUST include its hardware address in the ’chaddr’ field, if
727 necessary for delivery of DHCP reply messages. Non-Ethernet
728 interfaces will leave 'chaddr' empty and use the client identifier
729 instead (eg, RFC 4390 section 2.1).
731 if (client
->arp_type
== ARPHRD_ETHER
)
732 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
734 /* If no client identifier exists, construct an RFC 4361-compliant one */
735 if (client
->client_id_len
== 0) {
738 client
->client_id
.type
= 255;
740 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
741 true, &client
->client_id
.ns
.iaid
);
745 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
749 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
752 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
753 Identifier option is not set */
754 if (client
->client_id_len
) {
755 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
756 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
757 client
->client_id_len
,
763 /* RFC2131 section 3.5:
764 in its initial DHCPDISCOVER or DHCPREQUEST message, a
765 client may provide the server with a list of specific
766 parameters the client is interested in. If the client
767 includes a list of parameters in a DHCPDISCOVER message,
768 it MUST include that list in any subsequent DHCPREQUEST
772 /* RFC7844 section 3:
773 MAY contain the Parameter Request List option. */
774 /* NOTE: in case that there would be an option to do not send
775 * any PRL at all, the size should be checked before sending */
776 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
777 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
778 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
779 client
->req_opts_size
, client
->req_opts
);
784 /* RFC2131 section 3.5:
785 The client SHOULD include the ’maximum DHCP message size’ option to
786 let the server know how large the server may make its DHCP messages.
788 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
789 than the defined default size unless the Maximum Message Size option
792 RFC3442 "Requirements to Avoid Sizing Constraints":
793 Because a full routing table can be quite large, the standard 576
794 octet maximum size for a DHCP message may be too short to contain
795 some legitimate Classless Static Route options. Because of this,
796 clients implementing the Classless Static Route option SHOULD send a
797 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
798 stack is capable of receiving larger IP datagrams. In this case, the
799 client SHOULD set the value of this option to at least the MTU of the
800 interface that the client is configuring. The client MAY set the
801 value of this option higher, up to the size of the largest UDP packet
802 it is prepared to accept. (Note that the value specified in the
803 Maximum DHCP Message Size option is the total maximum packet size,
804 including IP and UDP headers.)
806 /* RFC7844 section 3:
807 SHOULD NOT contain any other option. */
808 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
809 max_size
= htobe16(size
);
810 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
811 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
818 *_optoffset
= optoffset
;
819 *ret
= TAKE_PTR(packet
);
824 static int client_append_fqdn_option(
825 DHCPMessage
*message
,
830 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
833 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
834 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
835 buffer
[1] = 0; /* RCODE1 (deprecated) */
836 buffer
[2] = 0; /* RCODE2 (deprecated) */
838 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
840 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
841 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
846 static int dhcp_client_send_raw(
847 sd_dhcp_client
*client
,
851 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
852 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
854 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
858 static int client_send_discover(sd_dhcp_client
*client
) {
859 _cleanup_free_ DHCPPacket
*discover
= NULL
;
860 size_t optoffset
, optlen
;
866 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
868 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
869 &optlen
, &optoffset
);
873 /* the client may suggest values for the network address
874 and lease time in the DHCPDISCOVER message. The client may include
875 the ’requested IP address’ option to suggest that a particular IP
876 address be assigned, and may include the ’IP address lease time’
877 option to suggest the lease time it would like.
879 if (client
->last_addr
!= INADDR_ANY
) {
880 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
881 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
882 4, &client
->last_addr
);
887 if (client
->hostname
) {
888 /* According to RFC 4702 "clients that send the Client FQDN option in
889 their messages MUST NOT also send the Host Name option". Just send
890 one of the two depending on the hostname type.
892 if (dns_name_is_single_label(client
->hostname
)) {
893 /* it is unclear from RFC 2131 if client should send hostname in
894 DHCPDISCOVER but dhclient does and so we do as well
896 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
897 SD_DHCP_OPTION_HOST_NAME
,
898 strlen(client
->hostname
), client
->hostname
);
900 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
906 if (client
->vendor_class_identifier
) {
907 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
908 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
909 strlen(client
->vendor_class_identifier
),
910 client
->vendor_class_identifier
);
915 if (client
->user_class
) {
916 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
917 SD_DHCP_OPTION_USER_CLASS
,
918 strv_length(client
->user_class
),
924 ORDERED_HASHMAP_FOREACH(j
, client
->options
, i
) {
925 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
926 j
->option
, j
->length
, j
->data
);
931 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
932 SD_DHCP_OPTION_END
, 0, NULL
);
936 /* We currently ignore:
937 The client SHOULD wait a random time between one and ten seconds to
938 desynchronize the use of DHCP at startup.
940 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
944 log_dhcp_client(client
, "DISCOVER");
949 static int client_send_request(sd_dhcp_client
*client
) {
950 _cleanup_free_ DHCPPacket
*request
= NULL
;
951 size_t optoffset
, optlen
;
956 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
960 switch (client
->state
) {
961 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
962 SELECTING should be REQUESTING)
965 case DHCP_STATE_REQUESTING
:
966 /* Client inserts the address of the selected server in ’server
967 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
968 filled in with the yiaddr value from the chosen DHCPOFFER.
971 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
972 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
973 4, &client
->lease
->server_address
);
977 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
978 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
979 4, &client
->lease
->address
);
985 case DHCP_STATE_INIT_REBOOT
:
986 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
987 option MUST be filled in with client’s notion of its previously
988 assigned address. ’ciaddr’ MUST be zero.
990 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
991 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
992 4, &client
->last_addr
);
997 case DHCP_STATE_RENEWING
:
998 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
999 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1000 client’s IP address.
1003 case DHCP_STATE_REBINDING
:
1004 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1005 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1006 client’s IP address.
1008 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1010 request
->dhcp
.ciaddr
= client
->lease
->address
;
1014 case DHCP_STATE_INIT
:
1015 case DHCP_STATE_SELECTING
:
1016 case DHCP_STATE_REBOOTING
:
1017 case DHCP_STATE_BOUND
:
1018 case DHCP_STATE_STOPPED
:
1022 if (client
->hostname
) {
1023 if (dns_name_is_single_label(client
->hostname
))
1024 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1025 SD_DHCP_OPTION_HOST_NAME
,
1026 strlen(client
->hostname
), client
->hostname
);
1028 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
1034 if (client
->vendor_class_identifier
) {
1035 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1036 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1037 strlen(client
->vendor_class_identifier
),
1038 client
->vendor_class_identifier
);
1043 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1044 SD_DHCP_OPTION_END
, 0, NULL
);
1048 if (client
->state
== DHCP_STATE_RENEWING
)
1049 r
= dhcp_network_send_udp_socket(client
->fd
,
1050 client
->lease
->server_address
,
1053 sizeof(DHCPMessage
) + optoffset
);
1055 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1059 switch (client
->state
) {
1061 case DHCP_STATE_REQUESTING
:
1062 log_dhcp_client(client
, "REQUEST (requesting)");
1065 case DHCP_STATE_INIT_REBOOT
:
1066 log_dhcp_client(client
, "REQUEST (init-reboot)");
1069 case DHCP_STATE_RENEWING
:
1070 log_dhcp_client(client
, "REQUEST (renewing)");
1073 case DHCP_STATE_REBINDING
:
1074 log_dhcp_client(client
, "REQUEST (rebinding)");
1078 log_dhcp_client(client
, "REQUEST (invalid)");
1085 static int client_start(sd_dhcp_client
*client
);
1087 static int client_timeout_resend(
1092 sd_dhcp_client
*client
= userdata
;
1093 DHCP_CLIENT_DONT_DESTROY(client
);
1094 usec_t next_timeout
= 0;
1101 assert(client
->event
);
1103 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1107 switch (client
->state
) {
1109 case DHCP_STATE_RENEWING
:
1111 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1115 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1119 case DHCP_STATE_REBINDING
:
1121 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1125 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1128 case DHCP_STATE_REBOOTING
:
1129 /* start over as we did not receive a timely ack or nak */
1130 r
= client_initialize(client
);
1134 r
= client_start(client
);
1138 log_dhcp_client(client
, "REBOOTED");
1142 case DHCP_STATE_INIT
:
1143 case DHCP_STATE_INIT_REBOOT
:
1144 case DHCP_STATE_SELECTING
:
1145 case DHCP_STATE_REQUESTING
:
1146 case DHCP_STATE_BOUND
:
1148 if (client
->attempt
< client
->max_attempts
)
1153 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1157 case DHCP_STATE_STOPPED
:
1162 next_timeout
+= (random_u32() & 0x1fffff);
1164 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1165 clock_boottime_or_monotonic(),
1166 next_timeout
, 10 * USEC_PER_MSEC
,
1167 client_timeout_resend
, client
,
1168 client
->event_priority
, "dhcp4-resend-timer", true);
1172 switch (client
->state
) {
1173 case DHCP_STATE_INIT
:
1174 r
= client_send_discover(client
);
1176 client
->state
= DHCP_STATE_SELECTING
;
1177 client
->attempt
= 0;
1178 } else if (client
->attempt
>= client
->max_attempts
)
1183 case DHCP_STATE_SELECTING
:
1184 r
= client_send_discover(client
);
1185 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1190 case DHCP_STATE_INIT_REBOOT
:
1191 case DHCP_STATE_REQUESTING
:
1192 case DHCP_STATE_RENEWING
:
1193 case DHCP_STATE_REBINDING
:
1194 r
= client_send_request(client
);
1195 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1198 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1199 client
->state
= DHCP_STATE_REBOOTING
;
1201 client
->request_sent
= time_now
;
1205 case DHCP_STATE_REBOOTING
:
1206 case DHCP_STATE_BOUND
:
1210 case DHCP_STATE_STOPPED
:
1218 client_stop(client
, r
);
1220 /* Errors were dealt with when stopping the client, don't spill
1221 errors into the event loop handler */
1225 static int client_initialize_io_events(
1226 sd_dhcp_client
*client
,
1227 sd_event_io_handler_t io_callback
) {
1232 assert(client
->event
);
1234 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1235 client
->fd
, EPOLLIN
, io_callback
,
1240 r
= sd_event_source_set_priority(client
->receive_message
,
1241 client
->event_priority
);
1245 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1251 client_stop(client
, r
);
1256 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1261 assert(client
->event
);
1263 if (client
->start_delay
> 0) {
1264 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1265 usec
+= client
->start_delay
;
1268 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1269 clock_boottime_or_monotonic(),
1271 client_timeout_resend
, client
,
1272 client
->event_priority
, "dhcp4-resend-timer", true);
1274 client_stop(client
, r
);
1280 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1281 client_initialize_io_events(client
, io_callback
);
1282 client_initialize_time_events(client
);
1287 static int client_start_delayed(sd_dhcp_client
*client
) {
1290 assert_return(client
, -EINVAL
);
1291 assert_return(client
->event
, -EINVAL
);
1292 assert_return(client
->ifindex
> 0, -EINVAL
);
1293 assert_return(client
->fd
< 0, -EBUSY
);
1294 assert_return(client
->xid
== 0, -EINVAL
);
1295 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1297 client
->xid
= random_u32();
1299 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1300 client
->xid
, client
->mac_addr
,
1301 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1303 client_stop(client
, r
);
1308 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1309 client
->start_time
= now(clock_boottime_or_monotonic());
1311 return client_initialize_events(client
, client_receive_message_raw
);
1314 static int client_start(sd_dhcp_client
*client
) {
1315 client
->start_delay
= 0;
1316 return client_start_delayed(client
);
1319 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1320 sd_dhcp_client
*client
= userdata
;
1321 DHCP_CLIENT_DONT_DESTROY(client
);
1323 log_dhcp_client(client
, "EXPIRED");
1325 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1327 /* lease was lost, start over if not freed or stopped in callback */
1328 if (client
->state
!= DHCP_STATE_STOPPED
) {
1329 client_initialize(client
);
1330 client_start(client
);
1336 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1337 sd_dhcp_client
*client
= userdata
;
1338 DHCP_CLIENT_DONT_DESTROY(client
);
1343 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1344 client
->fd
= asynchronous_close(client
->fd
);
1346 client
->state
= DHCP_STATE_REBINDING
;
1347 client
->attempt
= 0;
1349 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1350 client
->xid
, client
->mac_addr
,
1351 client
->mac_addr_len
, client
->arp_type
,
1354 client_stop(client
, r
);
1359 return client_initialize_events(client
, client_receive_message_raw
);
1362 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1363 sd_dhcp_client
*client
= userdata
;
1364 DHCP_CLIENT_DONT_DESTROY(client
);
1366 client
->state
= DHCP_STATE_RENEWING
;
1367 client
->attempt
= 0;
1369 return client_initialize_time_events(client
);
1372 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1373 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1376 r
= dhcp_lease_new(&lease
);
1380 if (client
->client_id_len
) {
1381 r
= dhcp_lease_set_client_id(lease
,
1382 (uint8_t *) &client
->client_id
,
1383 client
->client_id_len
);
1388 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1389 if (r
!= DHCP_OFFER
) {
1390 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1394 lease
->next_server
= offer
->siaddr
;
1395 lease
->address
= offer
->yiaddr
;
1397 if (lease
->address
== 0 ||
1398 lease
->server_address
== 0 ||
1399 lease
->lifetime
== 0) {
1400 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1404 if (!lease
->have_subnet_mask
) {
1405 r
= dhcp_lease_set_default_subnet_mask(lease
);
1407 log_dhcp_client(client
,
1408 "received lease lacks subnet mask, "
1409 "and a fallback one cannot be generated, ignoring");
1414 sd_dhcp_lease_unref(client
->lease
);
1415 client
->lease
= TAKE_PTR(lease
);
1417 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1420 log_dhcp_client(client
, "OFFER");
1425 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1428 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1429 if (r
!= DHCP_FORCERENEW
)
1432 log_dhcp_client(client
, "FORCERENEW");
1437 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1438 if (a
->address
!= b
->address
)
1441 if (a
->subnet_mask
!= b
->subnet_mask
)
1444 if (a
->router_size
!= b
->router_size
)
1447 for (size_t i
= 0; i
< a
->router_size
; i
++)
1448 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1454 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1455 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1456 _cleanup_free_
char *error_message
= NULL
;
1459 r
= dhcp_lease_new(&lease
);
1463 if (client
->client_id_len
) {
1464 r
= dhcp_lease_set_client_id(lease
,
1465 (uint8_t *) &client
->client_id
,
1466 client
->client_id_len
);
1471 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1472 if (r
== DHCP_NAK
) {
1473 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1474 return -EADDRNOTAVAIL
;
1477 if (r
!= DHCP_ACK
) {
1478 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1482 lease
->next_server
= ack
->siaddr
;
1484 lease
->address
= ack
->yiaddr
;
1486 if (lease
->address
== INADDR_ANY
||
1487 lease
->server_address
== INADDR_ANY
||
1488 lease
->lifetime
== 0) {
1489 log_dhcp_client(client
, "received lease lacks address, server "
1490 "address or lease lifetime, ignoring");
1494 if (lease
->subnet_mask
== INADDR_ANY
) {
1495 r
= dhcp_lease_set_default_subnet_mask(lease
);
1497 log_dhcp_client(client
,
1498 "received lease lacks subnet mask, "
1499 "and a fallback one cannot be generated, ignoring");
1504 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1505 if (client
->lease
) {
1506 if (lease_equal(client
->lease
, lease
))
1507 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1509 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1511 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1514 client
->lease
= TAKE_PTR(lease
);
1516 log_dhcp_client(client
, "ACK");
1521 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1523 assert(client
->request_sent
);
1524 assert(lifetime
> 0);
1531 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1532 + (random_u32() & 0x1fffff);
1535 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1537 uint64_t lifetime_timeout
;
1538 uint64_t t2_timeout
;
1539 uint64_t t1_timeout
;
1540 char time_string
[FORMAT_TIMESPAN_MAX
];
1544 assert(client
->event
);
1545 assert(client
->lease
);
1546 assert(client
->lease
->lifetime
);
1548 /* don't set timers for infinite leases */
1549 if (client
->lease
->lifetime
== 0xffffffff) {
1550 (void) event_source_disable(client
->timeout_t1
);
1551 (void) event_source_disable(client
->timeout_t2
);
1552 (void) event_source_disable(client
->timeout_expire
);
1557 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1560 assert(client
->request_sent
<= time_now
);
1562 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1563 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1564 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1565 /* both T1 and T2 are given */
1566 if (client
->lease
->t1
< client
->lease
->t2
&&
1567 client
->lease
->t2
< client
->lease
->lifetime
) {
1568 /* they are both valid */
1569 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1570 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1573 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1574 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1575 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1576 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1578 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1579 /* only T2 is given, and it is valid */
1580 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1581 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1582 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1583 if (t2_timeout
<= t1_timeout
) {
1584 /* the computed T1 would be invalid, so discard T2 */
1585 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1586 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1588 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1589 /* only T1 is given, and it is valid */
1590 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1591 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1592 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1593 if (t2_timeout
<= t1_timeout
) {
1594 /* the computed T2 would be invalid, so discard T1 */
1595 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1596 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1599 /* fall back to the default timeouts */
1600 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1601 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1602 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1603 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1606 /* arm lifetime timeout */
1607 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1608 clock_boottime_or_monotonic(),
1609 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1610 client_timeout_expire
, client
,
1611 client
->event_priority
, "dhcp4-lifetime", true);
1615 log_dhcp_client(client
, "lease expires in %s",
1616 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1618 /* don't arm earlier timeouts if this has already expired */
1619 if (lifetime_timeout
<= time_now
)
1622 /* arm T2 timeout */
1623 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1624 clock_boottime_or_monotonic(),
1625 t2_timeout
, 10 * USEC_PER_MSEC
,
1626 client_timeout_t2
, client
,
1627 client
->event_priority
, "dhcp4-t2-timeout", true);
1631 log_dhcp_client(client
, "T2 expires in %s",
1632 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1634 /* don't arm earlier timeout if this has already expired */
1635 if (t2_timeout
<= time_now
)
1638 /* arm T1 timeout */
1639 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1640 clock_boottime_or_monotonic(),
1641 t1_timeout
, 10 * USEC_PER_MSEC
,
1642 client_timeout_t1
, client
,
1643 client
->event_priority
, "dhcp4-t1-timer", true);
1647 log_dhcp_client(client
, "T1 expires in %s",
1648 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1653 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1654 DHCP_CLIENT_DONT_DESTROY(client
);
1655 char time_string
[FORMAT_TIMESPAN_MAX
];
1656 int r
= 0, notify_event
= 0;
1659 assert(client
->event
);
1662 switch (client
->state
) {
1663 case DHCP_STATE_SELECTING
:
1665 r
= client_handle_offer(client
, message
, len
);
1668 client
->state
= DHCP_STATE_REQUESTING
;
1669 client
->attempt
= 0;
1671 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1672 clock_boottime_or_monotonic(),
1674 client_timeout_resend
, client
,
1675 client
->event_priority
, "dhcp4-resend-timer", true);
1678 } else if (r
== -ENOMSG
)
1679 /* invalid message, let's ignore it */
1684 case DHCP_STATE_REBOOTING
:
1685 case DHCP_STATE_REQUESTING
:
1686 case DHCP_STATE_RENEWING
:
1687 case DHCP_STATE_REBINDING
:
1689 r
= client_handle_ack(client
, message
, len
);
1691 client
->start_delay
= 0;
1692 (void) event_source_disable(client
->timeout_resend
);
1693 client
->receive_message
=
1694 sd_event_source_unref(client
->receive_message
);
1695 client
->fd
= asynchronous_close(client
->fd
);
1697 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1698 DHCP_STATE_REBOOTING
))
1699 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1700 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1703 client
->state
= DHCP_STATE_BOUND
;
1704 client
->attempt
= 0;
1706 client
->last_addr
= client
->lease
->address
;
1708 r
= client_set_lease_timeouts(client
);
1710 log_dhcp_client(client
, "could not set lease timeouts");
1714 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1716 log_dhcp_client(client
, "could not bind UDP socket");
1722 client_initialize_io_events(client
, client_receive_message_udp
);
1725 client_notify(client
, notify_event
);
1726 if (client
->state
== DHCP_STATE_STOPPED
)
1730 } else if (r
== -EADDRNOTAVAIL
) {
1731 /* got a NAK, let's restart the client */
1732 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1734 r
= client_initialize(client
);
1738 r
= client_start_delayed(client
);
1742 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1743 client
->start_delay
, USEC_PER_SEC
));
1745 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1746 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1749 } else if (r
== -ENOMSG
)
1750 /* invalid message, let's ignore it */
1755 case DHCP_STATE_BOUND
:
1756 r
= client_handle_forcerenew(client
, message
, len
);
1758 r
= client_timeout_t1(NULL
, 0, client
);
1761 } else if (r
== -ENOMSG
)
1762 /* invalid message, let's ignore it */
1767 case DHCP_STATE_INIT
:
1768 case DHCP_STATE_INIT_REBOOT
:
1772 case DHCP_STATE_STOPPED
:
1779 client_stop(client
, r
);
1784 static int client_receive_message_udp(
1790 sd_dhcp_client
*client
= userdata
;
1791 _cleanup_free_ DHCPMessage
*message
= NULL
;
1792 const uint8_t *expected_chaddr
= NULL
;
1793 uint8_t expected_hlen
= 0;
1794 ssize_t len
, buflen
;
1799 buflen
= next_datagram_size_fd(fd
);
1800 if (buflen
== -ENETDOWN
) {
1801 /* the link is down. Don't return an error or the I/O event
1802 source will be disconnected and we won't be able to receive
1803 packets again when the link comes back. */
1809 message
= malloc0(buflen
);
1813 len
= recv(fd
, message
, buflen
, 0);
1815 /* see comment above for why we shouldn't error out on ENETDOWN. */
1816 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1819 return log_dhcp_client_errno(client
, errno
,
1820 "Could not receive message from UDP socket: %m");
1822 if ((size_t) len
< sizeof(DHCPMessage
)) {
1823 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1827 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1828 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1832 if (message
->op
!= BOOTREPLY
) {
1833 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1837 if (message
->htype
!= client
->arp_type
) {
1838 log_dhcp_client(client
, "Packet type does not match client type");
1842 if (client
->arp_type
== ARPHRD_ETHER
) {
1843 expected_hlen
= ETH_ALEN
;
1844 expected_chaddr
= &client
->mac_addr
[0];
1847 if (message
->hlen
!= expected_hlen
) {
1848 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1852 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1853 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1857 if (client
->state
!= DHCP_STATE_BOUND
&&
1858 be32toh(message
->xid
) != client
->xid
) {
1859 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1860 so ignore the xid in this case */
1861 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1862 be32toh(message
->xid
), client
->xid
);
1866 return client_handle_message(client
, message
, len
);
1869 static int client_receive_message_raw(
1875 sd_dhcp_client
*client
= userdata
;
1876 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1877 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1878 struct iovec iov
= {};
1879 struct msghdr msg
= {
1882 .msg_control
= cmsgbuf
,
1883 .msg_controllen
= sizeof(cmsgbuf
),
1885 struct cmsghdr
*cmsg
;
1886 bool checksum
= true;
1887 ssize_t buflen
, len
;
1893 buflen
= next_datagram_size_fd(fd
);
1894 if (buflen
== -ENETDOWN
)
1899 packet
= malloc0(buflen
);
1903 iov
= IOVEC_MAKE(packet
, buflen
);
1905 len
= recvmsg(fd
, &msg
, 0);
1907 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1910 return log_dhcp_client_errno(client
, errno
,
1911 "Could not receive message from raw socket: %m");
1912 } else if ((size_t)len
< sizeof(DHCPPacket
))
1915 CMSG_FOREACH(cmsg
, &msg
)
1916 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1917 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1918 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1919 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1921 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1925 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1929 len
-= DHCP_IP_UDP_SIZE
;
1931 return client_handle_message(client
, &packet
->dhcp
, len
);
1934 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1935 assert_return(client
, -EINVAL
);
1936 assert_return(client
->fd
>= 0, -EINVAL
);
1938 client
->start_delay
= 0;
1939 client
->attempt
= 1;
1940 client
->state
= DHCP_STATE_RENEWING
;
1942 return client_initialize_time_events(client
);
1945 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1948 assert_return(client
, -EINVAL
);
1950 r
= client_initialize(client
);
1954 /* RFC7844 section 3.3:
1955 SHOULD perform a complete four-way handshake, starting with a
1956 DHCPDISCOVER, to obtain a new address lease. If the client can
1957 ascertain that this is exactly the same network to which it was
1958 previously connected, and if the link-layer address did not change,
1959 the client MAY issue a DHCPREQUEST to try to reclaim the current
1961 if (client
->last_addr
&& !client
->anonymize
)
1962 client
->state
= DHCP_STATE_INIT_REBOOT
;
1964 r
= client_start(client
);
1966 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1971 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1972 assert_return(client
, -EINVAL
);
1973 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1974 assert_return(client
->lease
, -EUNATCH
);
1976 _cleanup_free_ DHCPPacket
*release
= NULL
;
1977 size_t optoffset
, optlen
;
1980 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
1984 /* Fill up release IP and MAC */
1985 release
->dhcp
.ciaddr
= client
->lease
->address
;
1986 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1988 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1989 SD_DHCP_OPTION_END
, 0, NULL
);
1993 r
= dhcp_network_send_udp_socket(client
->fd
,
1994 client
->lease
->server_address
,
1997 sizeof(DHCPMessage
) + optoffset
);
2001 log_dhcp_client(client
, "RELEASE");
2006 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2007 DHCP_CLIENT_DONT_DESTROY(client
);
2009 assert_return(client
, -EINVAL
);
2011 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2012 client
->state
= DHCP_STATE_STOPPED
;
2017 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2020 assert_return(client
, -EINVAL
);
2021 assert_return(!client
->event
, -EBUSY
);
2024 client
->event
= sd_event_ref(event
);
2026 r
= sd_event_default(&client
->event
);
2031 client
->event_priority
= priority
;
2036 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2037 assert_return(client
, -EINVAL
);
2039 client
->event
= sd_event_unref(client
->event
);
2044 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2045 assert_return(client
, NULL
);
2047 return client
->event
;
2050 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2054 log_dhcp_client(client
, "FREE");
2056 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2057 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2058 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2059 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2061 client_initialize(client
);
2063 sd_dhcp_client_detach_event(client
);
2065 sd_dhcp_lease_unref(client
->lease
);
2067 free(client
->req_opts
);
2068 free(client
->hostname
);
2069 free(client
->vendor_class_identifier
);
2070 client
->user_class
= strv_free(client
->user_class
);
2071 ordered_hashmap_free(client
->options
);
2072 return mfree(client
);
2075 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2077 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2078 assert_return(ret
, -EINVAL
);
2080 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2084 *client
= (sd_dhcp_client
) {
2086 .state
= DHCP_STATE_INIT
,
2089 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2090 .port
= DHCP_PORT_CLIENT
,
2091 .anonymize
= !!anonymize
,
2092 .max_attempts
= (uint64_t) -1,
2093 .ip_service_type
= -1,
2095 /* NOTE: this could be moved to a function. */
2097 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2098 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2100 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2101 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2103 if (!client
->req_opts
)
2106 *ret
= TAKE_PTR(client
);