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
) {
553 _cleanup_free_
void *q
= memdup(data
, length
);
557 sd_dhcp_option
*p
= new(sd_dhcp_option
, 1);
561 *p
= (sd_dhcp_option
) {
572 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option
, sd_dhcp_option
, dhcp_option_free
);
573 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
574 dhcp_option_hash_ops
,
577 trivial_compare_func
,
579 sd_dhcp_option_unref
);
581 int sd_dhcp_client_set_dhcp_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
584 assert_return(client
, -EINVAL
);
585 assert_return(v
, -EINVAL
);
587 r
= ordered_hashmap_ensure_allocated(&client
->options
, &dhcp_option_hash_ops
);
591 r
= ordered_hashmap_put(client
->options
, UINT_TO_PTR(v
->option
), v
);
595 sd_dhcp_option_ref(v
);
599 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
600 assert_return(client
, -EINVAL
);
602 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
603 return -EADDRNOTAVAIL
;
606 *ret
= client
->lease
;
611 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
612 assert_return(client
, -EINVAL
);
614 client
->ip_service_type
= type
;
619 static int client_notify(sd_dhcp_client
*client
, int event
) {
622 if (client
->callback
)
623 return client
->callback(client
, event
, client
->userdata
);
628 static int client_initialize(sd_dhcp_client
*client
) {
629 assert_return(client
, -EINVAL
);
631 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
633 client
->fd
= asynchronous_close(client
->fd
);
635 (void) event_source_disable(client
->timeout_resend
);
636 (void) event_source_disable(client
->timeout_t1
);
637 (void) event_source_disable(client
->timeout_t2
);
638 (void) event_source_disable(client
->timeout_expire
);
642 client
->state
= DHCP_STATE_INIT
;
645 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
650 static void client_stop(sd_dhcp_client
*client
, int error
) {
654 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
655 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
656 log_dhcp_client(client
, "STOPPED");
658 log_dhcp_client(client
, "STOPPED: Unknown event");
660 client_notify(client
, error
);
662 client_initialize(client
);
665 static int client_message_init(
666 sd_dhcp_client
*client
,
670 size_t *_optoffset
) {
672 _cleanup_free_ DHCPPacket
*packet
= NULL
;
673 size_t optlen
, optoffset
, size
;
680 assert(client
->start_time
);
684 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
));
686 optlen
= DHCP_MIN_OPTIONS_SIZE
;
687 size
= sizeof(DHCPPacket
) + optlen
;
689 packet
= malloc0(size
);
693 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
694 client
->arp_type
, optlen
, &optoffset
);
698 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
699 refuse to issue an DHCP lease if 'secs' is set to zero */
700 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
703 assert(time_now
>= client
->start_time
);
705 /* seconds between sending first and last DISCOVER
706 * must always be strictly positive to deal with broken servers */
707 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
708 packet
->dhcp
.secs
= htobe16(secs
);
710 /* RFC2132 section 4.1
711 A client that cannot receive unicast IP datagrams until its protocol
712 software has been configured with an IP address SHOULD set the
713 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
714 DHCPREQUEST messages that client sends. The BROADCAST bit will
715 provide a hint to the DHCP server and BOOTP relay agent to broadcast
716 any messages to the client on the client's subnet.
718 Note: some interfaces needs this to be enabled, but some networks
719 needs this to be disabled as broadcasts are filteretd, so this
720 needs to be configurable */
721 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
722 packet
->dhcp
.flags
= htobe16(0x8000);
724 /* RFC2132 section 4.1.1:
725 The client MUST include its hardware address in the ’chaddr’ field, if
726 necessary for delivery of DHCP reply messages. Non-Ethernet
727 interfaces will leave 'chaddr' empty and use the client identifier
728 instead (eg, RFC 4390 section 2.1).
730 if (client
->arp_type
== ARPHRD_ETHER
)
731 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
733 /* If no client identifier exists, construct an RFC 4361-compliant one */
734 if (client
->client_id_len
== 0) {
737 client
->client_id
.type
= 255;
739 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
740 true, &client
->client_id
.ns
.iaid
);
744 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
748 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
751 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
752 Identifier option is not set */
753 if (client
->client_id_len
) {
754 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
755 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
756 client
->client_id_len
,
762 /* RFC2131 section 3.5:
763 in its initial DHCPDISCOVER or DHCPREQUEST message, a
764 client may provide the server with a list of specific
765 parameters the client is interested in. If the client
766 includes a list of parameters in a DHCPDISCOVER message,
767 it MUST include that list in any subsequent DHCPREQUEST
771 /* RFC7844 section 3:
772 MAY contain the Parameter Request List option. */
773 /* NOTE: in case that there would be an option to do not send
774 * any PRL at all, the size should be checked before sending */
775 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
776 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
777 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
778 client
->req_opts_size
, client
->req_opts
);
783 /* RFC2131 section 3.5:
784 The client SHOULD include the ’maximum DHCP message size’ option to
785 let the server know how large the server may make its DHCP messages.
787 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
788 than the defined default size unless the Maximum Message Size option
791 RFC3442 "Requirements to Avoid Sizing Constraints":
792 Because a full routing table can be quite large, the standard 576
793 octet maximum size for a DHCP message may be too short to contain
794 some legitimate Classless Static Route options. Because of this,
795 clients implementing the Classless Static Route option SHOULD send a
796 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
797 stack is capable of receiving larger IP datagrams. In this case, the
798 client SHOULD set the value of this option to at least the MTU of the
799 interface that the client is configuring. The client MAY set the
800 value of this option higher, up to the size of the largest UDP packet
801 it is prepared to accept. (Note that the value specified in the
802 Maximum DHCP Message Size option is the total maximum packet size,
803 including IP and UDP headers.)
805 /* RFC7844 section 3:
806 SHOULD NOT contain any other option. */
807 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
808 max_size
= htobe16(size
);
809 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
810 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
817 *_optoffset
= optoffset
;
818 *ret
= TAKE_PTR(packet
);
823 static int client_append_fqdn_option(
824 DHCPMessage
*message
,
829 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
832 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
833 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
834 buffer
[1] = 0; /* RCODE1 (deprecated) */
835 buffer
[2] = 0; /* RCODE2 (deprecated) */
837 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
839 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
840 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
845 static int dhcp_client_send_raw(
846 sd_dhcp_client
*client
,
850 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
851 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
853 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
857 static int client_send_discover(sd_dhcp_client
*client
) {
858 _cleanup_free_ DHCPPacket
*discover
= NULL
;
859 size_t optoffset
, optlen
;
865 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
867 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
868 &optlen
, &optoffset
);
872 /* the client may suggest values for the network address
873 and lease time in the DHCPDISCOVER message. The client may include
874 the ’requested IP address’ option to suggest that a particular IP
875 address be assigned, and may include the ’IP address lease time’
876 option to suggest the lease time it would like.
878 if (client
->last_addr
!= INADDR_ANY
) {
879 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
880 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
881 4, &client
->last_addr
);
886 if (client
->hostname
) {
887 /* According to RFC 4702 "clients that send the Client FQDN option in
888 their messages MUST NOT also send the Host Name option". Just send
889 one of the two depending on the hostname type.
891 if (dns_name_is_single_label(client
->hostname
)) {
892 /* it is unclear from RFC 2131 if client should send hostname in
893 DHCPDISCOVER but dhclient does and so we do as well
895 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
896 SD_DHCP_OPTION_HOST_NAME
,
897 strlen(client
->hostname
), client
->hostname
);
899 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
905 if (client
->vendor_class_identifier
) {
906 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
907 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
908 strlen(client
->vendor_class_identifier
),
909 client
->vendor_class_identifier
);
914 if (client
->user_class
) {
915 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
916 SD_DHCP_OPTION_USER_CLASS
,
917 strv_length(client
->user_class
),
923 ORDERED_HASHMAP_FOREACH(j
, client
->options
, i
) {
924 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
925 j
->option
, j
->length
, j
->data
);
930 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
931 SD_DHCP_OPTION_END
, 0, NULL
);
935 /* We currently ignore:
936 The client SHOULD wait a random time between one and ten seconds to
937 desynchronize the use of DHCP at startup.
939 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
943 log_dhcp_client(client
, "DISCOVER");
948 static int client_send_request(sd_dhcp_client
*client
) {
949 _cleanup_free_ DHCPPacket
*request
= NULL
;
950 size_t optoffset
, optlen
;
955 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
959 switch (client
->state
) {
960 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
961 SELECTING should be REQUESTING)
964 case DHCP_STATE_REQUESTING
:
965 /* Client inserts the address of the selected server in ’server
966 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
967 filled in with the yiaddr value from the chosen DHCPOFFER.
970 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
971 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
972 4, &client
->lease
->server_address
);
976 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
977 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
978 4, &client
->lease
->address
);
984 case DHCP_STATE_INIT_REBOOT
:
985 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
986 option MUST be filled in with client’s notion of its previously
987 assigned address. ’ciaddr’ MUST be zero.
989 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
990 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
991 4, &client
->last_addr
);
996 case DHCP_STATE_RENEWING
:
997 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
998 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1002 case DHCP_STATE_REBINDING
:
1003 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1004 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1005 client’s IP address.
1007 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1009 request
->dhcp
.ciaddr
= client
->lease
->address
;
1013 case DHCP_STATE_INIT
:
1014 case DHCP_STATE_SELECTING
:
1015 case DHCP_STATE_REBOOTING
:
1016 case DHCP_STATE_BOUND
:
1017 case DHCP_STATE_STOPPED
:
1021 if (client
->hostname
) {
1022 if (dns_name_is_single_label(client
->hostname
))
1023 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1024 SD_DHCP_OPTION_HOST_NAME
,
1025 strlen(client
->hostname
), client
->hostname
);
1027 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
1033 if (client
->vendor_class_identifier
) {
1034 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1035 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
1036 strlen(client
->vendor_class_identifier
),
1037 client
->vendor_class_identifier
);
1042 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1043 SD_DHCP_OPTION_END
, 0, NULL
);
1047 if (client
->state
== DHCP_STATE_RENEWING
)
1048 r
= dhcp_network_send_udp_socket(client
->fd
,
1049 client
->lease
->server_address
,
1052 sizeof(DHCPMessage
) + optoffset
);
1054 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1058 switch (client
->state
) {
1060 case DHCP_STATE_REQUESTING
:
1061 log_dhcp_client(client
, "REQUEST (requesting)");
1064 case DHCP_STATE_INIT_REBOOT
:
1065 log_dhcp_client(client
, "REQUEST (init-reboot)");
1068 case DHCP_STATE_RENEWING
:
1069 log_dhcp_client(client
, "REQUEST (renewing)");
1072 case DHCP_STATE_REBINDING
:
1073 log_dhcp_client(client
, "REQUEST (rebinding)");
1077 log_dhcp_client(client
, "REQUEST (invalid)");
1084 static int client_start(sd_dhcp_client
*client
);
1086 static int client_timeout_resend(
1091 sd_dhcp_client
*client
= userdata
;
1092 DHCP_CLIENT_DONT_DESTROY(client
);
1093 usec_t next_timeout
= 0;
1100 assert(client
->event
);
1102 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1106 switch (client
->state
) {
1108 case DHCP_STATE_RENEWING
:
1110 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1114 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1118 case DHCP_STATE_REBINDING
:
1120 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1124 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1127 case DHCP_STATE_REBOOTING
:
1128 /* start over as we did not receive a timely ack or nak */
1129 r
= client_initialize(client
);
1133 r
= client_start(client
);
1137 log_dhcp_client(client
, "REBOOTED");
1141 case DHCP_STATE_INIT
:
1142 case DHCP_STATE_INIT_REBOOT
:
1143 case DHCP_STATE_SELECTING
:
1144 case DHCP_STATE_REQUESTING
:
1145 case DHCP_STATE_BOUND
:
1147 if (client
->attempt
< client
->max_attempts
)
1152 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1156 case DHCP_STATE_STOPPED
:
1161 next_timeout
+= (random_u32() & 0x1fffff);
1163 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1164 clock_boottime_or_monotonic(),
1165 next_timeout
, 10 * USEC_PER_MSEC
,
1166 client_timeout_resend
, client
,
1167 client
->event_priority
, "dhcp4-resend-timer", true);
1171 switch (client
->state
) {
1172 case DHCP_STATE_INIT
:
1173 r
= client_send_discover(client
);
1175 client
->state
= DHCP_STATE_SELECTING
;
1176 client
->attempt
= 0;
1177 } else if (client
->attempt
>= client
->max_attempts
)
1182 case DHCP_STATE_SELECTING
:
1183 r
= client_send_discover(client
);
1184 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1189 case DHCP_STATE_INIT_REBOOT
:
1190 case DHCP_STATE_REQUESTING
:
1191 case DHCP_STATE_RENEWING
:
1192 case DHCP_STATE_REBINDING
:
1193 r
= client_send_request(client
);
1194 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1197 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1198 client
->state
= DHCP_STATE_REBOOTING
;
1200 client
->request_sent
= time_now
;
1204 case DHCP_STATE_REBOOTING
:
1205 case DHCP_STATE_BOUND
:
1209 case DHCP_STATE_STOPPED
:
1217 client_stop(client
, r
);
1219 /* Errors were dealt with when stopping the client, don't spill
1220 errors into the event loop handler */
1224 static int client_initialize_io_events(
1225 sd_dhcp_client
*client
,
1226 sd_event_io_handler_t io_callback
) {
1231 assert(client
->event
);
1233 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1234 client
->fd
, EPOLLIN
, io_callback
,
1239 r
= sd_event_source_set_priority(client
->receive_message
,
1240 client
->event_priority
);
1244 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1250 client_stop(client
, r
);
1255 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1260 assert(client
->event
);
1262 if (client
->start_delay
> 0) {
1263 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1264 usec
+= client
->start_delay
;
1267 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1268 clock_boottime_or_monotonic(),
1270 client_timeout_resend
, client
,
1271 client
->event_priority
, "dhcp4-resend-timer", true);
1273 client_stop(client
, r
);
1279 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1280 client_initialize_io_events(client
, io_callback
);
1281 client_initialize_time_events(client
);
1286 static int client_start_delayed(sd_dhcp_client
*client
) {
1289 assert_return(client
, -EINVAL
);
1290 assert_return(client
->event
, -EINVAL
);
1291 assert_return(client
->ifindex
> 0, -EINVAL
);
1292 assert_return(client
->fd
< 0, -EBUSY
);
1293 assert_return(client
->xid
== 0, -EINVAL
);
1294 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1296 client
->xid
= random_u32();
1298 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1299 client
->xid
, client
->mac_addr
,
1300 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1302 client_stop(client
, r
);
1307 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1308 client
->start_time
= now(clock_boottime_or_monotonic());
1310 return client_initialize_events(client
, client_receive_message_raw
);
1313 static int client_start(sd_dhcp_client
*client
) {
1314 client
->start_delay
= 0;
1315 return client_start_delayed(client
);
1318 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1319 sd_dhcp_client
*client
= userdata
;
1320 DHCP_CLIENT_DONT_DESTROY(client
);
1322 log_dhcp_client(client
, "EXPIRED");
1324 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1326 /* lease was lost, start over if not freed or stopped in callback */
1327 if (client
->state
!= DHCP_STATE_STOPPED
) {
1328 client_initialize(client
);
1329 client_start(client
);
1335 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1336 sd_dhcp_client
*client
= userdata
;
1337 DHCP_CLIENT_DONT_DESTROY(client
);
1342 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1343 client
->fd
= asynchronous_close(client
->fd
);
1345 client
->state
= DHCP_STATE_REBINDING
;
1346 client
->attempt
= 0;
1348 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1349 client
->xid
, client
->mac_addr
,
1350 client
->mac_addr_len
, client
->arp_type
,
1353 client_stop(client
, r
);
1358 return client_initialize_events(client
, client_receive_message_raw
);
1361 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1362 sd_dhcp_client
*client
= userdata
;
1363 DHCP_CLIENT_DONT_DESTROY(client
);
1365 client
->state
= DHCP_STATE_RENEWING
;
1366 client
->attempt
= 0;
1368 return client_initialize_time_events(client
);
1371 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1372 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1375 r
= dhcp_lease_new(&lease
);
1379 if (client
->client_id_len
) {
1380 r
= dhcp_lease_set_client_id(lease
,
1381 (uint8_t *) &client
->client_id
,
1382 client
->client_id_len
);
1387 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1388 if (r
!= DHCP_OFFER
) {
1389 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1393 lease
->next_server
= offer
->siaddr
;
1394 lease
->address
= offer
->yiaddr
;
1396 if (lease
->address
== 0 ||
1397 lease
->server_address
== 0 ||
1398 lease
->lifetime
== 0) {
1399 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1403 if (!lease
->have_subnet_mask
) {
1404 r
= dhcp_lease_set_default_subnet_mask(lease
);
1406 log_dhcp_client(client
,
1407 "received lease lacks subnet mask, "
1408 "and a fallback one cannot be generated, ignoring");
1413 sd_dhcp_lease_unref(client
->lease
);
1414 client
->lease
= TAKE_PTR(lease
);
1416 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1419 log_dhcp_client(client
, "OFFER");
1424 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1427 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1428 if (r
!= DHCP_FORCERENEW
)
1431 log_dhcp_client(client
, "FORCERENEW");
1436 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1437 if (a
->address
!= b
->address
)
1440 if (a
->subnet_mask
!= b
->subnet_mask
)
1443 if (a
->router_size
!= b
->router_size
)
1446 for (size_t i
= 0; i
< a
->router_size
; i
++)
1447 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1453 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1454 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1455 _cleanup_free_
char *error_message
= NULL
;
1458 r
= dhcp_lease_new(&lease
);
1462 if (client
->client_id_len
) {
1463 r
= dhcp_lease_set_client_id(lease
,
1464 (uint8_t *) &client
->client_id
,
1465 client
->client_id_len
);
1470 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1471 if (r
== DHCP_NAK
) {
1472 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1473 return -EADDRNOTAVAIL
;
1476 if (r
!= DHCP_ACK
) {
1477 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1481 lease
->next_server
= ack
->siaddr
;
1483 lease
->address
= ack
->yiaddr
;
1485 if (lease
->address
== INADDR_ANY
||
1486 lease
->server_address
== INADDR_ANY
||
1487 lease
->lifetime
== 0) {
1488 log_dhcp_client(client
, "received lease lacks address, server "
1489 "address or lease lifetime, ignoring");
1493 if (lease
->subnet_mask
== INADDR_ANY
) {
1494 r
= dhcp_lease_set_default_subnet_mask(lease
);
1496 log_dhcp_client(client
,
1497 "received lease lacks subnet mask, "
1498 "and a fallback one cannot be generated, ignoring");
1503 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1504 if (client
->lease
) {
1505 if (lease_equal(client
->lease
, lease
))
1506 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1508 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1510 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1513 client
->lease
= TAKE_PTR(lease
);
1515 log_dhcp_client(client
, "ACK");
1520 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1522 assert(client
->request_sent
);
1523 assert(lifetime
> 0);
1530 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1531 + (random_u32() & 0x1fffff);
1534 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1536 uint64_t lifetime_timeout
;
1537 uint64_t t2_timeout
;
1538 uint64_t t1_timeout
;
1539 char time_string
[FORMAT_TIMESPAN_MAX
];
1543 assert(client
->event
);
1544 assert(client
->lease
);
1545 assert(client
->lease
->lifetime
);
1547 /* don't set timers for infinite leases */
1548 if (client
->lease
->lifetime
== 0xffffffff) {
1549 (void) event_source_disable(client
->timeout_t1
);
1550 (void) event_source_disable(client
->timeout_t2
);
1551 (void) event_source_disable(client
->timeout_expire
);
1556 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1559 assert(client
->request_sent
<= time_now
);
1561 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1562 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1563 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1564 /* both T1 and T2 are given */
1565 if (client
->lease
->t1
< client
->lease
->t2
&&
1566 client
->lease
->t2
< client
->lease
->lifetime
) {
1567 /* they are both valid */
1568 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1569 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1572 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1573 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1574 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1575 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1577 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1578 /* only T2 is given, and it is valid */
1579 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1580 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1581 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1582 if (t2_timeout
<= t1_timeout
) {
1583 /* the computed T1 would be invalid, so discard T2 */
1584 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1585 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1587 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1588 /* only T1 is given, and it is valid */
1589 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1590 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1591 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1592 if (t2_timeout
<= t1_timeout
) {
1593 /* the computed T2 would be invalid, so discard T1 */
1594 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1595 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1598 /* fall back to the default timeouts */
1599 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1600 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1601 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1602 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1605 /* arm lifetime timeout */
1606 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1607 clock_boottime_or_monotonic(),
1608 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1609 client_timeout_expire
, client
,
1610 client
->event_priority
, "dhcp4-lifetime", true);
1614 log_dhcp_client(client
, "lease expires in %s",
1615 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1617 /* don't arm earlier timeouts if this has already expired */
1618 if (lifetime_timeout
<= time_now
)
1621 /* arm T2 timeout */
1622 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1623 clock_boottime_or_monotonic(),
1624 t2_timeout
, 10 * USEC_PER_MSEC
,
1625 client_timeout_t2
, client
,
1626 client
->event_priority
, "dhcp4-t2-timeout", true);
1630 log_dhcp_client(client
, "T2 expires in %s",
1631 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1633 /* don't arm earlier timeout if this has already expired */
1634 if (t2_timeout
<= time_now
)
1637 /* arm T1 timeout */
1638 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1639 clock_boottime_or_monotonic(),
1640 t1_timeout
, 10 * USEC_PER_MSEC
,
1641 client_timeout_t1
, client
,
1642 client
->event_priority
, "dhcp4-t1-timer", true);
1646 log_dhcp_client(client
, "T1 expires in %s",
1647 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1652 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1653 DHCP_CLIENT_DONT_DESTROY(client
);
1654 char time_string
[FORMAT_TIMESPAN_MAX
];
1655 int r
= 0, notify_event
= 0;
1658 assert(client
->event
);
1661 switch (client
->state
) {
1662 case DHCP_STATE_SELECTING
:
1664 r
= client_handle_offer(client
, message
, len
);
1667 client
->state
= DHCP_STATE_REQUESTING
;
1668 client
->attempt
= 0;
1670 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1671 clock_boottime_or_monotonic(),
1673 client_timeout_resend
, client
,
1674 client
->event_priority
, "dhcp4-resend-timer", true);
1677 } else if (r
== -ENOMSG
)
1678 /* invalid message, let's ignore it */
1683 case DHCP_STATE_REBOOTING
:
1684 case DHCP_STATE_REQUESTING
:
1685 case DHCP_STATE_RENEWING
:
1686 case DHCP_STATE_REBINDING
:
1688 r
= client_handle_ack(client
, message
, len
);
1690 client
->start_delay
= 0;
1691 (void) event_source_disable(client
->timeout_resend
);
1692 client
->receive_message
=
1693 sd_event_source_unref(client
->receive_message
);
1694 client
->fd
= asynchronous_close(client
->fd
);
1696 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1697 DHCP_STATE_REBOOTING
))
1698 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1699 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1702 client
->state
= DHCP_STATE_BOUND
;
1703 client
->attempt
= 0;
1705 client
->last_addr
= client
->lease
->address
;
1707 r
= client_set_lease_timeouts(client
);
1709 log_dhcp_client(client
, "could not set lease timeouts");
1713 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1715 log_dhcp_client(client
, "could not bind UDP socket");
1721 client_initialize_io_events(client
, client_receive_message_udp
);
1724 client_notify(client
, notify_event
);
1725 if (client
->state
== DHCP_STATE_STOPPED
)
1729 } else if (r
== -EADDRNOTAVAIL
) {
1730 /* got a NAK, let's restart the client */
1731 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1733 r
= client_initialize(client
);
1737 r
= client_start_delayed(client
);
1741 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1742 client
->start_delay
, USEC_PER_SEC
));
1744 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1745 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1748 } else if (r
== -ENOMSG
)
1749 /* invalid message, let's ignore it */
1754 case DHCP_STATE_BOUND
:
1755 r
= client_handle_forcerenew(client
, message
, len
);
1757 r
= client_timeout_t1(NULL
, 0, client
);
1760 } else if (r
== -ENOMSG
)
1761 /* invalid message, let's ignore it */
1766 case DHCP_STATE_INIT
:
1767 case DHCP_STATE_INIT_REBOOT
:
1771 case DHCP_STATE_STOPPED
:
1778 client_stop(client
, r
);
1783 static int client_receive_message_udp(
1789 sd_dhcp_client
*client
= userdata
;
1790 _cleanup_free_ DHCPMessage
*message
= NULL
;
1791 const uint8_t *expected_chaddr
= NULL
;
1792 uint8_t expected_hlen
= 0;
1793 ssize_t len
, buflen
;
1798 buflen
= next_datagram_size_fd(fd
);
1799 if (buflen
== -ENETDOWN
) {
1800 /* the link is down. Don't return an error or the I/O event
1801 source will be disconnected and we won't be able to receive
1802 packets again when the link comes back. */
1808 message
= malloc0(buflen
);
1812 len
= recv(fd
, message
, buflen
, 0);
1814 /* see comment above for why we shouldn't error out on ENETDOWN. */
1815 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1818 return log_dhcp_client_errno(client
, errno
,
1819 "Could not receive message from UDP socket: %m");
1821 if ((size_t) len
< sizeof(DHCPMessage
)) {
1822 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1826 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1827 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1831 if (message
->op
!= BOOTREPLY
) {
1832 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1836 if (message
->htype
!= client
->arp_type
) {
1837 log_dhcp_client(client
, "Packet type does not match client type");
1841 if (client
->arp_type
== ARPHRD_ETHER
) {
1842 expected_hlen
= ETH_ALEN
;
1843 expected_chaddr
= &client
->mac_addr
[0];
1846 if (message
->hlen
!= expected_hlen
) {
1847 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1851 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1852 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1856 if (client
->state
!= DHCP_STATE_BOUND
&&
1857 be32toh(message
->xid
) != client
->xid
) {
1858 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1859 so ignore the xid in this case */
1860 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1861 be32toh(message
->xid
), client
->xid
);
1865 return client_handle_message(client
, message
, len
);
1868 static int client_receive_message_raw(
1874 sd_dhcp_client
*client
= userdata
;
1875 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1876 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1877 struct iovec iov
= {};
1878 struct msghdr msg
= {
1881 .msg_control
= cmsgbuf
,
1882 .msg_controllen
= sizeof(cmsgbuf
),
1884 struct cmsghdr
*cmsg
;
1885 bool checksum
= true;
1886 ssize_t buflen
, len
;
1892 buflen
= next_datagram_size_fd(fd
);
1893 if (buflen
== -ENETDOWN
)
1898 packet
= malloc0(buflen
);
1902 iov
= IOVEC_MAKE(packet
, buflen
);
1904 len
= recvmsg(fd
, &msg
, 0);
1906 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1909 return log_dhcp_client_errno(client
, errno
,
1910 "Could not receive message from raw socket: %m");
1911 } else if ((size_t)len
< sizeof(DHCPPacket
))
1914 CMSG_FOREACH(cmsg
, &msg
)
1915 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1916 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1917 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1918 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1920 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1924 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1928 len
-= DHCP_IP_UDP_SIZE
;
1930 return client_handle_message(client
, &packet
->dhcp
, len
);
1933 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1934 assert_return(client
, -EINVAL
);
1935 assert_return(client
->fd
>= 0, -EINVAL
);
1937 client
->start_delay
= 0;
1938 client
->attempt
= 1;
1939 client
->state
= DHCP_STATE_RENEWING
;
1941 return client_initialize_time_events(client
);
1944 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1947 assert_return(client
, -EINVAL
);
1949 r
= client_initialize(client
);
1953 /* RFC7844 section 3.3:
1954 SHOULD perform a complete four-way handshake, starting with a
1955 DHCPDISCOVER, to obtain a new address lease. If the client can
1956 ascertain that this is exactly the same network to which it was
1957 previously connected, and if the link-layer address did not change,
1958 the client MAY issue a DHCPREQUEST to try to reclaim the current
1960 if (client
->last_addr
&& !client
->anonymize
)
1961 client
->state
= DHCP_STATE_INIT_REBOOT
;
1963 r
= client_start(client
);
1965 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1970 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1971 assert_return(client
, -EINVAL
);
1972 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1973 assert_return(client
->lease
, -EUNATCH
);
1975 _cleanup_free_ DHCPPacket
*release
= NULL
;
1976 size_t optoffset
, optlen
;
1979 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
1983 /* Fill up release IP and MAC */
1984 release
->dhcp
.ciaddr
= client
->lease
->address
;
1985 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1987 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1988 SD_DHCP_OPTION_END
, 0, NULL
);
1992 r
= dhcp_network_send_udp_socket(client
->fd
,
1993 client
->lease
->server_address
,
1996 sizeof(DHCPMessage
) + optoffset
);
2000 log_dhcp_client(client
, "RELEASE");
2005 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2006 DHCP_CLIENT_DONT_DESTROY(client
);
2008 assert_return(client
, -EINVAL
);
2010 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2011 client
->state
= DHCP_STATE_STOPPED
;
2016 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2019 assert_return(client
, -EINVAL
);
2020 assert_return(!client
->event
, -EBUSY
);
2023 client
->event
= sd_event_ref(event
);
2025 r
= sd_event_default(&client
->event
);
2030 client
->event_priority
= priority
;
2035 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2036 assert_return(client
, -EINVAL
);
2038 client
->event
= sd_event_unref(client
->event
);
2043 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2044 assert_return(client
, NULL
);
2046 return client
->event
;
2049 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2052 log_dhcp_client(client
, "FREE");
2054 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2055 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2056 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2057 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2059 client_initialize(client
);
2061 sd_dhcp_client_detach_event(client
);
2063 sd_dhcp_lease_unref(client
->lease
);
2065 free(client
->req_opts
);
2066 free(client
->hostname
);
2067 free(client
->vendor_class_identifier
);
2068 client
->user_class
= strv_free(client
->user_class
);
2069 ordered_hashmap_free(client
->options
);
2070 return mfree(client
);
2073 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2075 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2076 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
2078 assert_return(ret
, -EINVAL
);
2080 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
);