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 _cleanup_(sd_dhcp_option_unrefp
) sd_dhcp_option
*p
= NULL
;
552 _cleanup_free_
void *q
= NULL
;
556 q
= memdup(data
, length
);
560 p
= new(sd_dhcp_option
, 1);
564 *p
= (sd_dhcp_option
) {
575 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option
, sd_dhcp_option
, dhcp_option_free
);
576 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
577 dhcp_option_hash_ops
,
580 trivial_compare_func
,
582 sd_dhcp_option_unref
);
584 int sd_dhcp_client_set_dhcp_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
587 assert_return(client
, -EINVAL
);
588 assert_return(v
, -EINVAL
);
590 r
= ordered_hashmap_ensure_allocated(&client
->options
, &dhcp_option_hash_ops
);
594 r
= ordered_hashmap_put(client
->options
, UINT_TO_PTR(v
->option
), v
);
598 sd_dhcp_option_ref(v
);
602 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
603 assert_return(client
, -EINVAL
);
605 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
606 return -EADDRNOTAVAIL
;
609 *ret
= client
->lease
;
614 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
615 assert_return(client
, -EINVAL
);
617 client
->ip_service_type
= type
;
622 static int client_notify(sd_dhcp_client
*client
, int event
) {
625 if (client
->callback
)
626 return client
->callback(client
, event
, client
->userdata
);
631 static int client_initialize(sd_dhcp_client
*client
) {
632 assert_return(client
, -EINVAL
);
634 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
636 client
->fd
= asynchronous_close(client
->fd
);
638 (void) event_source_disable(client
->timeout_resend
);
639 (void) event_source_disable(client
->timeout_t1
);
640 (void) event_source_disable(client
->timeout_t2
);
641 (void) event_source_disable(client
->timeout_expire
);
645 client
->state
= DHCP_STATE_INIT
;
648 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
653 static void client_stop(sd_dhcp_client
*client
, int error
) {
657 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
658 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
659 log_dhcp_client(client
, "STOPPED");
661 log_dhcp_client(client
, "STOPPED: Unknown event");
663 client_notify(client
, error
);
665 client_initialize(client
);
668 static int client_message_init(
669 sd_dhcp_client
*client
,
673 size_t *_optoffset
) {
675 _cleanup_free_ DHCPPacket
*packet
= NULL
;
676 size_t optlen
, optoffset
, size
;
683 assert(client
->start_time
);
687 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
));
689 optlen
= DHCP_MIN_OPTIONS_SIZE
;
690 size
= sizeof(DHCPPacket
) + optlen
;
692 packet
= malloc0(size
);
696 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
697 client
->arp_type
, optlen
, &optoffset
);
701 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
702 refuse to issue an DHCP lease if 'secs' is set to zero */
703 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
706 assert(time_now
>= client
->start_time
);
708 /* seconds between sending first and last DISCOVER
709 * must always be strictly positive to deal with broken servers */
710 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
711 packet
->dhcp
.secs
= htobe16(secs
);
713 /* RFC2132 section 4.1
714 A client that cannot receive unicast IP datagrams until its protocol
715 software has been configured with an IP address SHOULD set the
716 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
717 DHCPREQUEST messages that client sends. The BROADCAST bit will
718 provide a hint to the DHCP server and BOOTP relay agent to broadcast
719 any messages to the client on the client's subnet.
721 Note: some interfaces needs this to be enabled, but some networks
722 needs this to be disabled as broadcasts are filteretd, so this
723 needs to be configurable */
724 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
725 packet
->dhcp
.flags
= htobe16(0x8000);
727 /* RFC2132 section 4.1.1:
728 The client MUST include its hardware address in the ’chaddr’ field, if
729 necessary for delivery of DHCP reply messages. Non-Ethernet
730 interfaces will leave 'chaddr' empty and use the client identifier
731 instead (eg, RFC 4390 section 2.1).
733 if (client
->arp_type
== ARPHRD_ETHER
)
734 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
736 /* If no client identifier exists, construct an RFC 4361-compliant one */
737 if (client
->client_id_len
== 0) {
740 client
->client_id
.type
= 255;
742 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
743 true, &client
->client_id
.ns
.iaid
);
747 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
751 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
754 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
755 Identifier option is not set */
756 if (client
->client_id_len
) {
757 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
758 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
759 client
->client_id_len
,
765 /* RFC2131 section 3.5:
766 in its initial DHCPDISCOVER or DHCPREQUEST message, a
767 client may provide the server with a list of specific
768 parameters the client is interested in. If the client
769 includes a list of parameters in a DHCPDISCOVER message,
770 it MUST include that list in any subsequent DHCPREQUEST
774 /* RFC7844 section 3:
775 MAY contain the Parameter Request List option. */
776 /* NOTE: in case that there would be an option to do not send
777 * any PRL at all, the size should be checked before sending */
778 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
779 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
780 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
781 client
->req_opts_size
, client
->req_opts
);
786 /* RFC2131 section 3.5:
787 The client SHOULD include the ’maximum DHCP message size’ option to
788 let the server know how large the server may make its DHCP messages.
790 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
791 than the defined default size unless the Maximum Message Size option
794 RFC3442 "Requirements to Avoid Sizing Constraints":
795 Because a full routing table can be quite large, the standard 576
796 octet maximum size for a DHCP message may be too short to contain
797 some legitimate Classless Static Route options. Because of this,
798 clients implementing the Classless Static Route option SHOULD send a
799 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
800 stack is capable of receiving larger IP datagrams. In this case, the
801 client SHOULD set the value of this option to at least the MTU of the
802 interface that the client is configuring. The client MAY set the
803 value of this option higher, up to the size of the largest UDP packet
804 it is prepared to accept. (Note that the value specified in the
805 Maximum DHCP Message Size option is the total maximum packet size,
806 including IP and UDP headers.)
808 /* RFC7844 section 3:
809 SHOULD NOT contain any other option. */
810 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
811 max_size
= htobe16(size
);
812 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
813 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
820 *_optoffset
= optoffset
;
821 *ret
= TAKE_PTR(packet
);
826 static int client_append_fqdn_option(
827 DHCPMessage
*message
,
832 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
835 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
836 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
837 buffer
[1] = 0; /* RCODE1 (deprecated) */
838 buffer
[2] = 0; /* RCODE2 (deprecated) */
840 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
842 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
843 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
848 static int dhcp_client_send_raw(
849 sd_dhcp_client
*client
,
853 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
854 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
856 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
860 static int client_send_discover(sd_dhcp_client
*client
) {
861 _cleanup_free_ DHCPPacket
*discover
= NULL
;
862 size_t optoffset
, optlen
;
868 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
870 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
871 &optlen
, &optoffset
);
875 /* the client may suggest values for the network address
876 and lease time in the DHCPDISCOVER message. The client may include
877 the ’requested IP address’ option to suggest that a particular IP
878 address be assigned, and may include the ’IP address lease time’
879 option to suggest the lease time it would like.
881 if (client
->last_addr
!= INADDR_ANY
) {
882 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
883 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
884 4, &client
->last_addr
);
889 if (client
->hostname
) {
890 /* According to RFC 4702 "clients that send the Client FQDN option in
891 their messages MUST NOT also send the Host Name option". Just send
892 one of the two depending on the hostname type.
894 if (dns_name_is_single_label(client
->hostname
)) {
895 /* it is unclear from RFC 2131 if client should send hostname in
896 DHCPDISCOVER but dhclient does and so we do as well
898 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
899 SD_DHCP_OPTION_HOST_NAME
,
900 strlen(client
->hostname
), client
->hostname
);
902 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
908 if (client
->vendor_class_identifier
) {
909 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
910 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
911 strlen(client
->vendor_class_identifier
),
912 client
->vendor_class_identifier
);
917 if (client
->user_class
) {
918 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
919 SD_DHCP_OPTION_USER_CLASS
,
920 strv_length(client
->user_class
),
926 ORDERED_HASHMAP_FOREACH(j
, client
->options
, i
) {
927 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
928 j
->option
, j
->length
, j
->data
);
933 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
934 SD_DHCP_OPTION_END
, 0, NULL
);
938 /* We currently ignore:
939 The client SHOULD wait a random time between one and ten seconds to
940 desynchronize the use of DHCP at startup.
942 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
946 log_dhcp_client(client
, "DISCOVER");
951 static int client_send_request(sd_dhcp_client
*client
) {
952 _cleanup_free_ DHCPPacket
*request
= NULL
;
953 size_t optoffset
, optlen
;
958 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
962 switch (client
->state
) {
963 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
964 SELECTING should be REQUESTING)
967 case DHCP_STATE_REQUESTING
:
968 /* Client inserts the address of the selected server in ’server
969 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
970 filled in with the yiaddr value from the chosen DHCPOFFER.
973 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
974 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
975 4, &client
->lease
->server_address
);
979 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
980 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
981 4, &client
->lease
->address
);
987 case DHCP_STATE_INIT_REBOOT
:
988 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
989 option MUST be filled in with client’s notion of its previously
990 assigned address. ’ciaddr’ MUST be zero.
992 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
993 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
994 4, &client
->last_addr
);
999 case DHCP_STATE_RENEWING
:
1000 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1001 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1002 client’s IP address.
1005 case DHCP_STATE_REBINDING
:
1006 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1007 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1008 client’s IP address.
1010 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1012 request
->dhcp
.ciaddr
= client
->lease
->address
;
1016 case DHCP_STATE_INIT
:
1017 case DHCP_STATE_SELECTING
:
1018 case DHCP_STATE_REBOOTING
:
1019 case DHCP_STATE_BOUND
:
1020 case DHCP_STATE_STOPPED
:
1024 if (client
->hostname
) {
1025 if (dns_name_is_single_label(client
->hostname
))
1026 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1027 SD_DHCP_OPTION_HOST_NAME
,
1028 strlen(client
->hostname
), client
->hostname
);
1030 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
1036 if (client
->vendor_class_identifier
) {
1037 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1038 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1039 strlen(client
->vendor_class_identifier
),
1040 client
->vendor_class_identifier
);
1045 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1046 SD_DHCP_OPTION_END
, 0, NULL
);
1050 if (client
->state
== DHCP_STATE_RENEWING
)
1051 r
= dhcp_network_send_udp_socket(client
->fd
,
1052 client
->lease
->server_address
,
1055 sizeof(DHCPMessage
) + optoffset
);
1057 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1061 switch (client
->state
) {
1063 case DHCP_STATE_REQUESTING
:
1064 log_dhcp_client(client
, "REQUEST (requesting)");
1067 case DHCP_STATE_INIT_REBOOT
:
1068 log_dhcp_client(client
, "REQUEST (init-reboot)");
1071 case DHCP_STATE_RENEWING
:
1072 log_dhcp_client(client
, "REQUEST (renewing)");
1075 case DHCP_STATE_REBINDING
:
1076 log_dhcp_client(client
, "REQUEST (rebinding)");
1080 log_dhcp_client(client
, "REQUEST (invalid)");
1087 static int client_start(sd_dhcp_client
*client
);
1089 static int client_timeout_resend(
1094 sd_dhcp_client
*client
= userdata
;
1095 DHCP_CLIENT_DONT_DESTROY(client
);
1096 usec_t next_timeout
= 0;
1103 assert(client
->event
);
1105 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1109 switch (client
->state
) {
1111 case DHCP_STATE_RENEWING
:
1113 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1117 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1121 case DHCP_STATE_REBINDING
:
1123 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1127 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1130 case DHCP_STATE_REBOOTING
:
1131 /* start over as we did not receive a timely ack or nak */
1132 r
= client_initialize(client
);
1136 r
= client_start(client
);
1140 log_dhcp_client(client
, "REBOOTED");
1144 case DHCP_STATE_INIT
:
1145 case DHCP_STATE_INIT_REBOOT
:
1146 case DHCP_STATE_SELECTING
:
1147 case DHCP_STATE_REQUESTING
:
1148 case DHCP_STATE_BOUND
:
1150 if (client
->attempt
< client
->max_attempts
)
1155 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1159 case DHCP_STATE_STOPPED
:
1164 next_timeout
+= (random_u32() & 0x1fffff);
1166 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1167 clock_boottime_or_monotonic(),
1168 next_timeout
, 10 * USEC_PER_MSEC
,
1169 client_timeout_resend
, client
,
1170 client
->event_priority
, "dhcp4-resend-timer", true);
1174 switch (client
->state
) {
1175 case DHCP_STATE_INIT
:
1176 r
= client_send_discover(client
);
1178 client
->state
= DHCP_STATE_SELECTING
;
1179 client
->attempt
= 0;
1180 } else if (client
->attempt
>= client
->max_attempts
)
1185 case DHCP_STATE_SELECTING
:
1186 r
= client_send_discover(client
);
1187 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1192 case DHCP_STATE_INIT_REBOOT
:
1193 case DHCP_STATE_REQUESTING
:
1194 case DHCP_STATE_RENEWING
:
1195 case DHCP_STATE_REBINDING
:
1196 r
= client_send_request(client
);
1197 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1200 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1201 client
->state
= DHCP_STATE_REBOOTING
;
1203 client
->request_sent
= time_now
;
1207 case DHCP_STATE_REBOOTING
:
1208 case DHCP_STATE_BOUND
:
1212 case DHCP_STATE_STOPPED
:
1220 client_stop(client
, r
);
1222 /* Errors were dealt with when stopping the client, don't spill
1223 errors into the event loop handler */
1227 static int client_initialize_io_events(
1228 sd_dhcp_client
*client
,
1229 sd_event_io_handler_t io_callback
) {
1234 assert(client
->event
);
1236 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1237 client
->fd
, EPOLLIN
, io_callback
,
1242 r
= sd_event_source_set_priority(client
->receive_message
,
1243 client
->event_priority
);
1247 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1253 client_stop(client
, r
);
1258 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1263 assert(client
->event
);
1265 if (client
->start_delay
> 0) {
1266 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1267 usec
+= client
->start_delay
;
1270 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1271 clock_boottime_or_monotonic(),
1273 client_timeout_resend
, client
,
1274 client
->event_priority
, "dhcp4-resend-timer", true);
1276 client_stop(client
, r
);
1282 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1283 client_initialize_io_events(client
, io_callback
);
1284 client_initialize_time_events(client
);
1289 static int client_start_delayed(sd_dhcp_client
*client
) {
1292 assert_return(client
, -EINVAL
);
1293 assert_return(client
->event
, -EINVAL
);
1294 assert_return(client
->ifindex
> 0, -EINVAL
);
1295 assert_return(client
->fd
< 0, -EBUSY
);
1296 assert_return(client
->xid
== 0, -EINVAL
);
1297 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1299 client
->xid
= random_u32();
1301 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1302 client
->xid
, client
->mac_addr
,
1303 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1305 client_stop(client
, r
);
1310 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1311 client
->start_time
= now(clock_boottime_or_monotonic());
1313 return client_initialize_events(client
, client_receive_message_raw
);
1316 static int client_start(sd_dhcp_client
*client
) {
1317 client
->start_delay
= 0;
1318 return client_start_delayed(client
);
1321 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1322 sd_dhcp_client
*client
= userdata
;
1323 DHCP_CLIENT_DONT_DESTROY(client
);
1325 log_dhcp_client(client
, "EXPIRED");
1327 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1329 /* lease was lost, start over if not freed or stopped in callback */
1330 if (client
->state
!= DHCP_STATE_STOPPED
) {
1331 client_initialize(client
);
1332 client_start(client
);
1338 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1339 sd_dhcp_client
*client
= userdata
;
1340 DHCP_CLIENT_DONT_DESTROY(client
);
1345 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1346 client
->fd
= asynchronous_close(client
->fd
);
1348 client
->state
= DHCP_STATE_REBINDING
;
1349 client
->attempt
= 0;
1351 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1352 client
->xid
, client
->mac_addr
,
1353 client
->mac_addr_len
, client
->arp_type
,
1356 client_stop(client
, r
);
1361 return client_initialize_events(client
, client_receive_message_raw
);
1364 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1365 sd_dhcp_client
*client
= userdata
;
1366 DHCP_CLIENT_DONT_DESTROY(client
);
1368 client
->state
= DHCP_STATE_RENEWING
;
1369 client
->attempt
= 0;
1371 return client_initialize_time_events(client
);
1374 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1375 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1378 r
= dhcp_lease_new(&lease
);
1382 if (client
->client_id_len
) {
1383 r
= dhcp_lease_set_client_id(lease
,
1384 (uint8_t *) &client
->client_id
,
1385 client
->client_id_len
);
1390 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1391 if (r
!= DHCP_OFFER
) {
1392 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1396 lease
->next_server
= offer
->siaddr
;
1397 lease
->address
= offer
->yiaddr
;
1399 if (lease
->address
== 0 ||
1400 lease
->server_address
== 0 ||
1401 lease
->lifetime
== 0) {
1402 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1406 if (!lease
->have_subnet_mask
) {
1407 r
= dhcp_lease_set_default_subnet_mask(lease
);
1409 log_dhcp_client(client
,
1410 "received lease lacks subnet mask, "
1411 "and a fallback one cannot be generated, ignoring");
1416 sd_dhcp_lease_unref(client
->lease
);
1417 client
->lease
= TAKE_PTR(lease
);
1419 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1422 log_dhcp_client(client
, "OFFER");
1427 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1430 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1431 if (r
!= DHCP_FORCERENEW
)
1434 log_dhcp_client(client
, "FORCERENEW");
1439 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1440 if (a
->address
!= b
->address
)
1443 if (a
->subnet_mask
!= b
->subnet_mask
)
1446 if (a
->router_size
!= b
->router_size
)
1449 for (size_t i
= 0; i
< a
->router_size
; i
++)
1450 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1456 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1457 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1458 _cleanup_free_
char *error_message
= NULL
;
1461 r
= dhcp_lease_new(&lease
);
1465 if (client
->client_id_len
) {
1466 r
= dhcp_lease_set_client_id(lease
,
1467 (uint8_t *) &client
->client_id
,
1468 client
->client_id_len
);
1473 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1474 if (r
== DHCP_NAK
) {
1475 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1476 return -EADDRNOTAVAIL
;
1479 if (r
!= DHCP_ACK
) {
1480 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1484 lease
->next_server
= ack
->siaddr
;
1486 lease
->address
= ack
->yiaddr
;
1488 if (lease
->address
== INADDR_ANY
||
1489 lease
->server_address
== INADDR_ANY
||
1490 lease
->lifetime
== 0) {
1491 log_dhcp_client(client
, "received lease lacks address, server "
1492 "address or lease lifetime, ignoring");
1496 if (lease
->subnet_mask
== INADDR_ANY
) {
1497 r
= dhcp_lease_set_default_subnet_mask(lease
);
1499 log_dhcp_client(client
,
1500 "received lease lacks subnet mask, "
1501 "and a fallback one cannot be generated, ignoring");
1506 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1507 if (client
->lease
) {
1508 if (lease_equal(client
->lease
, lease
))
1509 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1511 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1513 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1516 client
->lease
= TAKE_PTR(lease
);
1518 log_dhcp_client(client
, "ACK");
1523 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1525 assert(client
->request_sent
);
1526 assert(lifetime
> 0);
1533 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1534 + (random_u32() & 0x1fffff);
1537 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1539 uint64_t lifetime_timeout
;
1540 uint64_t t2_timeout
;
1541 uint64_t t1_timeout
;
1542 char time_string
[FORMAT_TIMESPAN_MAX
];
1546 assert(client
->event
);
1547 assert(client
->lease
);
1548 assert(client
->lease
->lifetime
);
1550 /* don't set timers for infinite leases */
1551 if (client
->lease
->lifetime
== 0xffffffff) {
1552 (void) event_source_disable(client
->timeout_t1
);
1553 (void) event_source_disable(client
->timeout_t2
);
1554 (void) event_source_disable(client
->timeout_expire
);
1559 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1562 assert(client
->request_sent
<= time_now
);
1564 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1565 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1566 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1567 /* both T1 and T2 are given */
1568 if (client
->lease
->t1
< client
->lease
->t2
&&
1569 client
->lease
->t2
< client
->lease
->lifetime
) {
1570 /* they are both valid */
1571 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1572 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1575 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1576 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1577 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1578 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1580 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1581 /* only T2 is given, and it is valid */
1582 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1583 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1584 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1585 if (t2_timeout
<= t1_timeout
) {
1586 /* the computed T1 would be invalid, so discard T2 */
1587 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1588 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1590 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1591 /* only T1 is given, and it is valid */
1592 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1593 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1594 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1595 if (t2_timeout
<= t1_timeout
) {
1596 /* the computed T2 would be invalid, so discard T1 */
1597 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1598 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1601 /* fall back to the default timeouts */
1602 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1603 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1604 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1605 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1608 /* arm lifetime timeout */
1609 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1610 clock_boottime_or_monotonic(),
1611 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1612 client_timeout_expire
, client
,
1613 client
->event_priority
, "dhcp4-lifetime", true);
1617 log_dhcp_client(client
, "lease expires in %s",
1618 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1620 /* don't arm earlier timeouts if this has already expired */
1621 if (lifetime_timeout
<= time_now
)
1624 /* arm T2 timeout */
1625 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1626 clock_boottime_or_monotonic(),
1627 t2_timeout
, 10 * USEC_PER_MSEC
,
1628 client_timeout_t2
, client
,
1629 client
->event_priority
, "dhcp4-t2-timeout", true);
1633 log_dhcp_client(client
, "T2 expires in %s",
1634 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1636 /* don't arm earlier timeout if this has already expired */
1637 if (t2_timeout
<= time_now
)
1640 /* arm T1 timeout */
1641 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1642 clock_boottime_or_monotonic(),
1643 t1_timeout
, 10 * USEC_PER_MSEC
,
1644 client_timeout_t1
, client
,
1645 client
->event_priority
, "dhcp4-t1-timer", true);
1649 log_dhcp_client(client
, "T1 expires in %s",
1650 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1655 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1656 DHCP_CLIENT_DONT_DESTROY(client
);
1657 char time_string
[FORMAT_TIMESPAN_MAX
];
1658 int r
= 0, notify_event
= 0;
1661 assert(client
->event
);
1664 switch (client
->state
) {
1665 case DHCP_STATE_SELECTING
:
1667 r
= client_handle_offer(client
, message
, len
);
1670 client
->state
= DHCP_STATE_REQUESTING
;
1671 client
->attempt
= 0;
1673 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1674 clock_boottime_or_monotonic(),
1676 client_timeout_resend
, client
,
1677 client
->event_priority
, "dhcp4-resend-timer", true);
1680 } else if (r
== -ENOMSG
)
1681 /* invalid message, let's ignore it */
1686 case DHCP_STATE_REBOOTING
:
1687 case DHCP_STATE_REQUESTING
:
1688 case DHCP_STATE_RENEWING
:
1689 case DHCP_STATE_REBINDING
:
1691 r
= client_handle_ack(client
, message
, len
);
1693 client
->start_delay
= 0;
1694 (void) event_source_disable(client
->timeout_resend
);
1695 client
->receive_message
=
1696 sd_event_source_unref(client
->receive_message
);
1697 client
->fd
= asynchronous_close(client
->fd
);
1699 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1700 DHCP_STATE_REBOOTING
))
1701 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1702 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1705 client
->state
= DHCP_STATE_BOUND
;
1706 client
->attempt
= 0;
1708 client
->last_addr
= client
->lease
->address
;
1710 r
= client_set_lease_timeouts(client
);
1712 log_dhcp_client(client
, "could not set lease timeouts");
1716 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1718 log_dhcp_client(client
, "could not bind UDP socket");
1724 client_initialize_io_events(client
, client_receive_message_udp
);
1727 client_notify(client
, notify_event
);
1728 if (client
->state
== DHCP_STATE_STOPPED
)
1732 } else if (r
== -EADDRNOTAVAIL
) {
1733 /* got a NAK, let's restart the client */
1734 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1736 r
= client_initialize(client
);
1740 r
= client_start_delayed(client
);
1744 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1745 client
->start_delay
, USEC_PER_SEC
));
1747 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1748 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1751 } else if (r
== -ENOMSG
)
1752 /* invalid message, let's ignore it */
1757 case DHCP_STATE_BOUND
:
1758 r
= client_handle_forcerenew(client
, message
, len
);
1760 r
= client_timeout_t1(NULL
, 0, client
);
1763 } else if (r
== -ENOMSG
)
1764 /* invalid message, let's ignore it */
1769 case DHCP_STATE_INIT
:
1770 case DHCP_STATE_INIT_REBOOT
:
1774 case DHCP_STATE_STOPPED
:
1781 client_stop(client
, r
);
1786 static int client_receive_message_udp(
1792 sd_dhcp_client
*client
= userdata
;
1793 _cleanup_free_ DHCPMessage
*message
= NULL
;
1794 const uint8_t *expected_chaddr
= NULL
;
1795 uint8_t expected_hlen
= 0;
1796 ssize_t len
, buflen
;
1801 buflen
= next_datagram_size_fd(fd
);
1802 if (buflen
== -ENETDOWN
) {
1803 /* the link is down. Don't return an error or the I/O event
1804 source will be disconnected and we won't be able to receive
1805 packets again when the link comes back. */
1811 message
= malloc0(buflen
);
1815 len
= recv(fd
, message
, buflen
, 0);
1817 /* see comment above for why we shouldn't error out on ENETDOWN. */
1818 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1821 return log_dhcp_client_errno(client
, errno
,
1822 "Could not receive message from UDP socket: %m");
1824 if ((size_t) len
< sizeof(DHCPMessage
)) {
1825 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1829 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1830 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1834 if (message
->op
!= BOOTREPLY
) {
1835 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1839 if (message
->htype
!= client
->arp_type
) {
1840 log_dhcp_client(client
, "Packet type does not match client type");
1844 if (client
->arp_type
== ARPHRD_ETHER
) {
1845 expected_hlen
= ETH_ALEN
;
1846 expected_chaddr
= &client
->mac_addr
[0];
1849 if (message
->hlen
!= expected_hlen
) {
1850 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1854 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1855 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1859 if (client
->state
!= DHCP_STATE_BOUND
&&
1860 be32toh(message
->xid
) != client
->xid
) {
1861 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1862 so ignore the xid in this case */
1863 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1864 be32toh(message
->xid
), client
->xid
);
1868 return client_handle_message(client
, message
, len
);
1871 static int client_receive_message_raw(
1877 sd_dhcp_client
*client
= userdata
;
1878 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1879 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1880 struct iovec iov
= {};
1881 struct msghdr msg
= {
1884 .msg_control
= cmsgbuf
,
1885 .msg_controllen
= sizeof(cmsgbuf
),
1887 struct cmsghdr
*cmsg
;
1888 bool checksum
= true;
1889 ssize_t buflen
, len
;
1895 buflen
= next_datagram_size_fd(fd
);
1896 if (buflen
== -ENETDOWN
)
1901 packet
= malloc0(buflen
);
1905 iov
= IOVEC_MAKE(packet
, buflen
);
1907 len
= recvmsg(fd
, &msg
, 0);
1909 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1912 return log_dhcp_client_errno(client
, errno
,
1913 "Could not receive message from raw socket: %m");
1914 } else if ((size_t)len
< sizeof(DHCPPacket
))
1917 CMSG_FOREACH(cmsg
, &msg
)
1918 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1919 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1920 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1921 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1923 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1927 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1931 len
-= DHCP_IP_UDP_SIZE
;
1933 return client_handle_message(client
, &packet
->dhcp
, len
);
1936 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1937 assert_return(client
, -EINVAL
);
1938 assert_return(client
->fd
>= 0, -EINVAL
);
1940 client
->start_delay
= 0;
1941 client
->attempt
= 1;
1942 client
->state
= DHCP_STATE_RENEWING
;
1944 return client_initialize_time_events(client
);
1947 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1950 assert_return(client
, -EINVAL
);
1952 r
= client_initialize(client
);
1956 /* RFC7844 section 3.3:
1957 SHOULD perform a complete four-way handshake, starting with a
1958 DHCPDISCOVER, to obtain a new address lease. If the client can
1959 ascertain that this is exactly the same network to which it was
1960 previously connected, and if the link-layer address did not change,
1961 the client MAY issue a DHCPREQUEST to try to reclaim the current
1963 if (client
->last_addr
&& !client
->anonymize
)
1964 client
->state
= DHCP_STATE_INIT_REBOOT
;
1966 r
= client_start(client
);
1968 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1973 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1974 assert_return(client
, -EINVAL
);
1975 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1976 assert_return(client
->lease
, -EUNATCH
);
1978 _cleanup_free_ DHCPPacket
*release
= NULL
;
1979 size_t optoffset
, optlen
;
1982 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
1986 /* Fill up release IP and MAC */
1987 release
->dhcp
.ciaddr
= client
->lease
->address
;
1988 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1990 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1991 SD_DHCP_OPTION_END
, 0, NULL
);
1995 r
= dhcp_network_send_udp_socket(client
->fd
,
1996 client
->lease
->server_address
,
1999 sizeof(DHCPMessage
) + optoffset
);
2003 log_dhcp_client(client
, "RELEASE");
2008 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2009 DHCP_CLIENT_DONT_DESTROY(client
);
2011 assert_return(client
, -EINVAL
);
2013 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2014 client
->state
= DHCP_STATE_STOPPED
;
2019 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2022 assert_return(client
, -EINVAL
);
2023 assert_return(!client
->event
, -EBUSY
);
2026 client
->event
= sd_event_ref(event
);
2028 r
= sd_event_default(&client
->event
);
2033 client
->event_priority
= priority
;
2038 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2039 assert_return(client
, -EINVAL
);
2041 client
->event
= sd_event_unref(client
->event
);
2046 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2047 assert_return(client
, NULL
);
2049 return client
->event
;
2052 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2055 log_dhcp_client(client
, "FREE");
2057 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2058 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2059 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2060 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2062 client_initialize(client
);
2064 sd_dhcp_client_detach_event(client
);
2066 sd_dhcp_lease_unref(client
->lease
);
2068 free(client
->req_opts
);
2069 free(client
->hostname
);
2070 free(client
->vendor_class_identifier
);
2071 client
->user_class
= strv_free(client
->user_class
);
2072 ordered_hashmap_free(client
->options
);
2073 return mfree(client
);
2076 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2078 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2079 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
2081 assert_return(ret
, -EINVAL
);
2083 client
= new(sd_dhcp_client
, 1);
2087 *client
= (sd_dhcp_client
) {
2089 .state
= DHCP_STATE_INIT
,
2092 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2093 .port
= DHCP_PORT_CLIENT
,
2094 .anonymize
= !!anonymize
,
2095 .max_attempts
= (uint64_t) -1,
2096 .ip_service_type
= -1,
2098 /* NOTE: this could be moved to a function. */
2100 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2101 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2103 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2104 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2106 if (!client
->req_opts
)
2109 *ret
= TAKE_PTR(client
);