1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
7 #include <net/ethernet.h>
8 #include <net/if_arp.h>
12 #include <sys/ioctl.h>
13 #include <linux/if_infiniband.h>
15 #include "sd-dhcp-client.h"
17 #include "alloc-util.h"
19 #include "dhcp-identifier.h"
20 #include "dhcp-internal.h"
21 #include "dhcp-lease-internal.h"
22 #include "dhcp-protocol.h"
23 #include "dns-domain.h"
24 #include "event-util.h"
25 #include "hostname-util.h"
27 #include "memory-util.h"
28 #include "random-util.h"
29 #include "string-util.h"
32 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
33 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
35 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
36 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
38 struct sd_dhcp_client
{
44 sd_event_source
*timeout_resend
;
48 union sockaddr_union link
;
49 sd_event_source
*receive_message
;
50 bool request_broadcast
;
52 size_t req_opts_allocated
;
56 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
63 /* 0: Generic (non-LL) (RFC 2132) */
64 uint8_t data
[MAX_CLIENT_ID_LEN
];
67 /* 1: Ethernet Link-Layer (RFC 2132) */
68 uint8_t haddr
[ETH_ALEN
];
71 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
75 /* 255: Node-specific (RFC 4361) */
80 uint8_t data
[MAX_CLIENT_ID_LEN
];
86 char *vendor_class_identifier
;
92 uint64_t max_attempts
;
94 sd_event_source
*timeout_t1
;
95 sd_event_source
*timeout_t2
;
96 sd_event_source
*timeout_expire
;
97 sd_dhcp_client_callback_t callback
;
104 static const uint8_t default_req_opts
[] = {
105 SD_DHCP_OPTION_SUBNET_MASK
,
106 SD_DHCP_OPTION_ROUTER
,
107 SD_DHCP_OPTION_HOST_NAME
,
108 SD_DHCP_OPTION_DOMAIN_NAME
,
109 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
112 /* RFC7844 section 3:
113 MAY contain the Parameter Request List option.
115 The client intending to protect its privacy SHOULD only request a
116 minimal number of options in the PRL and SHOULD also randomly shuffle
117 the ordering of option codes in the PRL. If this random ordering
118 cannot be implemented, the client MAY order the option codes in the
119 PRL by option code number (lowest to highest).
121 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
122 static const uint8_t default_req_opts_anonymize
[] = {
123 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
124 SD_DHCP_OPTION_ROUTER
, /* 3 */
125 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
126 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
127 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
128 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
129 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
130 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
131 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
132 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
133 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
134 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
135 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
138 static int client_receive_message_raw(
143 static int client_receive_message_udp(
148 static void client_stop(sd_dhcp_client
*client
, int error
);
150 int sd_dhcp_client_set_callback(
151 sd_dhcp_client
*client
,
152 sd_dhcp_client_callback_t cb
,
155 assert_return(client
, -EINVAL
);
157 client
->callback
= cb
;
158 client
->userdata
= userdata
;
163 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
164 assert_return(client
, -EINVAL
);
166 client
->request_broadcast
= !!broadcast
;
171 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
174 assert_return(client
, -EINVAL
);
175 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
179 case SD_DHCP_OPTION_PAD
:
180 case SD_DHCP_OPTION_OVERLOAD
:
181 case SD_DHCP_OPTION_MESSAGE_TYPE
:
182 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
183 case SD_DHCP_OPTION_END
:
190 for (i
= 0; i
< client
->req_opts_size
; i
++)
191 if (client
->req_opts
[i
] == option
)
194 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
195 client
->req_opts_size
+ 1))
198 client
->req_opts
[client
->req_opts_size
++] = option
;
203 int sd_dhcp_client_set_request_address(
204 sd_dhcp_client
*client
,
205 const struct in_addr
*last_addr
) {
207 assert_return(client
, -EINVAL
);
208 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
211 client
->last_addr
= last_addr
->s_addr
;
213 client
->last_addr
= INADDR_ANY
;
218 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
220 assert_return(client
, -EINVAL
);
221 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
222 assert_return(ifindex
> 0, -EINVAL
);
224 client
->ifindex
= ifindex
;
228 int sd_dhcp_client_set_mac(
229 sd_dhcp_client
*client
,
234 DHCP_CLIENT_DONT_DESTROY(client
);
235 bool need_restart
= false;
237 assert_return(client
, -EINVAL
);
238 assert_return(addr
, -EINVAL
);
239 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
240 assert_return(arp_type
> 0, -EINVAL
);
242 if (arp_type
== ARPHRD_ETHER
)
243 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
244 else if (arp_type
== ARPHRD_INFINIBAND
)
245 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
249 if (client
->mac_addr_len
== addr_len
&&
250 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
253 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
254 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
256 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
259 memcpy(&client
->mac_addr
, addr
, addr_len
);
260 client
->mac_addr_len
= addr_len
;
261 client
->arp_type
= arp_type
;
263 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
264 sd_dhcp_client_start(client
);
269 int sd_dhcp_client_get_client_id(
270 sd_dhcp_client
*client
,
272 const uint8_t **data
,
275 assert_return(client
, -EINVAL
);
276 assert_return(type
, -EINVAL
);
277 assert_return(data
, -EINVAL
);
278 assert_return(data_len
, -EINVAL
);
283 if (client
->client_id_len
) {
284 *type
= client
->client_id
.type
;
285 *data
= client
->client_id
.raw
.data
;
286 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
292 int sd_dhcp_client_set_client_id(
293 sd_dhcp_client
*client
,
298 DHCP_CLIENT_DONT_DESTROY(client
);
299 bool need_restart
= false;
301 assert_return(client
, -EINVAL
);
302 assert_return(data
, -EINVAL
);
303 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
305 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
306 client
->client_id
.type
== type
&&
307 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
310 /* For hardware types, log debug message about unexpected data length.
312 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
313 * last last 8 bytes of the address are stable and suitable to put into
314 * the client-id. The caller is advised to account for that. */
315 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
316 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
317 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
318 "unexpected address length %zu",
321 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
322 log_dhcp_client(client
, "Changing client ID on running DHCP "
323 "client, restarting");
325 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
328 client
->client_id
.type
= type
;
329 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
330 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
332 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
333 sd_dhcp_client_start(client
);
339 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
340 * without further modification. Otherwise, if duid_type is supported, DUID
341 * is set based on that type. Otherwise, an error is returned.
343 static int dhcp_client_set_iaid_duid_internal(
344 sd_dhcp_client
*client
,
353 DHCP_CLIENT_DONT_DESTROY(client
);
357 assert_return(client
, -EINVAL
);
358 assert_return(duid_len
== 0 || duid
, -EINVAL
);
361 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
366 zero(client
->client_id
);
367 client
->client_id
.type
= 255;
371 client
->client_id
.ns
.iaid
= htobe32(iaid
);
373 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
374 client
->mac_addr_len
,
376 &client
->client_id
.ns
.iaid
);
383 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
384 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
385 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
389 if (client
->mac_addr_len
== 0)
392 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
397 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
402 if (client
->mac_addr_len
== 0)
405 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
410 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
418 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
419 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
421 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
422 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
423 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
424 sd_dhcp_client_start(client
);
430 int sd_dhcp_client_set_iaid_duid(
431 sd_dhcp_client
*client
,
437 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
440 int sd_dhcp_client_set_iaid_duid_llt(
441 sd_dhcp_client
*client
,
445 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
448 int sd_dhcp_client_set_duid(
449 sd_dhcp_client
*client
,
453 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
456 int sd_dhcp_client_set_duid_llt(
457 sd_dhcp_client
*client
,
459 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
462 int sd_dhcp_client_set_hostname(
463 sd_dhcp_client
*client
,
464 const char *hostname
) {
466 assert_return(client
, -EINVAL
);
468 /* Make sure hostnames qualify as DNS and as Linux hostnames */
470 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
473 return free_and_strdup(&client
->hostname
, hostname
);
476 int sd_dhcp_client_set_vendor_class_identifier(
477 sd_dhcp_client
*client
,
480 assert_return(client
, -EINVAL
);
482 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
485 int sd_dhcp_client_set_user_class(
486 sd_dhcp_client
*client
,
487 const char* const* user_class
) {
489 _cleanup_strv_free_
char **s
= NULL
;
492 STRV_FOREACH(p
, (char **) user_class
)
493 if (strlen(*p
) > 255)
494 return -ENAMETOOLONG
;
496 s
= strv_copy((char **) user_class
);
500 client
->user_class
= TAKE_PTR(s
);
505 int sd_dhcp_client_set_client_port(
506 sd_dhcp_client
*client
,
509 assert_return(client
, -EINVAL
);
516 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
517 assert_return(client
, -EINVAL
);
518 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
525 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
526 assert_return(client
, -EINVAL
);
528 client
->max_attempts
= max_attempts
;
533 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
534 assert_return(client
, -EINVAL
);
536 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
537 return -EADDRNOTAVAIL
;
540 *ret
= client
->lease
;
545 int sd_dhcp_client_set_service_type(sd_dhcp_client
*client
, int type
) {
546 assert_return(client
, -EINVAL
);
548 client
->ip_service_type
= type
;
553 static int client_notify(sd_dhcp_client
*client
, int event
) {
556 if (client
->callback
)
557 return client
->callback(client
, event
, client
->userdata
);
562 static int client_initialize(sd_dhcp_client
*client
) {
563 assert_return(client
, -EINVAL
);
565 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
567 client
->fd
= asynchronous_close(client
->fd
);
569 (void) event_source_disable(client
->timeout_resend
);
570 (void) event_source_disable(client
->timeout_t1
);
571 (void) event_source_disable(client
->timeout_t2
);
572 (void) event_source_disable(client
->timeout_expire
);
576 client
->state
= DHCP_STATE_INIT
;
579 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
584 static void client_stop(sd_dhcp_client
*client
, int error
) {
588 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
589 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
590 log_dhcp_client(client
, "STOPPED");
592 log_dhcp_client(client
, "STOPPED: Unknown event");
594 client_notify(client
, error
);
596 client_initialize(client
);
599 static int client_message_init(
600 sd_dhcp_client
*client
,
604 size_t *_optoffset
) {
606 _cleanup_free_ DHCPPacket
*packet
= NULL
;
607 size_t optlen
, optoffset
, size
;
614 assert(client
->start_time
);
618 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
));
620 optlen
= DHCP_MIN_OPTIONS_SIZE
;
621 size
= sizeof(DHCPPacket
) + optlen
;
623 packet
= malloc0(size
);
627 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
628 client
->arp_type
, optlen
, &optoffset
);
632 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
633 refuse to issue an DHCP lease if 'secs' is set to zero */
634 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
637 assert(time_now
>= client
->start_time
);
639 /* seconds between sending first and last DISCOVER
640 * must always be strictly positive to deal with broken servers */
641 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
642 packet
->dhcp
.secs
= htobe16(secs
);
644 /* RFC2132 section 4.1
645 A client that cannot receive unicast IP datagrams until its protocol
646 software has been configured with an IP address SHOULD set the
647 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
648 DHCPREQUEST messages that client sends. The BROADCAST bit will
649 provide a hint to the DHCP server and BOOTP relay agent to broadcast
650 any messages to the client on the client's subnet.
652 Note: some interfaces needs this to be enabled, but some networks
653 needs this to be disabled as broadcasts are filteretd, so this
654 needs to be configurable */
655 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
656 packet
->dhcp
.flags
= htobe16(0x8000);
658 /* RFC2132 section 4.1.1:
659 The client MUST include its hardware address in the ’chaddr’ field, if
660 necessary for delivery of DHCP reply messages. Non-Ethernet
661 interfaces will leave 'chaddr' empty and use the client identifier
662 instead (eg, RFC 4390 section 2.1).
664 if (client
->arp_type
== ARPHRD_ETHER
)
665 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
667 /* If no client identifier exists, construct an RFC 4361-compliant one */
668 if (client
->client_id_len
== 0) {
671 client
->client_id
.type
= 255;
673 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
674 true, &client
->client_id
.ns
.iaid
);
678 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
682 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
685 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
686 Identifier option is not set */
687 if (client
->client_id_len
) {
688 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
689 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
690 client
->client_id_len
,
696 /* RFC2131 section 3.5:
697 in its initial DHCPDISCOVER or DHCPREQUEST message, a
698 client may provide the server with a list of specific
699 parameters the client is interested in. If the client
700 includes a list of parameters in a DHCPDISCOVER message,
701 it MUST include that list in any subsequent DHCPREQUEST
705 /* RFC7844 section 3:
706 MAY contain the Parameter Request List option. */
707 /* NOTE: in case that there would be an option to do not send
708 * any PRL at all, the size should be checked before sending */
709 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
710 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
711 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
712 client
->req_opts_size
, client
->req_opts
);
717 /* RFC2131 section 3.5:
718 The client SHOULD include the ’maximum DHCP message size’ option to
719 let the server know how large the server may make its DHCP messages.
721 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
722 than the defined default size unless the Maximum Message Size option
725 RFC3442 "Requirements to Avoid Sizing Constraints":
726 Because a full routing table can be quite large, the standard 576
727 octet maximum size for a DHCP message may be too short to contain
728 some legitimate Classless Static Route options. Because of this,
729 clients implementing the Classless Static Route option SHOULD send a
730 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
731 stack is capable of receiving larger IP datagrams. In this case, the
732 client SHOULD set the value of this option to at least the MTU of the
733 interface that the client is configuring. The client MAY set the
734 value of this option higher, up to the size of the largest UDP packet
735 it is prepared to accept. (Note that the value specified in the
736 Maximum DHCP Message Size option is the total maximum packet size,
737 including IP and UDP headers.)
739 /* RFC7844 section 3:
740 SHOULD NOT contain any other option. */
741 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
742 max_size
= htobe16(size
);
743 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
744 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
751 *_optoffset
= optoffset
;
752 *ret
= TAKE_PTR(packet
);
757 static int client_append_fqdn_option(
758 DHCPMessage
*message
,
763 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
766 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
767 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
768 buffer
[1] = 0; /* RCODE1 (deprecated) */
769 buffer
[2] = 0; /* RCODE2 (deprecated) */
771 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
773 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
774 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
779 static int dhcp_client_send_raw(
780 sd_dhcp_client
*client
,
784 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
785 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
, client
->ip_service_type
);
787 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
791 static int client_send_discover(sd_dhcp_client
*client
) {
792 _cleanup_free_ DHCPPacket
*discover
= NULL
;
793 size_t optoffset
, optlen
;
797 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
799 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
800 &optlen
, &optoffset
);
804 /* the client may suggest values for the network address
805 and lease time in the DHCPDISCOVER message. The client may include
806 the ’requested IP address’ option to suggest that a particular IP
807 address be assigned, and may include the ’IP address lease time’
808 option to suggest the lease time it would like.
810 if (client
->last_addr
!= INADDR_ANY
) {
811 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
812 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
813 4, &client
->last_addr
);
818 if (client
->hostname
) {
819 /* According to RFC 4702 "clients that send the Client FQDN option in
820 their messages MUST NOT also send the Host Name option". Just send
821 one of the two depending on the hostname type.
823 if (dns_name_is_single_label(client
->hostname
)) {
824 /* it is unclear from RFC 2131 if client should send hostname in
825 DHCPDISCOVER but dhclient does and so we do as well
827 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
828 SD_DHCP_OPTION_HOST_NAME
,
829 strlen(client
->hostname
), client
->hostname
);
831 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
837 if (client
->vendor_class_identifier
) {
838 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
839 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
840 strlen(client
->vendor_class_identifier
),
841 client
->vendor_class_identifier
);
846 if (client
->user_class
) {
847 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
848 SD_DHCP_OPTION_USER_CLASS
,
849 strv_length(client
->user_class
),
855 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
856 SD_DHCP_OPTION_END
, 0, NULL
);
860 /* We currently ignore:
861 The client SHOULD wait a random time between one and ten seconds to
862 desynchronize the use of DHCP at startup.
864 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
868 log_dhcp_client(client
, "DISCOVER");
873 static int client_send_request(sd_dhcp_client
*client
) {
874 _cleanup_free_ DHCPPacket
*request
= NULL
;
875 size_t optoffset
, optlen
;
880 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
884 switch (client
->state
) {
885 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
886 SELECTING should be REQUESTING)
889 case DHCP_STATE_REQUESTING
:
890 /* Client inserts the address of the selected server in ’server
891 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
892 filled in with the yiaddr value from the chosen DHCPOFFER.
895 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
896 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
897 4, &client
->lease
->server_address
);
901 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
902 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
903 4, &client
->lease
->address
);
909 case DHCP_STATE_INIT_REBOOT
:
910 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
911 option MUST be filled in with client’s notion of its previously
912 assigned address. ’ciaddr’ MUST be zero.
914 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
915 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
916 4, &client
->last_addr
);
921 case DHCP_STATE_RENEWING
:
922 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
923 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
927 case DHCP_STATE_REBINDING
:
928 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
929 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
932 This message MUST be broadcast to the 0xffffffff IP broadcast address.
934 request
->dhcp
.ciaddr
= client
->lease
->address
;
938 case DHCP_STATE_INIT
:
939 case DHCP_STATE_SELECTING
:
940 case DHCP_STATE_REBOOTING
:
941 case DHCP_STATE_BOUND
:
942 case DHCP_STATE_STOPPED
:
946 if (client
->hostname
) {
947 if (dns_name_is_single_label(client
->hostname
))
948 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
949 SD_DHCP_OPTION_HOST_NAME
,
950 strlen(client
->hostname
), client
->hostname
);
952 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
958 if (client
->vendor_class_identifier
) {
959 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
960 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
961 strlen(client
->vendor_class_identifier
),
962 client
->vendor_class_identifier
);
967 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
968 SD_DHCP_OPTION_END
, 0, NULL
);
972 if (client
->state
== DHCP_STATE_RENEWING
)
973 r
= dhcp_network_send_udp_socket(client
->fd
,
974 client
->lease
->server_address
,
977 sizeof(DHCPMessage
) + optoffset
);
979 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
983 switch (client
->state
) {
985 case DHCP_STATE_REQUESTING
:
986 log_dhcp_client(client
, "REQUEST (requesting)");
989 case DHCP_STATE_INIT_REBOOT
:
990 log_dhcp_client(client
, "REQUEST (init-reboot)");
993 case DHCP_STATE_RENEWING
:
994 log_dhcp_client(client
, "REQUEST (renewing)");
997 case DHCP_STATE_REBINDING
:
998 log_dhcp_client(client
, "REQUEST (rebinding)");
1002 log_dhcp_client(client
, "REQUEST (invalid)");
1009 static int client_start(sd_dhcp_client
*client
);
1011 static int client_timeout_resend(
1016 sd_dhcp_client
*client
= userdata
;
1017 DHCP_CLIENT_DONT_DESTROY(client
);
1018 usec_t next_timeout
= 0;
1025 assert(client
->event
);
1027 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1031 switch (client
->state
) {
1033 case DHCP_STATE_RENEWING
:
1035 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1039 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1043 case DHCP_STATE_REBINDING
:
1045 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1049 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1052 case DHCP_STATE_REBOOTING
:
1053 /* start over as we did not receive a timely ack or nak */
1054 r
= client_initialize(client
);
1058 r
= client_start(client
);
1062 log_dhcp_client(client
, "REBOOTED");
1066 case DHCP_STATE_INIT
:
1067 case DHCP_STATE_INIT_REBOOT
:
1068 case DHCP_STATE_SELECTING
:
1069 case DHCP_STATE_REQUESTING
:
1070 case DHCP_STATE_BOUND
:
1072 if (client
->attempt
< client
->max_attempts
)
1077 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1081 case DHCP_STATE_STOPPED
:
1086 next_timeout
+= (random_u32() & 0x1fffff);
1088 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1089 clock_boottime_or_monotonic(),
1090 next_timeout
, 10 * USEC_PER_MSEC
,
1091 client_timeout_resend
, client
,
1092 client
->event_priority
, "dhcp4-resend-timer", true);
1096 switch (client
->state
) {
1097 case DHCP_STATE_INIT
:
1098 r
= client_send_discover(client
);
1100 client
->state
= DHCP_STATE_SELECTING
;
1101 client
->attempt
= 0;
1102 } else if (client
->attempt
>= client
->max_attempts
)
1107 case DHCP_STATE_SELECTING
:
1108 r
= client_send_discover(client
);
1109 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1114 case DHCP_STATE_INIT_REBOOT
:
1115 case DHCP_STATE_REQUESTING
:
1116 case DHCP_STATE_RENEWING
:
1117 case DHCP_STATE_REBINDING
:
1118 r
= client_send_request(client
);
1119 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1122 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1123 client
->state
= DHCP_STATE_REBOOTING
;
1125 client
->request_sent
= time_now
;
1129 case DHCP_STATE_REBOOTING
:
1130 case DHCP_STATE_BOUND
:
1134 case DHCP_STATE_STOPPED
:
1142 client_stop(client
, r
);
1144 /* Errors were dealt with when stopping the client, don't spill
1145 errors into the event loop handler */
1149 static int client_initialize_io_events(
1150 sd_dhcp_client
*client
,
1151 sd_event_io_handler_t io_callback
) {
1156 assert(client
->event
);
1158 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1159 client
->fd
, EPOLLIN
, io_callback
,
1164 r
= sd_event_source_set_priority(client
->receive_message
,
1165 client
->event_priority
);
1169 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1175 client_stop(client
, r
);
1180 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1185 assert(client
->event
);
1187 if (client
->start_delay
> 0) {
1188 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1189 usec
+= client
->start_delay
;
1192 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1193 clock_boottime_or_monotonic(),
1195 client_timeout_resend
, client
,
1196 client
->event_priority
, "dhcp4-resend-timer", true);
1198 client_stop(client
, r
);
1204 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1205 client_initialize_io_events(client
, io_callback
);
1206 client_initialize_time_events(client
);
1211 static int client_start_delayed(sd_dhcp_client
*client
) {
1214 assert_return(client
, -EINVAL
);
1215 assert_return(client
->event
, -EINVAL
);
1216 assert_return(client
->ifindex
> 0, -EINVAL
);
1217 assert_return(client
->fd
< 0, -EBUSY
);
1218 assert_return(client
->xid
== 0, -EINVAL
);
1219 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1221 client
->xid
= random_u32();
1223 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1224 client
->xid
, client
->mac_addr
,
1225 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1227 client_stop(client
, r
);
1232 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1233 client
->start_time
= now(clock_boottime_or_monotonic());
1235 return client_initialize_events(client
, client_receive_message_raw
);
1238 static int client_start(sd_dhcp_client
*client
) {
1239 client
->start_delay
= 0;
1240 return client_start_delayed(client
);
1243 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1244 sd_dhcp_client
*client
= userdata
;
1245 DHCP_CLIENT_DONT_DESTROY(client
);
1247 log_dhcp_client(client
, "EXPIRED");
1249 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1251 /* lease was lost, start over if not freed or stopped in callback */
1252 if (client
->state
!= DHCP_STATE_STOPPED
) {
1253 client_initialize(client
);
1254 client_start(client
);
1260 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1261 sd_dhcp_client
*client
= userdata
;
1262 DHCP_CLIENT_DONT_DESTROY(client
);
1267 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1268 client
->fd
= asynchronous_close(client
->fd
);
1270 client
->state
= DHCP_STATE_REBINDING
;
1271 client
->attempt
= 0;
1273 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1274 client
->xid
, client
->mac_addr
,
1275 client
->mac_addr_len
, client
->arp_type
,
1278 client_stop(client
, r
);
1283 return client_initialize_events(client
, client_receive_message_raw
);
1286 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1287 sd_dhcp_client
*client
= userdata
;
1288 DHCP_CLIENT_DONT_DESTROY(client
);
1290 client
->state
= DHCP_STATE_RENEWING
;
1291 client
->attempt
= 0;
1293 return client_initialize_time_events(client
);
1296 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1297 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1300 r
= dhcp_lease_new(&lease
);
1304 if (client
->client_id_len
) {
1305 r
= dhcp_lease_set_client_id(lease
,
1306 (uint8_t *) &client
->client_id
,
1307 client
->client_id_len
);
1312 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1313 if (r
!= DHCP_OFFER
) {
1314 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1318 lease
->next_server
= offer
->siaddr
;
1319 lease
->address
= offer
->yiaddr
;
1321 if (lease
->address
== 0 ||
1322 lease
->server_address
== 0 ||
1323 lease
->lifetime
== 0) {
1324 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1328 if (!lease
->have_subnet_mask
) {
1329 r
= dhcp_lease_set_default_subnet_mask(lease
);
1331 log_dhcp_client(client
,
1332 "received lease lacks subnet mask, "
1333 "and a fallback one cannot be generated, ignoring");
1338 sd_dhcp_lease_unref(client
->lease
);
1339 client
->lease
= TAKE_PTR(lease
);
1341 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1344 log_dhcp_client(client
, "OFFER");
1349 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1352 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1353 if (r
!= DHCP_FORCERENEW
)
1356 log_dhcp_client(client
, "FORCERENEW");
1361 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1362 if (a
->address
!= b
->address
)
1365 if (a
->subnet_mask
!= b
->subnet_mask
)
1368 if (a
->router_size
!= b
->router_size
)
1371 for (size_t i
= 0; i
< a
->router_size
; i
++)
1372 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1378 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1379 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1380 _cleanup_free_
char *error_message
= NULL
;
1383 r
= dhcp_lease_new(&lease
);
1387 if (client
->client_id_len
) {
1388 r
= dhcp_lease_set_client_id(lease
,
1389 (uint8_t *) &client
->client_id
,
1390 client
->client_id_len
);
1395 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1396 if (r
== DHCP_NAK
) {
1397 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1398 return -EADDRNOTAVAIL
;
1401 if (r
!= DHCP_ACK
) {
1402 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1406 lease
->next_server
= ack
->siaddr
;
1408 lease
->address
= ack
->yiaddr
;
1410 if (lease
->address
== INADDR_ANY
||
1411 lease
->server_address
== INADDR_ANY
||
1412 lease
->lifetime
== 0) {
1413 log_dhcp_client(client
, "received lease lacks address, server "
1414 "address or lease lifetime, ignoring");
1418 if (lease
->subnet_mask
== INADDR_ANY
) {
1419 r
= dhcp_lease_set_default_subnet_mask(lease
);
1421 log_dhcp_client(client
,
1422 "received lease lacks subnet mask, "
1423 "and a fallback one cannot be generated, ignoring");
1428 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1429 if (client
->lease
) {
1430 if (lease_equal(client
->lease
, lease
))
1431 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1433 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1435 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1438 client
->lease
= TAKE_PTR(lease
);
1440 log_dhcp_client(client
, "ACK");
1445 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1447 assert(client
->request_sent
);
1448 assert(lifetime
> 0);
1455 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1456 + (random_u32() & 0x1fffff);
1459 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1461 uint64_t lifetime_timeout
;
1462 uint64_t t2_timeout
;
1463 uint64_t t1_timeout
;
1464 char time_string
[FORMAT_TIMESPAN_MAX
];
1468 assert(client
->event
);
1469 assert(client
->lease
);
1470 assert(client
->lease
->lifetime
);
1472 /* don't set timers for infinite leases */
1473 if (client
->lease
->lifetime
== 0xffffffff) {
1474 (void) event_source_disable(client
->timeout_t1
);
1475 (void) event_source_disable(client
->timeout_t2
);
1476 (void) event_source_disable(client
->timeout_expire
);
1481 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1484 assert(client
->request_sent
<= time_now
);
1486 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1487 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1488 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1489 /* both T1 and T2 are given */
1490 if (client
->lease
->t1
< client
->lease
->t2
&&
1491 client
->lease
->t2
< client
->lease
->lifetime
) {
1492 /* they are both valid */
1493 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1494 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1497 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1498 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1499 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1500 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1502 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1503 /* only T2 is given, and it is valid */
1504 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1505 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1506 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1507 if (t2_timeout
<= t1_timeout
) {
1508 /* the computed T1 would be invalid, so discard T2 */
1509 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1510 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1512 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1513 /* only T1 is given, and it is valid */
1514 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1515 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1516 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1517 if (t2_timeout
<= t1_timeout
) {
1518 /* the computed T2 would be invalid, so discard T1 */
1519 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1520 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1523 /* fall back to the default timeouts */
1524 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1525 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1526 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1527 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1530 /* arm lifetime timeout */
1531 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1532 clock_boottime_or_monotonic(),
1533 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1534 client_timeout_expire
, client
,
1535 client
->event_priority
, "dhcp4-lifetime", true);
1539 log_dhcp_client(client
, "lease expires in %s",
1540 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1542 /* don't arm earlier timeouts if this has already expired */
1543 if (lifetime_timeout
<= time_now
)
1546 /* arm T2 timeout */
1547 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1548 clock_boottime_or_monotonic(),
1549 t2_timeout
, 10 * USEC_PER_MSEC
,
1550 client_timeout_t2
, client
,
1551 client
->event_priority
, "dhcp4-t2-timeout", true);
1555 log_dhcp_client(client
, "T2 expires in %s",
1556 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1558 /* don't arm earlier timeout if this has already expired */
1559 if (t2_timeout
<= time_now
)
1562 /* arm T1 timeout */
1563 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1564 clock_boottime_or_monotonic(),
1565 t1_timeout
, 10 * USEC_PER_MSEC
,
1566 client_timeout_t1
, client
,
1567 client
->event_priority
, "dhcp4-t1-timer", true);
1571 log_dhcp_client(client
, "T1 expires in %s",
1572 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1577 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1578 DHCP_CLIENT_DONT_DESTROY(client
);
1579 char time_string
[FORMAT_TIMESPAN_MAX
];
1580 int r
= 0, notify_event
= 0;
1583 assert(client
->event
);
1586 switch (client
->state
) {
1587 case DHCP_STATE_SELECTING
:
1589 r
= client_handle_offer(client
, message
, len
);
1592 client
->state
= DHCP_STATE_REQUESTING
;
1593 client
->attempt
= 0;
1595 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1596 clock_boottime_or_monotonic(),
1598 client_timeout_resend
, client
,
1599 client
->event_priority
, "dhcp4-resend-timer", true);
1602 } else if (r
== -ENOMSG
)
1603 /* invalid message, let's ignore it */
1608 case DHCP_STATE_REBOOTING
:
1609 case DHCP_STATE_REQUESTING
:
1610 case DHCP_STATE_RENEWING
:
1611 case DHCP_STATE_REBINDING
:
1613 r
= client_handle_ack(client
, message
, len
);
1615 client
->start_delay
= 0;
1616 (void) event_source_disable(client
->timeout_resend
);
1617 client
->receive_message
=
1618 sd_event_source_unref(client
->receive_message
);
1619 client
->fd
= asynchronous_close(client
->fd
);
1621 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1622 DHCP_STATE_REBOOTING
))
1623 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1624 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1627 client
->state
= DHCP_STATE_BOUND
;
1628 client
->attempt
= 0;
1630 client
->last_addr
= client
->lease
->address
;
1632 r
= client_set_lease_timeouts(client
);
1634 log_dhcp_client(client
, "could not set lease timeouts");
1638 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1640 log_dhcp_client(client
, "could not bind UDP socket");
1646 client_initialize_io_events(client
, client_receive_message_udp
);
1649 client_notify(client
, notify_event
);
1650 if (client
->state
== DHCP_STATE_STOPPED
)
1654 } else if (r
== -EADDRNOTAVAIL
) {
1655 /* got a NAK, let's restart the client */
1656 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1658 r
= client_initialize(client
);
1662 r
= client_start_delayed(client
);
1666 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1667 client
->start_delay
, USEC_PER_SEC
));
1669 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1670 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1673 } else if (r
== -ENOMSG
)
1674 /* invalid message, let's ignore it */
1679 case DHCP_STATE_BOUND
:
1680 r
= client_handle_forcerenew(client
, message
, len
);
1682 r
= client_timeout_t1(NULL
, 0, client
);
1685 } else if (r
== -ENOMSG
)
1686 /* invalid message, let's ignore it */
1691 case DHCP_STATE_INIT
:
1692 case DHCP_STATE_INIT_REBOOT
:
1696 case DHCP_STATE_STOPPED
:
1703 client_stop(client
, r
);
1708 static int client_receive_message_udp(
1714 sd_dhcp_client
*client
= userdata
;
1715 _cleanup_free_ DHCPMessage
*message
= NULL
;
1716 const uint8_t *expected_chaddr
= NULL
;
1717 uint8_t expected_hlen
= 0;
1718 ssize_t len
, buflen
;
1723 buflen
= next_datagram_size_fd(fd
);
1724 if (buflen
== -ENETDOWN
) {
1725 /* the link is down. Don't return an error or the I/O event
1726 source will be disconnected and we won't be able to receive
1727 packets again when the link comes back. */
1733 message
= malloc0(buflen
);
1737 len
= recv(fd
, message
, buflen
, 0);
1739 /* see comment above for why we shouldn't error out on ENETDOWN. */
1740 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1743 return log_dhcp_client_errno(client
, errno
,
1744 "Could not receive message from UDP socket: %m");
1746 if ((size_t) len
< sizeof(DHCPMessage
)) {
1747 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1751 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1752 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1756 if (message
->op
!= BOOTREPLY
) {
1757 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1761 if (message
->htype
!= client
->arp_type
) {
1762 log_dhcp_client(client
, "Packet type does not match client type");
1766 if (client
->arp_type
== ARPHRD_ETHER
) {
1767 expected_hlen
= ETH_ALEN
;
1768 expected_chaddr
= &client
->mac_addr
[0];
1771 if (message
->hlen
!= expected_hlen
) {
1772 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1776 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1777 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1781 if (client
->state
!= DHCP_STATE_BOUND
&&
1782 be32toh(message
->xid
) != client
->xid
) {
1783 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1784 so ignore the xid in this case */
1785 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1786 be32toh(message
->xid
), client
->xid
);
1790 return client_handle_message(client
, message
, len
);
1793 static int client_receive_message_raw(
1799 sd_dhcp_client
*client
= userdata
;
1800 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1801 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1802 struct iovec iov
= {};
1803 struct msghdr msg
= {
1806 .msg_control
= cmsgbuf
,
1807 .msg_controllen
= sizeof(cmsgbuf
),
1809 struct cmsghdr
*cmsg
;
1810 bool checksum
= true;
1811 ssize_t buflen
, len
;
1817 buflen
= next_datagram_size_fd(fd
);
1818 if (buflen
== -ENETDOWN
)
1823 packet
= malloc0(buflen
);
1827 iov
= IOVEC_MAKE(packet
, buflen
);
1829 len
= recvmsg(fd
, &msg
, 0);
1831 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1834 return log_dhcp_client_errno(client
, errno
,
1835 "Could not receive message from raw socket: %m");
1836 } else if ((size_t)len
< sizeof(DHCPPacket
))
1839 CMSG_FOREACH(cmsg
, &msg
)
1840 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1841 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1842 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1843 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1845 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1849 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1853 len
-= DHCP_IP_UDP_SIZE
;
1855 return client_handle_message(client
, &packet
->dhcp
, len
);
1858 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1859 assert_return(client
, -EINVAL
);
1860 assert_return(client
->fd
>= 0, -EINVAL
);
1862 client
->start_delay
= 0;
1863 client
->attempt
= 1;
1864 client
->state
= DHCP_STATE_RENEWING
;
1866 return client_initialize_time_events(client
);
1869 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1872 assert_return(client
, -EINVAL
);
1874 r
= client_initialize(client
);
1878 /* RFC7844 section 3.3:
1879 SHOULD perform a complete four-way handshake, starting with a
1880 DHCPDISCOVER, to obtain a new address lease. If the client can
1881 ascertain that this is exactly the same network to which it was
1882 previously connected, and if the link-layer address did not change,
1883 the client MAY issue a DHCPREQUEST to try to reclaim the current
1885 if (client
->last_addr
&& !client
->anonymize
)
1886 client
->state
= DHCP_STATE_INIT_REBOOT
;
1888 r
= client_start(client
);
1890 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1895 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1896 assert_return(client
, -EINVAL
);
1897 assert_return(client
->state
!= DHCP_STATE_STOPPED
, -ESTALE
);
1898 assert_return(client
->lease
, -EUNATCH
);
1900 _cleanup_free_ DHCPPacket
*release
= NULL
;
1901 size_t optoffset
, optlen
;
1904 r
= client_message_init(client
, &release
, DHCP_RELEASE
, &optlen
, &optoffset
);
1908 /* Fill up release IP and MAC */
1909 release
->dhcp
.ciaddr
= client
->lease
->address
;
1910 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
1912 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
1913 SD_DHCP_OPTION_END
, 0, NULL
);
1917 r
= dhcp_network_send_udp_socket(client
->fd
,
1918 client
->lease
->server_address
,
1921 sizeof(DHCPMessage
) + optoffset
);
1925 log_dhcp_client(client
, "RELEASE");
1930 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1931 DHCP_CLIENT_DONT_DESTROY(client
);
1933 assert_return(client
, -EINVAL
);
1935 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1936 client
->state
= DHCP_STATE_STOPPED
;
1941 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1944 assert_return(client
, -EINVAL
);
1945 assert_return(!client
->event
, -EBUSY
);
1948 client
->event
= sd_event_ref(event
);
1950 r
= sd_event_default(&client
->event
);
1955 client
->event_priority
= priority
;
1960 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1961 assert_return(client
, -EINVAL
);
1963 client
->event
= sd_event_unref(client
->event
);
1968 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1969 assert_return(client
, NULL
);
1971 return client
->event
;
1974 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1977 log_dhcp_client(client
, "FREE");
1979 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1980 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1981 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1982 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1984 client_initialize(client
);
1986 sd_dhcp_client_detach_event(client
);
1988 sd_dhcp_lease_unref(client
->lease
);
1990 free(client
->req_opts
);
1991 free(client
->hostname
);
1992 free(client
->vendor_class_identifier
);
1993 client
->user_class
= strv_free(client
->user_class
);
1994 return mfree(client
);
1997 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1999 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2000 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
2002 assert_return(ret
, -EINVAL
);
2004 client
= new(sd_dhcp_client
, 1);
2008 *client
= (sd_dhcp_client
) {
2010 .state
= DHCP_STATE_INIT
,
2013 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2014 .port
= DHCP_PORT_CLIENT
,
2015 .anonymize
= !!anonymize
,
2016 .max_attempts
= (uint64_t) -1,
2017 .ip_service_type
= -1,
2019 /* NOTE: this could be moved to a function. */
2021 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2022 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2024 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2025 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2027 if (!client
->req_opts
)
2030 *ret
= TAKE_PTR(client
);