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"
33 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
34 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
36 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
37 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
39 typedef struct sd_dhcp_client_id
{
43 /* 0: Generic (non-LL) (RFC 2132) */
44 uint8_t data
[MAX_CLIENT_ID_LEN
];
47 /* 1: Ethernet Link-Layer (RFC 2132) */
48 uint8_t haddr
[ETH_ALEN
];
51 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
55 /* 255: Node-specific (RFC 4361) */
60 uint8_t data
[MAX_CLIENT_ID_LEN
];
63 } _packed_ sd_dhcp_client_id
;
65 struct sd_dhcp_client
{
71 sd_event_source
*timeout_resend
;
75 union sockaddr_union link
;
76 sd_event_source
*receive_message
;
77 bool request_broadcast
;
79 size_t req_opts_allocated
;
83 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
86 sd_dhcp_client_id client_id
;
89 char *vendor_class_identifier
;
93 uint32_t fallback_lease_lifetime
;
97 uint64_t max_attempts
;
98 OrderedHashmap
*extra_options
;
99 OrderedHashmap
*vendor_options
;
101 sd_event_source
*timeout_t1
;
102 sd_event_source
*timeout_t2
;
103 sd_event_source
*timeout_expire
;
104 sd_dhcp_client_callback_t callback
;
106 sd_dhcp_lease
*lease
;
111 static const uint8_t default_req_opts
[] = {
112 SD_DHCP_OPTION_SUBNET_MASK
,
113 SD_DHCP_OPTION_ROUTER
,
114 SD_DHCP_OPTION_HOST_NAME
,
115 SD_DHCP_OPTION_DOMAIN_NAME
,
116 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
119 /* RFC7844 section 3:
120 MAY contain the Parameter Request List option.
122 The client intending to protect its privacy SHOULD only request a
123 minimal number of options in the PRL and SHOULD also randomly shuffle
124 the ordering of option codes in the PRL. If this random ordering
125 cannot be implemented, the client MAY order the option codes in the
126 PRL by option code number (lowest to highest).
128 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
129 static const uint8_t default_req_opts_anonymize
[] = {
130 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
131 SD_DHCP_OPTION_ROUTER
, /* 3 */
132 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
133 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
134 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
135 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
136 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
137 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
138 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
139 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
140 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
141 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
142 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
145 static int client_receive_message_raw(
150 static int client_receive_message_udp(
155 static void client_stop(sd_dhcp_client
*client
, int error
);
157 int sd_dhcp_client_id_to_string(const void *data
, size_t len
, char **ret
) {
158 const sd_dhcp_client_id
*client_id
= data
;
159 _cleanup_free_
char *t
= NULL
;
162 assert_return(data
, -EINVAL
);
163 assert_return(len
>= 1, -EINVAL
);
164 assert_return(ret
, -EINVAL
);
167 if (len
> MAX_CLIENT_ID_LEN
)
170 switch (client_id
->type
) {
172 if (utf8_is_printable((char *) client_id
->gen
.data
, len
))
173 r
= asprintf(&t
, "%.*s", (int) len
, client_id
->gen
.data
);
175 r
= asprintf(&t
, "DATA");
178 if (len
!= sizeof_field(sd_dhcp_client_id
, eth
))
181 r
= asprintf(&t
, "%x:%x:%x:%x:%x:%x",
182 client_id
->eth
.haddr
[0],
183 client_id
->eth
.haddr
[1],
184 client_id
->eth
.haddr
[2],
185 client_id
->eth
.haddr
[3],
186 client_id
->eth
.haddr
[4],
187 client_id
->eth
.haddr
[5]);
190 r
= asprintf(&t
, "ARP/LL");
196 uint32_t iaid
= be32toh(client_id
->ns
.iaid
);
197 uint16_t duid_type
= be16toh(client_id
->ns
.duid
.type
);
198 if (dhcp_validate_duid_len(duid_type
, len
- 6, true) < 0)
201 r
= asprintf(&t
, "IAID:0x%x/DUID", iaid
);
211 int sd_dhcp_client_set_callback(
212 sd_dhcp_client
*client
,
213 sd_dhcp_client_callback_t cb
,
216 assert_return(client
, -EINVAL
);
218 client
->callback
= cb
;
219 client
->userdata
= userdata
;
224 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
225 assert_return(client
, -EINVAL
);
227 client
->request_broadcast
= !!broadcast
;
232 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
235 assert_return(client
, -EINVAL
);
236 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
240 case SD_DHCP_OPTION_PAD
:
241 case SD_DHCP_OPTION_OVERLOAD
:
242 case SD_DHCP_OPTION_MESSAGE_TYPE
:
243 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
244 case SD_DHCP_OPTION_END
:
251 for (i
= 0; i
< client
->req_opts_size
; i
++)
252 if (client
->req_opts
[i
] == option
)
255 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
256 client
->req_opts_size
+ 1))
259 client
->req_opts
[client
->req_opts_size
++] = option
;
264 int sd_dhcp_client_set_request_address(
265 sd_dhcp_client
*client
,
266 const struct in_addr
*last_addr
) {
268 assert_return(client
, -EINVAL
);
269 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
272 client
->last_addr
= last_addr
->s_addr
;
274 client
->last_addr
= INADDR_ANY
;
279 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
281 assert_return(client
, -EINVAL
);
282 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
283 assert_return(ifindex
> 0, -EINVAL
);
285 client
->ifindex
= ifindex
;
289 int sd_dhcp_client_set_mac(
290 sd_dhcp_client
*client
,
295 DHCP_CLIENT_DONT_DESTROY(client
);
296 bool need_restart
= false;
299 assert_return(client
, -EINVAL
);
300 assert_return(addr
, -EINVAL
);
301 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
302 assert_return(arp_type
> 0, -EINVAL
);
304 if (arp_type
== ARPHRD_ETHER
)
305 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
306 else if (arp_type
== ARPHRD_INFINIBAND
)
307 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
311 if (client
->mac_addr_len
== addr_len
&&
312 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
315 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
316 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
318 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
321 memcpy(&client
->mac_addr
, addr
, addr_len
);
322 client
->mac_addr_len
= addr_len
;
323 client
->arp_type
= arp_type
;
325 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
326 r
= sd_dhcp_client_start(client
);
328 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
334 int sd_dhcp_client_get_client_id(
335 sd_dhcp_client
*client
,
337 const uint8_t **data
,
340 assert_return(client
, -EINVAL
);
341 assert_return(type
, -EINVAL
);
342 assert_return(data
, -EINVAL
);
343 assert_return(data_len
, -EINVAL
);
348 if (client
->client_id_len
) {
349 *type
= client
->client_id
.type
;
350 *data
= client
->client_id
.raw
.data
;
351 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
357 int sd_dhcp_client_set_client_id(
358 sd_dhcp_client
*client
,
363 DHCP_CLIENT_DONT_DESTROY(client
);
364 bool need_restart
= false;
367 assert_return(client
, -EINVAL
);
368 assert_return(data
, -EINVAL
);
369 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
371 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
372 client
->client_id
.type
== type
&&
373 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
376 /* For hardware types, log debug message about unexpected data length.
378 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
379 * the last 8 bytes of the address are stable and suitable to put into
380 * the client-id. The caller is advised to account for that. */
381 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
382 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
383 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
384 "unexpected address length %zu",
387 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
388 log_dhcp_client(client
, "Changing client ID on running DHCP "
389 "client, restarting");
391 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
394 client
->client_id
.type
= type
;
395 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
396 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
398 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
) {
399 r
= sd_dhcp_client_start(client
);
401 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
408 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
409 * without further modification. Otherwise, if duid_type is supported, DUID
410 * is set based on that type. Otherwise, an error is returned.
412 static int dhcp_client_set_iaid_duid_internal(
413 sd_dhcp_client
*client
,
422 DHCP_CLIENT_DONT_DESTROY(client
);
426 assert_return(client
, -EINVAL
);
427 assert_return(duid_len
== 0 || duid
, -EINVAL
);
430 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
432 return log_dhcp_client_errno(client
, r
, "Failed to validate length of DUID: %m");
435 zero(client
->client_id
);
436 client
->client_id
.type
= 255;
440 client
->client_id
.ns
.iaid
= htobe32(iaid
);
442 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
443 client
->mac_addr_len
,
445 &client
->client_id
.ns
.iaid
);
447 return log_dhcp_client_errno(client
, r
, "Failed to set IAID: %m");
452 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
453 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
454 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
458 if (client
->mac_addr_len
== 0)
459 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LLT, MAC address is not set.");
461 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
463 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LLT: %m");
466 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
468 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-EN: %m");
471 if (client
->mac_addr_len
== 0)
472 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Failed to set DUID-LL, MAC address is not set.");
474 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
476 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-LL: %m");
479 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
481 return log_dhcp_client_errno(client
, r
, "Failed to set DUID-UUID: %m");
484 return log_dhcp_client_errno(client
, SYNTHETIC_ERRNO(EINVAL
), "Invalid DUID type");
487 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
488 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
490 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
491 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
492 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
493 r
= sd_dhcp_client_start(client
);
495 return log_dhcp_client_errno(client
, r
, "Failed to restart DHCPv4 client: %m");
501 int sd_dhcp_client_set_iaid_duid(
502 sd_dhcp_client
*client
,
508 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
511 int sd_dhcp_client_set_iaid_duid_llt(
512 sd_dhcp_client
*client
,
516 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
519 int sd_dhcp_client_set_duid(
520 sd_dhcp_client
*client
,
524 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
527 int sd_dhcp_client_set_duid_llt(
528 sd_dhcp_client
*client
,
530 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
533 int sd_dhcp_client_set_hostname(
534 sd_dhcp_client
*client
,
535 const char *hostname
) {
537 assert_return(client
, -EINVAL
);
539 /* Make sure hostnames qualify as DNS and as Linux hostnames */
541 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
544 return free_and_strdup(&client
->hostname
, hostname
);
547 int sd_dhcp_client_set_vendor_class_identifier(
548 sd_dhcp_client
*client
,
551 assert_return(client
, -EINVAL
);
553 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
556 int sd_dhcp_client_set_mud_url(
557 sd_dhcp_client
*client
,
558 const char *mudurl
) {
560 assert_return(client
, -EINVAL
);
561 assert_return(mudurl
, -EINVAL
);
562 assert_return(strlen(mudurl
) <= 255, -EINVAL
);
563 assert_return(http_url_is_valid(mudurl
), -EINVAL
);
565 return free_and_strdup(&client
->mudurl
, mudurl
);
568 int sd_dhcp_client_set_user_class(
569 sd_dhcp_client
*client
,
570 const char* const* user_class
) {
572 _cleanup_strv_free_
char **s
= NULL
;
575 STRV_FOREACH(p
, (char **) user_class
)
576 if (strlen(*p
) > 255)
577 return -ENAMETOOLONG
;
579 s
= strv_copy((char **) user_class
);
583 client
->user_class
= TAKE_PTR(s
);
588 int sd_dhcp_client_set_client_port(
589 sd_dhcp_client
*client
,
592 assert_return(client
, -EINVAL
);
599 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
600 assert_return(client
, -EINVAL
);
601 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
608 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
609 assert_return(client
, -EINVAL
);
611 client
->max_attempts
= max_attempts
;
616 int sd_dhcp_client_add_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
619 assert_return(client
, -EINVAL
);
620 assert_return(v
, -EINVAL
);
622 r
= ordered_hashmap_ensure_allocated(&client
->extra_options
, &dhcp_option_hash_ops
);
626 r
= ordered_hashmap_put(client
->extra_options
, UINT_TO_PTR(v
->option
), v
);
630 sd_dhcp_option_ref(v
);
634 int sd_dhcp_client_add_vendor_option(sd_dhcp_client
*client
, sd_dhcp_option
*v
) {
637 assert_return(client
, -EINVAL
);
638 assert_return(v
, -EINVAL
);
640 r
= ordered_hashmap_ensure_allocated(&client
->vendor_options
, &dhcp_option_hash_ops
);
644 r
= ordered_hashmap_put(client
->vendor_options
, v
, v
);
648 sd_dhcp_option_ref(v
);
653 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
654 assert_return(client
, -EINVAL
);
656 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
657 return -EADDRNOTAVAIL
;
660 *ret
= client
->lease
;
665 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
666 assert_return(client
, -EINVAL
);
668 client
->ip_service_type
= type
;
673 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client
*client
, uint32_t fallback_lease_lifetime
) {
674 assert_return(client
, -EINVAL
);
675 assert_return(fallback_lease_lifetime
> 0, -EINVAL
);
677 client
->fallback_lease_lifetime
= fallback_lease_lifetime
;
682 static int client_notify(sd_dhcp_client
*client
, int event
) {
685 if (client
->callback
)
686 return client
->callback(client
, event
, client
->userdata
);
691 static int client_initialize(sd_dhcp_client
*client
) {
692 assert_return(client
, -EINVAL
);
694 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
696 client
->fd
= asynchronous_close(client
->fd
);
698 (void) event_source_disable(client
->timeout_resend
);
699 (void) event_source_disable(client
->timeout_t1
);
700 (void) event_source_disable(client
->timeout_t2
);
701 (void) event_source_disable(client
->timeout_expire
);
705 client
->state
= DHCP_STATE_INIT
;
708 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
713 static void client_stop(sd_dhcp_client
*client
, int error
) {
717 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
718 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
719 log_dhcp_client(client
, "STOPPED");
721 log_dhcp_client(client
, "STOPPED: Unknown event");
723 client_notify(client
, error
);
725 client_initialize(client
);
728 static int client_message_init(
729 sd_dhcp_client
*client
,
733 size_t *_optoffset
) {
735 _cleanup_free_ DHCPPacket
*packet
= NULL
;
736 size_t optlen
, optoffset
, size
;
743 assert(client
->start_time
);
747 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
, DHCP_DECLINE
));
749 optlen
= DHCP_MIN_OPTIONS_SIZE
;
750 size
= sizeof(DHCPPacket
) + optlen
;
752 packet
= malloc0(size
);
756 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
757 client
->arp_type
, optlen
, &optoffset
);
761 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
762 refuse to issue an DHCP lease if 'secs' is set to zero */
763 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
766 assert(time_now
>= client
->start_time
);
768 /* seconds between sending first and last DISCOVER
769 * must always be strictly positive to deal with broken servers */
770 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
771 packet
->dhcp
.secs
= htobe16(secs
);
773 /* RFC2132 section 4.1
774 A client that cannot receive unicast IP datagrams until its protocol
775 software has been configured with an IP address SHOULD set the
776 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
777 DHCPREQUEST messages that client sends. The BROADCAST bit will
778 provide a hint to the DHCP server and BOOTP relay agent to broadcast
779 any messages to the client on the client's subnet.
781 Note: some interfaces needs this to be enabled, but some networks
782 needs this to be disabled as broadcasts are filteretd, so this
783 needs to be configurable */
784 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
785 packet
->dhcp
.flags
= htobe16(0x8000);
787 /* RFC2132 section 4.1.1:
788 The client MUST include its hardware address in the ’chaddr’ field, if
789 necessary for delivery of DHCP reply messages. Non-Ethernet
790 interfaces will leave 'chaddr' empty and use the client identifier
791 instead (eg, RFC 4390 section 2.1).
793 if (client
->arp_type
== ARPHRD_ETHER
)
794 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
796 /* If no client identifier exists, construct an RFC 4361-compliant one */
797 if (client
->client_id_len
== 0) {
800 client
->client_id
.type
= 255;
802 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
803 true, &client
->client_id
.ns
.iaid
);
807 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
811 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
814 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
815 Identifier option is not set */
816 if (client
->client_id_len
) {
817 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
818 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
819 client
->client_id_len
,
825 /* RFC2131 section 3.5:
826 in its initial DHCPDISCOVER or DHCPREQUEST message, a
827 client may provide the server with a list of specific
828 parameters the client is interested in. If the client
829 includes a list of parameters in a DHCPDISCOVER message,
830 it MUST include that list in any subsequent DHCPREQUEST
834 /* RFC7844 section 3:
835 MAY contain the Parameter Request List option. */
836 /* NOTE: in case that there would be an option to do not send
837 * any PRL at all, the size should be checked before sending */
838 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
839 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
840 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
841 client
->req_opts_size
, client
->req_opts
);
846 /* RFC2131 section 3.5:
847 The client SHOULD include the ’maximum DHCP message size’ option to
848 let the server know how large the server may make its DHCP messages.
850 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
851 than the defined default size unless the Maximum Message Size option
854 RFC3442 "Requirements to Avoid Sizing Constraints":
855 Because a full routing table can be quite large, the standard 576
856 octet maximum size for a DHCP message may be too short to contain
857 some legitimate Classless Static Route options. Because of this,
858 clients implementing the Classless Static Route option SHOULD send a
859 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
860 stack is capable of receiving larger IP datagrams. In this case, the
861 client SHOULD set the value of this option to at least the MTU of the
862 interface that the client is configuring. The client MAY set the
863 value of this option higher, up to the size of the largest UDP packet
864 it is prepared to accept. (Note that the value specified in the
865 Maximum DHCP Message Size option is the total maximum packet size,
866 including IP and UDP headers.)
868 /* RFC7844 section 3:
869 SHOULD NOT contain any other option. */
870 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
871 max_size
= htobe16(size
);
872 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
873 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
880 *_optoffset
= optoffset
;
881 *ret
= TAKE_PTR(packet
);
886 static int client_append_fqdn_option(
887 DHCPMessage
*message
,
892 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
895 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
896 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
897 buffer
[1] = 0; /* RCODE1 (deprecated) */
898 buffer
[2] = 0; /* RCODE2 (deprecated) */
900 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
902 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
903 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
908 static int dhcp_client_send_raw(
909 sd_dhcp_client
*client
,
913 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
914 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
916 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
920 static int client_append_common_discover_request_options(sd_dhcp_client
*client
, DHCPPacket
*packet
, size_t *optoffset
, size_t optlen
) {
926 if (client
->hostname
) {
927 /* According to RFC 4702 "clients that send the Client FQDN option in
928 their messages MUST NOT also send the Host Name option". Just send
929 one of the two depending on the hostname type.
931 if (dns_name_is_single_label(client
->hostname
)) {
932 /* it is unclear from RFC 2131 if client should send hostname in
933 DHCPDISCOVER but dhclient does and so we do as well
935 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
936 SD_DHCP_OPTION_HOST_NAME
,
937 strlen(client
->hostname
), client
->hostname
);
939 r
= client_append_fqdn_option(&packet
->dhcp
, optlen
, optoffset
,
945 if (client
->vendor_class_identifier
) {
946 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
947 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
948 strlen(client
->vendor_class_identifier
),
949 client
->vendor_class_identifier
);
954 if (client
->mudurl
) {
955 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
956 SD_DHCP_OPTION_MUD_URL
,
957 strlen(client
->mudurl
),
963 if (client
->user_class
) {
964 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
965 SD_DHCP_OPTION_USER_CLASS
,
966 strv_length(client
->user_class
),
972 ORDERED_HASHMAP_FOREACH(j
, client
->extra_options
) {
973 r
= dhcp_option_append(&packet
->dhcp
, optlen
, optoffset
, 0,
974 j
->option
, j
->length
, j
->data
);
979 if (!ordered_hashmap_isempty(client
->vendor_options
)) {
980 r
= dhcp_option_append(
981 &packet
->dhcp
, optlen
, optoffset
, 0,
982 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
983 ordered_hashmap_size(client
->vendor_options
), client
->vendor_options
);
992 static int client_send_discover(sd_dhcp_client
*client
) {
993 _cleanup_free_ DHCPPacket
*discover
= NULL
;
994 size_t optoffset
, optlen
;
998 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
1000 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
1001 &optlen
, &optoffset
);
1005 /* the client may suggest values for the network address
1006 and lease time in the DHCPDISCOVER message. The client may include
1007 the ’requested IP address’ option to suggest that a particular IP
1008 address be assigned, and may include the ’IP address lease time’
1009 option to suggest the lease time it would like.
1011 /* RFC7844 section 3:
1012 SHOULD NOT contain any other option. */
1013 if (!client
->anonymize
&& client
->last_addr
!= INADDR_ANY
) {
1014 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1015 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1016 4, &client
->last_addr
);
1021 r
= client_append_common_discover_request_options(client
, discover
, &optoffset
, optlen
);
1025 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
1026 SD_DHCP_OPTION_END
, 0, NULL
);
1030 /* We currently ignore:
1031 The client SHOULD wait a random time between one and ten seconds to
1032 desynchronize the use of DHCP at startup.
1034 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
1038 log_dhcp_client(client
, "DISCOVER");
1043 static int client_send_request(sd_dhcp_client
*client
) {
1044 _cleanup_free_ DHCPPacket
*request
= NULL
;
1045 size_t optoffset
, optlen
;
1050 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
1054 switch (client
->state
) {
1055 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1056 SELECTING should be REQUESTING)
1059 case DHCP_STATE_REQUESTING
:
1060 /* Client inserts the address of the selected server in ’server
1061 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1062 filled in with the yiaddr value from the chosen DHCPOFFER.
1065 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1066 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
1067 4, &client
->lease
->server_address
);
1071 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1072 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1073 4, &client
->lease
->address
);
1079 case DHCP_STATE_INIT_REBOOT
:
1080 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1081 option MUST be filled in with client’s notion of its previously
1082 assigned address. ’ciaddr’ MUST be zero.
1084 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1085 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
1086 4, &client
->last_addr
);
1091 case DHCP_STATE_RENEWING
:
1092 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1093 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1094 client’s IP address.
1097 case DHCP_STATE_REBINDING
:
1098 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1099 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1100 client’s IP address.
1102 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1104 request
->dhcp
.ciaddr
= client
->lease
->address
;
1108 case DHCP_STATE_INIT
:
1109 case DHCP_STATE_SELECTING
:
1110 case DHCP_STATE_REBOOTING
:
1111 case DHCP_STATE_BOUND
:
1112 case DHCP_STATE_STOPPED
:
1116 r
= client_append_common_discover_request_options(client
, request
, &optoffset
, optlen
);
1120 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1121 SD_DHCP_OPTION_END
, 0, NULL
);
1125 if (client
->state
== DHCP_STATE_RENEWING
)
1126 r
= dhcp_network_send_udp_socket(client
->fd
,
1127 client
->lease
->server_address
,
1130 sizeof(DHCPMessage
) + optoffset
);
1132 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1136 switch (client
->state
) {
1138 case DHCP_STATE_REQUESTING
:
1139 log_dhcp_client(client
, "REQUEST (requesting)");
1142 case DHCP_STATE_INIT_REBOOT
:
1143 log_dhcp_client(client
, "REQUEST (init-reboot)");
1146 case DHCP_STATE_RENEWING
:
1147 log_dhcp_client(client
, "REQUEST (renewing)");
1150 case DHCP_STATE_REBINDING
:
1151 log_dhcp_client(client
, "REQUEST (rebinding)");
1155 log_dhcp_client(client
, "REQUEST (invalid)");
1162 static int client_start(sd_dhcp_client
*client
);
1164 static int client_timeout_resend(
1169 sd_dhcp_client
*client
= userdata
;
1170 DHCP_CLIENT_DONT_DESTROY(client
);
1171 usec_t next_timeout
= 0;
1178 assert(client
->event
);
1180 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1184 switch (client
->state
) {
1186 case DHCP_STATE_RENEWING
:
1188 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1192 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1196 case DHCP_STATE_REBINDING
:
1198 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1202 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1205 case DHCP_STATE_REBOOTING
:
1206 /* start over as we did not receive a timely ack or nak */
1207 r
= client_initialize(client
);
1211 r
= client_start(client
);
1215 log_dhcp_client(client
, "REBOOTED");
1219 case DHCP_STATE_INIT
:
1220 case DHCP_STATE_INIT_REBOOT
:
1221 case DHCP_STATE_SELECTING
:
1222 case DHCP_STATE_REQUESTING
:
1223 case DHCP_STATE_BOUND
:
1225 if (client
->attempt
< client
->max_attempts
)
1230 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1234 case DHCP_STATE_STOPPED
:
1239 next_timeout
+= (random_u32() & 0x1fffff);
1241 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1242 clock_boottime_or_monotonic(),
1243 next_timeout
, 10 * USEC_PER_MSEC
,
1244 client_timeout_resend
, client
,
1245 client
->event_priority
, "dhcp4-resend-timer", true);
1249 switch (client
->state
) {
1250 case DHCP_STATE_INIT
:
1251 r
= client_send_discover(client
);
1253 client
->state
= DHCP_STATE_SELECTING
;
1254 client
->attempt
= 0;
1255 } else if (client
->attempt
>= client
->max_attempts
)
1260 case DHCP_STATE_SELECTING
:
1261 r
= client_send_discover(client
);
1262 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1267 case DHCP_STATE_INIT_REBOOT
:
1268 case DHCP_STATE_REQUESTING
:
1269 case DHCP_STATE_RENEWING
:
1270 case DHCP_STATE_REBINDING
:
1271 r
= client_send_request(client
);
1272 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1275 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1276 client
->state
= DHCP_STATE_REBOOTING
;
1278 client
->request_sent
= time_now
;
1282 case DHCP_STATE_REBOOTING
:
1283 case DHCP_STATE_BOUND
:
1287 case DHCP_STATE_STOPPED
:
1295 client_stop(client
, r
);
1297 /* Errors were dealt with when stopping the client, don't spill
1298 errors into the event loop handler */
1302 static int client_initialize_io_events(
1303 sd_dhcp_client
*client
,
1304 sd_event_io_handler_t io_callback
) {
1309 assert(client
->event
);
1311 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1312 client
->fd
, EPOLLIN
, io_callback
,
1317 r
= sd_event_source_set_priority(client
->receive_message
,
1318 client
->event_priority
);
1322 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1328 client_stop(client
, r
);
1333 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1338 assert(client
->event
);
1340 if (client
->start_delay
> 0) {
1341 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1342 usec
+= client
->start_delay
;
1345 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1346 clock_boottime_or_monotonic(),
1348 client_timeout_resend
, client
,
1349 client
->event_priority
, "dhcp4-resend-timer", true);
1351 client_stop(client
, r
);
1357 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1358 client_initialize_io_events(client
, io_callback
);
1359 client_initialize_time_events(client
);
1364 static int client_start_delayed(sd_dhcp_client
*client
) {
1367 assert_return(client
, -EINVAL
);
1368 assert_return(client
->event
, -EINVAL
);
1369 assert_return(client
->ifindex
> 0, -EINVAL
);
1370 assert_return(client
->fd
< 0, -EBUSY
);
1371 assert_return(client
->xid
== 0, -EINVAL
);
1372 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1374 client
->xid
= random_u32();
1376 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1377 client
->xid
, client
->mac_addr
,
1378 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1380 client_stop(client
, r
);
1385 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1386 client
->start_time
= now(clock_boottime_or_monotonic());
1388 return client_initialize_events(client
, client_receive_message_raw
);
1391 static int client_start(sd_dhcp_client
*client
) {
1392 client
->start_delay
= 0;
1393 return client_start_delayed(client
);
1396 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1397 sd_dhcp_client
*client
= userdata
;
1398 DHCP_CLIENT_DONT_DESTROY(client
);
1400 log_dhcp_client(client
, "EXPIRED");
1402 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1404 /* lease was lost, start over if not freed or stopped in callback */
1405 if (client
->state
!= DHCP_STATE_STOPPED
) {
1406 client_initialize(client
);
1407 client_start(client
);
1413 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1414 sd_dhcp_client
*client
= userdata
;
1415 DHCP_CLIENT_DONT_DESTROY(client
);
1420 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1421 client
->fd
= asynchronous_close(client
->fd
);
1423 client
->state
= DHCP_STATE_REBINDING
;
1424 client
->attempt
= 0;
1426 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1427 client
->xid
, client
->mac_addr
,
1428 client
->mac_addr_len
, client
->arp_type
,
1431 client_stop(client
, r
);
1436 return client_initialize_events(client
, client_receive_message_raw
);
1439 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1440 sd_dhcp_client
*client
= userdata
;
1441 DHCP_CLIENT_DONT_DESTROY(client
);
1444 client
->state
= DHCP_STATE_RENEWING
;
1445 else if (client
->state
!= DHCP_STATE_INIT
)
1446 client
->state
= DHCP_STATE_INIT_REBOOT
;
1447 client
->attempt
= 0;
1449 return client_initialize_time_events(client
);
1452 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1453 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1456 r
= dhcp_lease_new(&lease
);
1460 if (client
->client_id_len
) {
1461 r
= dhcp_lease_set_client_id(lease
,
1462 (uint8_t *) &client
->client_id
,
1463 client
->client_id_len
);
1468 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1469 if (r
!= DHCP_OFFER
) {
1470 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1474 lease
->next_server
= offer
->siaddr
;
1475 lease
->address
= offer
->yiaddr
;
1477 if (lease
->lifetime
== 0 && client
->fallback_lease_lifetime
> 0)
1478 lease
->lifetime
= client
->fallback_lease_lifetime
;
1480 if (lease
->address
== 0 ||
1481 lease
->server_address
== 0 ||
1482 lease
->lifetime
== 0) {
1483 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1487 if (!lease
->have_subnet_mask
) {
1488 r
= dhcp_lease_set_default_subnet_mask(lease
);
1490 log_dhcp_client(client
,
1491 "received lease lacks subnet mask, "
1492 "and a fallback one cannot be generated, ignoring");
1497 sd_dhcp_lease_unref(client
->lease
);
1498 client
->lease
= TAKE_PTR(lease
);
1500 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1503 log_dhcp_client(client
, "OFFER");
1508 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1511 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1512 if (r
!= DHCP_FORCERENEW
)
1515 log_dhcp_client(client
, "FORCERENEW");
1520 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1521 if (a
->address
!= b
->address
)
1524 if (a
->subnet_mask
!= b
->subnet_mask
)
1527 if (a
->router_size
!= b
->router_size
)
1530 for (size_t i
= 0; i
< a
->router_size
; i
++)
1531 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1537 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1538 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1539 _cleanup_free_
char *error_message
= NULL
;
1542 r
= dhcp_lease_new(&lease
);
1546 if (client
->client_id_len
) {
1547 r
= dhcp_lease_set_client_id(lease
,
1548 (uint8_t *) &client
->client_id
,
1549 client
->client_id_len
);
1554 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1555 if (r
== DHCP_NAK
) {
1556 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1557 return -EADDRNOTAVAIL
;
1560 if (r
!= DHCP_ACK
) {
1561 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1565 lease
->next_server
= ack
->siaddr
;
1567 lease
->address
= ack
->yiaddr
;
1569 if (lease
->address
== INADDR_ANY
||
1570 lease
->server_address
== INADDR_ANY
||
1571 lease
->lifetime
== 0) {
1572 log_dhcp_client(client
, "received lease lacks address, server "
1573 "address or lease lifetime, ignoring");
1577 if (lease
->subnet_mask
== INADDR_ANY
) {
1578 r
= dhcp_lease_set_default_subnet_mask(lease
);
1580 log_dhcp_client(client
,
1581 "received lease lacks subnet mask, "
1582 "and a fallback one cannot be generated, ignoring");
1587 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1588 if (client
->lease
) {
1589 if (lease_equal(client
->lease
, lease
))
1590 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1592 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1594 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1597 client
->lease
= TAKE_PTR(lease
);
1599 log_dhcp_client(client
, "ACK");
1604 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1606 assert(client
->request_sent
);
1607 assert(lifetime
> 0);
1614 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1615 + (random_u32() & 0x1fffff);
1618 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1620 uint64_t lifetime_timeout
;
1621 uint64_t t2_timeout
;
1622 uint64_t t1_timeout
;
1623 char time_string
[FORMAT_TIMESPAN_MAX
];
1627 assert(client
->event
);
1628 assert(client
->lease
);
1629 assert(client
->lease
->lifetime
);
1631 /* don't set timers for infinite leases */
1632 if (client
->lease
->lifetime
== 0xffffffff) {
1633 (void) event_source_disable(client
->timeout_t1
);
1634 (void) event_source_disable(client
->timeout_t2
);
1635 (void) event_source_disable(client
->timeout_expire
);
1640 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1643 assert(client
->request_sent
<= time_now
);
1645 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1646 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1647 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1648 /* both T1 and T2 are given */
1649 if (client
->lease
->t1
< client
->lease
->t2
&&
1650 client
->lease
->t2
< client
->lease
->lifetime
) {
1651 /* they are both valid */
1652 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1653 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1656 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1657 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1658 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1659 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1661 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1662 /* only T2 is given, and it is valid */
1663 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1664 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1665 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1666 if (t2_timeout
<= t1_timeout
) {
1667 /* the computed T1 would be invalid, so discard T2 */
1668 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1669 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1671 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1672 /* only T1 is given, and it is valid */
1673 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1674 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1675 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1676 if (t2_timeout
<= t1_timeout
) {
1677 /* the computed T2 would be invalid, so discard T1 */
1678 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1679 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1682 /* fall back to the default timeouts */
1683 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1684 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1685 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1686 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1689 /* arm lifetime timeout */
1690 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1691 clock_boottime_or_monotonic(),
1692 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1693 client_timeout_expire
, client
,
1694 client
->event_priority
, "dhcp4-lifetime", true);
1698 log_dhcp_client(client
, "lease expires in %s",
1699 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1701 /* don't arm earlier timeouts if this has already expired */
1702 if (lifetime_timeout
<= time_now
)
1705 /* arm T2 timeout */
1706 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1707 clock_boottime_or_monotonic(),
1708 t2_timeout
, 10 * USEC_PER_MSEC
,
1709 client_timeout_t2
, client
,
1710 client
->event_priority
, "dhcp4-t2-timeout", true);
1714 log_dhcp_client(client
, "T2 expires in %s",
1715 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1717 /* don't arm earlier timeout if this has already expired */
1718 if (t2_timeout
<= time_now
)
1721 /* arm T1 timeout */
1722 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1723 clock_boottime_or_monotonic(),
1724 t1_timeout
, 10 * USEC_PER_MSEC
,
1725 client_timeout_t1
, client
,
1726 client
->event_priority
, "dhcp4-t1-timer", true);
1730 log_dhcp_client(client
, "T1 expires in %s",
1731 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1736 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1737 DHCP_CLIENT_DONT_DESTROY(client
);
1738 char time_string
[FORMAT_TIMESPAN_MAX
];
1739 int r
= 0, notify_event
= 0;
1742 assert(client
->event
);
1745 switch (client
->state
) {
1746 case DHCP_STATE_SELECTING
:
1748 r
= client_handle_offer(client
, message
, len
);
1751 client
->state
= DHCP_STATE_REQUESTING
;
1752 client
->attempt
= 0;
1754 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1755 clock_boottime_or_monotonic(),
1757 client_timeout_resend
, client
,
1758 client
->event_priority
, "dhcp4-resend-timer", true);
1761 } else if (r
== -ENOMSG
)
1762 /* invalid message, let's ignore it */
1767 case DHCP_STATE_REBOOTING
:
1768 case DHCP_STATE_REQUESTING
:
1769 case DHCP_STATE_RENEWING
:
1770 case DHCP_STATE_REBINDING
:
1772 r
= client_handle_ack(client
, message
, len
);
1774 client
->start_delay
= 0;
1775 (void) event_source_disable(client
->timeout_resend
);
1776 client
->receive_message
=
1777 sd_event_source_unref(client
->receive_message
);
1778 client
->fd
= asynchronous_close(client
->fd
);
1780 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1781 DHCP_STATE_REBOOTING
))
1782 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1783 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1786 client
->state
= DHCP_STATE_BOUND
;
1787 client
->attempt
= 0;
1789 client
->last_addr
= client
->lease
->address
;
1791 r
= client_set_lease_timeouts(client
);
1793 log_dhcp_client(client
, "could not set lease timeouts");
1797 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1799 log_dhcp_client(client
, "could not bind UDP socket");
1805 client_initialize_io_events(client
, client_receive_message_udp
);
1808 client_notify(client
, notify_event
);
1809 if (client
->state
== DHCP_STATE_STOPPED
)
1813 } else if (r
== -EADDRNOTAVAIL
) {
1814 /* got a NAK, let's restart the client */
1815 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1817 r
= client_initialize(client
);
1821 r
= client_start_delayed(client
);
1825 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1826 client
->start_delay
, USEC_PER_SEC
));
1828 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1829 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1832 } else if (r
== -ENOMSG
)
1833 /* invalid message, let's ignore it */
1838 case DHCP_STATE_BOUND
:
1839 r
= client_handle_forcerenew(client
, message
, len
);
1841 r
= client_timeout_t1(NULL
, 0, client
);
1844 } else if (r
== -ENOMSG
)
1845 /* invalid message, let's ignore it */
1850 case DHCP_STATE_INIT
:
1851 case DHCP_STATE_INIT_REBOOT
:
1855 case DHCP_STATE_STOPPED
:
1862 client_stop(client
, r
);
1867 static int client_receive_message_udp(
1873 sd_dhcp_client
*client
= userdata
;
1874 _cleanup_free_ DHCPMessage
*message
= NULL
;
1875 const uint8_t *expected_chaddr
= NULL
;
1876 uint8_t expected_hlen
= 0;
1877 ssize_t len
, buflen
;
1882 buflen
= next_datagram_size_fd(fd
);
1883 if (buflen
== -ENETDOWN
) {
1884 /* the link is down. Don't return an error or the I/O event
1885 source will be disconnected and we won't be able to receive
1886 packets again when the link comes back. */
1892 message
= malloc0(buflen
);
1896 len
= recv(fd
, message
, buflen
, 0);
1898 /* see comment above for why we shouldn't error out on ENETDOWN. */
1899 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1902 return log_dhcp_client_errno(client
, errno
,
1903 "Could not receive message from UDP socket: %m");
1905 if ((size_t) len
< sizeof(DHCPMessage
)) {
1906 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1910 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1911 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1915 if (message
->op
!= BOOTREPLY
) {
1916 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1920 if (message
->htype
!= client
->arp_type
) {
1921 log_dhcp_client(client
, "Packet type does not match client type");
1925 if (client
->arp_type
== ARPHRD_ETHER
) {
1926 expected_hlen
= ETH_ALEN
;
1927 expected_chaddr
= &client
->mac_addr
[0];
1930 if (message
->hlen
!= expected_hlen
) {
1931 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1935 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1936 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1940 if (client
->state
!= DHCP_STATE_BOUND
&&
1941 be32toh(message
->xid
) != client
->xid
) {
1942 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1943 so ignore the xid in this case */
1944 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1945 be32toh(message
->xid
), client
->xid
);
1949 return client_handle_message(client
, message
, len
);
1952 static int client_receive_message_raw(
1958 sd_dhcp_client
*client
= userdata
;
1959 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1960 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata
))) control
;
1961 struct iovec iov
= {};
1962 struct msghdr msg
= {
1965 .msg_control
= &control
,
1966 .msg_controllen
= sizeof(control
),
1968 struct cmsghdr
*cmsg
;
1969 bool checksum
= true;
1970 ssize_t buflen
, len
;
1976 buflen
= next_datagram_size_fd(fd
);
1977 if (buflen
== -ENETDOWN
)
1982 packet
= malloc0(buflen
);
1986 iov
= IOVEC_MAKE(packet
, buflen
);
1988 len
= recvmsg_safe(fd
, &msg
, 0);
1989 if (IN_SET(len
, -EAGAIN
, -EINTR
, -ENETDOWN
))
1992 return log_dhcp_client_errno(client
, len
,
1993 "Could not receive message from raw socket: %m");
1995 if ((size_t) len
< sizeof(DHCPPacket
))
1998 cmsg
= cmsg_find(&msg
, SOL_PACKET
, PACKET_AUXDATA
, CMSG_LEN(sizeof(struct tpacket_auxdata
)));
2000 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*) CMSG_DATA(cmsg
);
2001 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
2004 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
2008 len
-= DHCP_IP_UDP_SIZE
;
2010 return client_handle_message(client
, &packet
->dhcp
, len
);
2013 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
2014 assert_return(client
, -EINVAL
);
2015 assert_return(client
->fd
>= 0, -EINVAL
);
2020 client
->start_delay
= 0;
2021 client
->attempt
= 1;
2022 client
->state
= DHCP_STATE_RENEWING
;
2024 return client_initialize_time_events(client
);
2027 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
2030 assert_return(client
, -EINVAL
);
2032 r
= client_initialize(client
);
2036 /* RFC7844 section 3.3:
2037 SHOULD perform a complete four-way handshake, starting with a
2038 DHCPDISCOVER, to obtain a new address lease. If the client can
2039 ascertain that this is exactly the same network to which it was
2040 previously connected, and if the link-layer address did not change,
2041 the client MAY issue a DHCPREQUEST to try to reclaim the current
2043 if (client
->last_addr
&& !client
->anonymize
)
2044 client
->state
= DHCP_STATE_INIT_REBOOT
;
2046 r
= client_start(client
);
2048 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
2053 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
2054 assert_return(client
, -EINVAL
);
2055 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2056 assert_return(client
->lease
, -EUNATCH
);
2058 _cleanup_free_ DHCPPacket
*release
= NULL
;
2059 size_t optoffset
, optlen
;
2062 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
2066 /* Fill up release IP and MAC */
2067 release
->dhcp
.ciaddr
= client
->lease
->address
;
2068 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2070 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2071 SD_DHCP_OPTION_END
, 0, NULL
);
2075 r
= dhcp_network_send_udp_socket(client
->fd
,
2076 client
->lease
->server_address
,
2079 sizeof(DHCPMessage
) + optoffset
);
2083 log_dhcp_client(client
, "RELEASE");
2088 int sd_dhcp_client_send_decline(sd_dhcp_client
*client
) {
2089 assert_return(client
, -EINVAL
);
2090 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
2091 assert_return(client
->lease
, -EUNATCH
);
2093 _cleanup_free_ DHCPPacket
*release
= NULL
;
2094 size_t optoffset
, optlen
;
2097 r
= client_message_init(client
, &release
, DHCP_DECLINE
, &optlen
, &optoffset
);
2101 release
->dhcp
.ciaddr
= client
->lease
->address
;
2102 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
2104 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
2105 SD_DHCP_OPTION_END
, 0, NULL
);
2109 r
= dhcp_network_send_udp_socket(client
->fd
,
2110 client
->lease
->server_address
,
2113 sizeof(DHCPMessage
) + optoffset
);
2117 log_dhcp_client(client
, "DECLINE");
2119 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2121 if (client
->state
!= DHCP_STATE_STOPPED
) {
2122 r
= sd_dhcp_client_start(client
);
2130 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
2131 DHCP_CLIENT_DONT_DESTROY(client
);
2133 assert_return(client
, -EINVAL
);
2135 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
2136 client
->state
= DHCP_STATE_STOPPED
;
2141 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
2144 assert_return(client
, -EINVAL
);
2145 assert_return(!client
->event
, -EBUSY
);
2148 client
->event
= sd_event_ref(event
);
2150 r
= sd_event_default(&client
->event
);
2155 client
->event_priority
= priority
;
2160 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
2161 assert_return(client
, -EINVAL
);
2163 client
->event
= sd_event_unref(client
->event
);
2168 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
2169 assert_return(client
, NULL
);
2171 return client
->event
;
2174 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
2178 log_dhcp_client(client
, "FREE");
2180 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
2181 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
2182 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
2183 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
2185 client_initialize(client
);
2187 sd_dhcp_client_detach_event(client
);
2189 sd_dhcp_lease_unref(client
->lease
);
2191 free(client
->req_opts
);
2192 free(client
->hostname
);
2193 free(client
->vendor_class_identifier
);
2194 free(client
->mudurl
);
2195 client
->user_class
= strv_free(client
->user_class
);
2196 ordered_hashmap_free(client
->extra_options
);
2197 ordered_hashmap_free(client
->vendor_options
);
2198 return mfree(client
);
2201 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2203 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2204 assert_return(ret
, -EINVAL
);
2206 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= new(sd_dhcp_client
, 1);
2210 *client
= (sd_dhcp_client
) {
2212 .state
= DHCP_STATE_INIT
,
2215 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2216 .port
= DHCP_PORT_CLIENT
,
2217 .anonymize
= !!anonymize
,
2218 .max_attempts
= (uint64_t) -1,
2219 .ip_service_type
= -1,
2221 /* NOTE: this could be moved to a function. */
2223 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2224 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2226 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2227 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2229 if (!client
->req_opts
)
2232 *ret
= TAKE_PTR(client
);