1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
7 #include <net/ethernet.h>
8 #include <net/if_arp.h>
11 #include <sys/ioctl.h>
12 #include <linux/if_infiniband.h>
14 #include "sd-dhcp-client.h"
16 #include "alloc-util.h"
18 #include "dhcp-identifier.h"
19 #include "dhcp-internal.h"
20 #include "dhcp-lease-internal.h"
21 #include "dhcp-protocol.h"
22 #include "dns-domain.h"
23 #include "event-util.h"
24 #include "hostname-util.h"
26 #include "memory-util.h"
27 #include "random-util.h"
28 #include "string-util.h"
31 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
32 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
34 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
35 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
37 struct sd_dhcp_option
{
45 struct sd_dhcp_client
{
51 sd_event_source
*timeout_resend
;
55 union sockaddr_union link
;
56 sd_event_source
*receive_message
;
57 bool request_broadcast
;
59 size_t req_opts_allocated
;
63 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
70 /* 0: Generic (non-LL) (RFC 2132) */
71 uint8_t data
[MAX_CLIENT_ID_LEN
];
74 /* 1: Ethernet Link-Layer (RFC 2132) */
75 uint8_t haddr
[ETH_ALEN
];
78 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
82 /* 255: Node-specific (RFC 4361) */
87 uint8_t data
[MAX_CLIENT_ID_LEN
];
93 char *vendor_class_identifier
;
99 uint64_t max_attempts
;
100 OrderedHashmap
*options
;
102 sd_event_source
*timeout_t1
;
103 sd_event_source
*timeout_t2
;
104 sd_event_source
*timeout_expire
;
105 sd_dhcp_client_callback_t callback
;
107 sd_dhcp_lease
*lease
;
112 static const uint8_t default_req_opts
[] = {
113 SD_DHCP_OPTION_SUBNET_MASK
,
114 SD_DHCP_OPTION_ROUTER
,
115 SD_DHCP_OPTION_HOST_NAME
,
116 SD_DHCP_OPTION_DOMAIN_NAME
,
117 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
120 /* RFC7844 section 3:
121 MAY contain the Parameter Request List option.
123 The client intending to protect its privacy SHOULD only request a
124 minimal number of options in the PRL and SHOULD also randomly shuffle
125 the ordering of option codes in the PRL. If this random ordering
126 cannot be implemented, the client MAY order the option codes in the
127 PRL by option code number (lowest to highest).
129 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
130 static const uint8_t default_req_opts_anonymize
[] = {
131 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
132 SD_DHCP_OPTION_ROUTER
, /* 3 */
133 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
134 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
135 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
136 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
137 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
138 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
139 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
140 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
141 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
142 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
143 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
146 static int client_receive_message_raw(
151 static int client_receive_message_udp(
156 static void client_stop(sd_dhcp_client
*client
, int error
);
158 int sd_dhcp_client_set_callback(
159 sd_dhcp_client
*client
,
160 sd_dhcp_client_callback_t cb
,
163 assert_return(client
, -EINVAL
);
165 client
->callback
= cb
;
166 client
->userdata
= userdata
;
171 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
172 assert_return(client
, -EINVAL
);
174 client
->request_broadcast
= !!broadcast
;
179 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
182 assert_return(client
, -EINVAL
);
183 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
187 case SD_DHCP_OPTION_PAD
:
188 case SD_DHCP_OPTION_OVERLOAD
:
189 case SD_DHCP_OPTION_MESSAGE_TYPE
:
190 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
191 case SD_DHCP_OPTION_END
:
198 for (i
= 0; i
< client
->req_opts_size
; i
++)
199 if (client
->req_opts
[i
] == option
)
202 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
203 client
->req_opts_size
+ 1))
206 client
->req_opts
[client
->req_opts_size
++] = option
;
211 int sd_dhcp_client_set_request_address(
212 sd_dhcp_client
*client
,
213 const struct in_addr
*last_addr
) {
215 assert_return(client
, -EINVAL
);
216 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
219 client
->last_addr
= last_addr
->s_addr
;
221 client
->last_addr
= INADDR_ANY
;
226 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
228 assert_return(client
, -EINVAL
);
229 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
230 assert_return(ifindex
> 0, -EINVAL
);
232 client
->ifindex
= ifindex
;
236 int sd_dhcp_client_set_mac(
237 sd_dhcp_client
*client
,
242 DHCP_CLIENT_DONT_DESTROY(client
);
243 bool need_restart
= false;
245 assert_return(client
, -EINVAL
);
246 assert_return(addr
, -EINVAL
);
247 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
248 assert_return(arp_type
> 0, -EINVAL
);
250 if (arp_type
== ARPHRD_ETHER
)
251 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
252 else if (arp_type
== ARPHRD_INFINIBAND
)
253 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
257 if (client
->mac_addr_len
== addr_len
&&
258 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
261 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
262 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
264 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
267 memcpy(&client
->mac_addr
, addr
, addr_len
);
268 client
->mac_addr_len
= addr_len
;
269 client
->arp_type
= arp_type
;
271 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
272 sd_dhcp_client_start(client
);
277 int sd_dhcp_client_get_client_id(
278 sd_dhcp_client
*client
,
280 const uint8_t **data
,
283 assert_return(client
, -EINVAL
);
284 assert_return(type
, -EINVAL
);
285 assert_return(data
, -EINVAL
);
286 assert_return(data_len
, -EINVAL
);
291 if (client
->client_id_len
) {
292 *type
= client
->client_id
.type
;
293 *data
= client
->client_id
.raw
.data
;
294 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
300 int sd_dhcp_client_set_client_id(
301 sd_dhcp_client
*client
,
306 DHCP_CLIENT_DONT_DESTROY(client
);
307 bool need_restart
= false;
309 assert_return(client
, -EINVAL
);
310 assert_return(data
, -EINVAL
);
311 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
313 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
314 client
->client_id
.type
== type
&&
315 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
318 /* For hardware types, log debug message about unexpected data length.
320 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
321 * last last 8 bytes of the address are stable and suitable to put into
322 * the client-id. The caller is advised to account for that. */
323 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
324 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
325 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
326 "unexpected address length %zu",
329 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
330 log_dhcp_client(client
, "Changing client ID on running DHCP "
331 "client, restarting");
333 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
336 client
->client_id
.type
= type
;
337 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
338 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
340 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
341 sd_dhcp_client_start(client
);
347 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
348 * without further modification. Otherwise, if duid_type is supported, DUID
349 * is set based on that type. Otherwise, an error is returned.
351 static int dhcp_client_set_iaid_duid_internal(
352 sd_dhcp_client
*client
,
361 DHCP_CLIENT_DONT_DESTROY(client
);
365 assert_return(client
, -EINVAL
);
366 assert_return(duid_len
== 0 || duid
, -EINVAL
);
369 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
371 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
374 zero(client
->client_id
);
375 client
->client_id
.type
= 255;
379 client
->client_id
.ns
.iaid
= htobe32(iaid
);
381 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
382 client
->mac_addr_len
,
384 &client
->client_id
.ns
.iaid
);
386 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
391 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
392 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
393 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
397 if (client
->mac_addr_len
== 0)
398 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
400 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
402 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
405 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
407 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
410 if (client
->mac_addr_len
== 0)
411 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
413 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
415 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
418 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
420 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
423 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
426 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
427 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
429 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
430 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
431 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
432 sd_dhcp_client_start(client
);
438 int sd_dhcp_client_set_iaid_duid(
439 sd_dhcp_client
*client
,
445 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
448 int sd_dhcp_client_set_iaid_duid_llt(
449 sd_dhcp_client
*client
,
453 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
456 int sd_dhcp_client_set_duid(
457 sd_dhcp_client
*client
,
461 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
464 int sd_dhcp_client_set_duid_llt(
465 sd_dhcp_client
*client
,
467 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
470 int sd_dhcp_client_set_hostname(
471 sd_dhcp_client
*client
,
472 const char *hostname
) {
474 assert_return(client
, -EINVAL
);
476 /* Make sure hostnames qualify as DNS and as Linux hostnames */
478 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
481 return free_and_strdup(&client
->hostname
, hostname
);
484 int sd_dhcp_client_set_vendor_class_identifier(
485 sd_dhcp_client
*client
,
488 assert_return(client
, -EINVAL
);
490 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
493 int sd_dhcp_client_set_user_class(
494 sd_dhcp_client
*client
,
495 const char* const* user_class
) {
497 _cleanup_strv_free_
char **s
= NULL
;
500 STRV_FOREACH(p
, (char **) user_class
)
501 if (strlen(*p
) > 255)
502 return -ENAMETOOLONG
;
504 s
= strv_copy((char **) user_class
);
508 client
->user_class
= TAKE_PTR(s
);
513 int sd_dhcp_client_set_client_port(
514 sd_dhcp_client
*client
,
517 assert_return(client
, -EINVAL
);
524 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
525 assert_return(client
, -EINVAL
);
526 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
533 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
534 assert_return(client
, -EINVAL
);
536 client
->max_attempts
= max_attempts
;
541 static sd_dhcp_option
* dhcp_option_free(sd_dhcp_option
*i
) {
549 int sd_dhcp_option_new(uint8_t option
, void *data
, size_t length
, sd_dhcp_option
**ret
) {
550 assert_return(ret
, -EINVAL
);
551 assert_return(length
== 0 || data
, -EINVAL
);
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
) {
2053 log_dhcp_client(client
, "FREE");
2055 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2056 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2057 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2058 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2060 client_initialize(client
);
2062 sd_dhcp_client_detach_event(client
);
2064 sd_dhcp_lease_unref(client
->lease
);
2066 free(client
->req_opts
);
2067 free(client
->hostname
);
2068 free(client
->vendor_class_identifier
);
2069 client
->user_class
= strv_free(client
->user_class
);
2070 ordered_hashmap_free(client
->options
);
2071 return mfree(client
);
2074 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2076 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2077 assert_return(ret
, -EINVAL
);
2079 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2083 *client
= (sd_dhcp_client
) {
2085 .state
= DHCP_STATE_INIT
,
2088 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2089 .port
= DHCP_PORT_CLIENT
,
2090 .anonymize
= !!anonymize
,
2091 .max_attempts
= (uint64_t) -1,
2092 .ip_service_type
= -1,
2094 /* NOTE: this could be moved to a function. */
2096 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2097 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2099 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2100 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2102 if (!client
->req_opts
)
2105 *ret
= TAKE_PTR(client
);