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_release(sd_dhcp_client
*client
) {
874 _cleanup_free_ DHCPPacket
*release
= NULL
;
875 size_t optoffset
, optlen
;
879 assert(!IN_SET(client
->state
, DHCP_STATE_STOPPED
));
881 r
= client_message_init(client
, &release
, DHCP_RELEASE
,
882 &optlen
, &optoffset
);
886 /* Fill up release IP and MAC */
887 release
->dhcp
.ciaddr
= client
->lease
->address
;
888 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
890 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
891 SD_DHCP_OPTION_END
, 0, NULL
);
895 r
= dhcp_network_send_udp_socket(client
->fd
,
896 client
->lease
->server_address
,
899 sizeof(DHCPMessage
) + optoffset
);
903 log_dhcp_client(client
, "RELEASE");
908 static int client_send_request(sd_dhcp_client
*client
) {
909 _cleanup_free_ DHCPPacket
*request
= NULL
;
910 size_t optoffset
, optlen
;
915 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
919 switch (client
->state
) {
920 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
921 SELECTING should be REQUESTING)
924 case DHCP_STATE_REQUESTING
:
925 /* Client inserts the address of the selected server in ’server
926 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
927 filled in with the yiaddr value from the chosen DHCPOFFER.
930 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
931 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
932 4, &client
->lease
->server_address
);
936 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
937 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
938 4, &client
->lease
->address
);
944 case DHCP_STATE_INIT_REBOOT
:
945 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
946 option MUST be filled in with client’s notion of its previously
947 assigned address. ’ciaddr’ MUST be zero.
949 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
950 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
951 4, &client
->last_addr
);
956 case DHCP_STATE_RENEWING
:
957 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
958 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
962 case DHCP_STATE_REBINDING
:
963 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
964 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
967 This message MUST be broadcast to the 0xffffffff IP broadcast address.
969 request
->dhcp
.ciaddr
= client
->lease
->address
;
973 case DHCP_STATE_INIT
:
974 case DHCP_STATE_SELECTING
:
975 case DHCP_STATE_REBOOTING
:
976 case DHCP_STATE_BOUND
:
977 case DHCP_STATE_STOPPED
:
981 if (client
->hostname
) {
982 if (dns_name_is_single_label(client
->hostname
))
983 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
984 SD_DHCP_OPTION_HOST_NAME
,
985 strlen(client
->hostname
), client
->hostname
);
987 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
993 if (client
->vendor_class_identifier
) {
994 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
995 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
996 strlen(client
->vendor_class_identifier
),
997 client
->vendor_class_identifier
);
1002 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
1003 SD_DHCP_OPTION_END
, 0, NULL
);
1007 if (client
->state
== DHCP_STATE_RENEWING
)
1008 r
= dhcp_network_send_udp_socket(client
->fd
,
1009 client
->lease
->server_address
,
1012 sizeof(DHCPMessage
) + optoffset
);
1014 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1018 switch (client
->state
) {
1020 case DHCP_STATE_REQUESTING
:
1021 log_dhcp_client(client
, "REQUEST (requesting)");
1024 case DHCP_STATE_INIT_REBOOT
:
1025 log_dhcp_client(client
, "REQUEST (init-reboot)");
1028 case DHCP_STATE_RENEWING
:
1029 log_dhcp_client(client
, "REQUEST (renewing)");
1032 case DHCP_STATE_REBINDING
:
1033 log_dhcp_client(client
, "REQUEST (rebinding)");
1037 log_dhcp_client(client
, "REQUEST (invalid)");
1044 static int client_start(sd_dhcp_client
*client
);
1046 static int client_timeout_resend(
1051 sd_dhcp_client
*client
= userdata
;
1052 DHCP_CLIENT_DONT_DESTROY(client
);
1053 usec_t next_timeout
= 0;
1060 assert(client
->event
);
1062 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1066 switch (client
->state
) {
1068 case DHCP_STATE_RENEWING
:
1070 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1074 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1078 case DHCP_STATE_REBINDING
:
1080 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1084 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1087 case DHCP_STATE_REBOOTING
:
1088 /* start over as we did not receive a timely ack or nak */
1089 r
= client_initialize(client
);
1093 r
= client_start(client
);
1097 log_dhcp_client(client
, "REBOOTED");
1101 case DHCP_STATE_INIT
:
1102 case DHCP_STATE_INIT_REBOOT
:
1103 case DHCP_STATE_SELECTING
:
1104 case DHCP_STATE_REQUESTING
:
1105 case DHCP_STATE_BOUND
:
1107 if (client
->attempt
< client
->max_attempts
)
1112 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1116 case DHCP_STATE_STOPPED
:
1121 next_timeout
+= (random_u32() & 0x1fffff);
1123 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1124 clock_boottime_or_monotonic(),
1125 next_timeout
, 10 * USEC_PER_MSEC
,
1126 client_timeout_resend
, client
,
1127 client
->event_priority
, "dhcp4-resend-timer", true);
1131 switch (client
->state
) {
1132 case DHCP_STATE_INIT
:
1133 r
= client_send_discover(client
);
1135 client
->state
= DHCP_STATE_SELECTING
;
1136 client
->attempt
= 0;
1137 } else if (client
->attempt
>= client
->max_attempts
)
1142 case DHCP_STATE_SELECTING
:
1143 r
= client_send_discover(client
);
1144 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1149 case DHCP_STATE_INIT_REBOOT
:
1150 case DHCP_STATE_REQUESTING
:
1151 case DHCP_STATE_RENEWING
:
1152 case DHCP_STATE_REBINDING
:
1153 r
= client_send_request(client
);
1154 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1157 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1158 client
->state
= DHCP_STATE_REBOOTING
;
1160 client
->request_sent
= time_now
;
1164 case DHCP_STATE_REBOOTING
:
1165 case DHCP_STATE_BOUND
:
1169 case DHCP_STATE_STOPPED
:
1177 client_stop(client
, r
);
1179 /* Errors were dealt with when stopping the client, don't spill
1180 errors into the event loop handler */
1184 static int client_initialize_io_events(
1185 sd_dhcp_client
*client
,
1186 sd_event_io_handler_t io_callback
) {
1191 assert(client
->event
);
1193 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1194 client
->fd
, EPOLLIN
, io_callback
,
1199 r
= sd_event_source_set_priority(client
->receive_message
,
1200 client
->event_priority
);
1204 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1210 client_stop(client
, r
);
1215 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1220 assert(client
->event
);
1222 if (client
->start_delay
> 0) {
1223 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1224 usec
+= client
->start_delay
;
1227 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1228 clock_boottime_or_monotonic(),
1230 client_timeout_resend
, client
,
1231 client
->event_priority
, "dhcp4-resend-timer", true);
1233 client_stop(client
, r
);
1239 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1240 client_initialize_io_events(client
, io_callback
);
1241 client_initialize_time_events(client
);
1246 static int client_start_delayed(sd_dhcp_client
*client
) {
1249 assert_return(client
, -EINVAL
);
1250 assert_return(client
->event
, -EINVAL
);
1251 assert_return(client
->ifindex
> 0, -EINVAL
);
1252 assert_return(client
->fd
< 0, -EBUSY
);
1253 assert_return(client
->xid
== 0, -EINVAL
);
1254 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1256 client
->xid
= random_u32();
1258 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1259 client
->xid
, client
->mac_addr
,
1260 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1262 client_stop(client
, r
);
1267 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1268 client
->start_time
= now(clock_boottime_or_monotonic());
1270 return client_initialize_events(client
, client_receive_message_raw
);
1273 static int client_start(sd_dhcp_client
*client
) {
1274 client
->start_delay
= 0;
1275 return client_start_delayed(client
);
1278 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1279 sd_dhcp_client
*client
= userdata
;
1280 DHCP_CLIENT_DONT_DESTROY(client
);
1282 log_dhcp_client(client
, "EXPIRED");
1284 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1286 /* lease was lost, start over if not freed or stopped in callback */
1287 if (client
->state
!= DHCP_STATE_STOPPED
) {
1288 client_initialize(client
);
1289 client_start(client
);
1295 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1296 sd_dhcp_client
*client
= userdata
;
1297 DHCP_CLIENT_DONT_DESTROY(client
);
1302 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1303 client
->fd
= asynchronous_close(client
->fd
);
1305 client
->state
= DHCP_STATE_REBINDING
;
1306 client
->attempt
= 0;
1308 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1309 client
->xid
, client
->mac_addr
,
1310 client
->mac_addr_len
, client
->arp_type
,
1313 client_stop(client
, r
);
1318 return client_initialize_events(client
, client_receive_message_raw
);
1321 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1322 sd_dhcp_client
*client
= userdata
;
1323 DHCP_CLIENT_DONT_DESTROY(client
);
1325 client
->state
= DHCP_STATE_RENEWING
;
1326 client
->attempt
= 0;
1328 return client_initialize_time_events(client
);
1331 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1332 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1335 r
= dhcp_lease_new(&lease
);
1339 if (client
->client_id_len
) {
1340 r
= dhcp_lease_set_client_id(lease
,
1341 (uint8_t *) &client
->client_id
,
1342 client
->client_id_len
);
1347 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1348 if (r
!= DHCP_OFFER
) {
1349 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1353 lease
->next_server
= offer
->siaddr
;
1354 lease
->address
= offer
->yiaddr
;
1356 if (lease
->address
== 0 ||
1357 lease
->server_address
== 0 ||
1358 lease
->lifetime
== 0) {
1359 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1363 if (!lease
->have_subnet_mask
) {
1364 r
= dhcp_lease_set_default_subnet_mask(lease
);
1366 log_dhcp_client(client
,
1367 "received lease lacks subnet mask, "
1368 "and a fallback one cannot be generated, ignoring");
1373 sd_dhcp_lease_unref(client
->lease
);
1374 client
->lease
= TAKE_PTR(lease
);
1376 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1379 log_dhcp_client(client
, "OFFER");
1384 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1387 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1388 if (r
!= DHCP_FORCERENEW
)
1391 log_dhcp_client(client
, "FORCERENEW");
1396 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1397 if (a
->address
!= b
->address
)
1400 if (a
->subnet_mask
!= b
->subnet_mask
)
1403 if (a
->router_size
!= b
->router_size
)
1406 for (size_t i
= 0; i
< a
->router_size
; i
++)
1407 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1413 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1414 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1415 _cleanup_free_
char *error_message
= NULL
;
1418 r
= dhcp_lease_new(&lease
);
1422 if (client
->client_id_len
) {
1423 r
= dhcp_lease_set_client_id(lease
,
1424 (uint8_t *) &client
->client_id
,
1425 client
->client_id_len
);
1430 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1431 if (r
== DHCP_NAK
) {
1432 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1433 return -EADDRNOTAVAIL
;
1436 if (r
!= DHCP_ACK
) {
1437 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1441 lease
->next_server
= ack
->siaddr
;
1443 lease
->address
= ack
->yiaddr
;
1445 if (lease
->address
== INADDR_ANY
||
1446 lease
->server_address
== INADDR_ANY
||
1447 lease
->lifetime
== 0) {
1448 log_dhcp_client(client
, "received lease lacks address, server "
1449 "address or lease lifetime, ignoring");
1453 if (lease
->subnet_mask
== INADDR_ANY
) {
1454 r
= dhcp_lease_set_default_subnet_mask(lease
);
1456 log_dhcp_client(client
,
1457 "received lease lacks subnet mask, "
1458 "and a fallback one cannot be generated, ignoring");
1463 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1464 if (client
->lease
) {
1465 if (lease_equal(client
->lease
, lease
))
1466 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1468 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1470 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1473 client
->lease
= TAKE_PTR(lease
);
1475 log_dhcp_client(client
, "ACK");
1480 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1482 assert(client
->request_sent
);
1483 assert(lifetime
> 0);
1490 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1491 + (random_u32() & 0x1fffff);
1494 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1496 uint64_t lifetime_timeout
;
1497 uint64_t t2_timeout
;
1498 uint64_t t1_timeout
;
1499 char time_string
[FORMAT_TIMESPAN_MAX
];
1503 assert(client
->event
);
1504 assert(client
->lease
);
1505 assert(client
->lease
->lifetime
);
1507 /* don't set timers for infinite leases */
1508 if (client
->lease
->lifetime
== 0xffffffff) {
1509 (void) event_source_disable(client
->timeout_t1
);
1510 (void) event_source_disable(client
->timeout_t2
);
1511 (void) event_source_disable(client
->timeout_expire
);
1516 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1519 assert(client
->request_sent
<= time_now
);
1521 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1522 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1523 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1524 /* both T1 and T2 are given */
1525 if (client
->lease
->t1
< client
->lease
->t2
&&
1526 client
->lease
->t2
< client
->lease
->lifetime
) {
1527 /* they are both valid */
1528 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1529 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1532 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1533 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1534 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1535 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1537 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1538 /* only T2 is given, and it is valid */
1539 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1540 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1541 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1542 if (t2_timeout
<= t1_timeout
) {
1543 /* the computed T1 would be invalid, so discard T2 */
1544 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1545 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1547 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1548 /* only T1 is given, and it is valid */
1549 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1550 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1551 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1552 if (t2_timeout
<= t1_timeout
) {
1553 /* the computed T2 would be invalid, so discard T1 */
1554 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1555 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1558 /* fall back to the default timeouts */
1559 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1560 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1561 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1562 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1565 /* arm lifetime timeout */
1566 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1567 clock_boottime_or_monotonic(),
1568 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1569 client_timeout_expire
, client
,
1570 client
->event_priority
, "dhcp4-lifetime", true);
1574 log_dhcp_client(client
, "lease expires in %s",
1575 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1577 /* don't arm earlier timeouts if this has already expired */
1578 if (lifetime_timeout
<= time_now
)
1581 /* arm T2 timeout */
1582 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1583 clock_boottime_or_monotonic(),
1584 t2_timeout
, 10 * USEC_PER_MSEC
,
1585 client_timeout_t2
, client
,
1586 client
->event_priority
, "dhcp4-t2-timeout", true);
1590 log_dhcp_client(client
, "T2 expires in %s",
1591 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1593 /* don't arm earlier timeout if this has already expired */
1594 if (t2_timeout
<= time_now
)
1597 /* arm T1 timeout */
1598 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1599 clock_boottime_or_monotonic(),
1600 t1_timeout
, 10 * USEC_PER_MSEC
,
1601 client_timeout_t1
, client
,
1602 client
->event_priority
, "dhcp4-t1-timer", true);
1606 log_dhcp_client(client
, "T1 expires in %s",
1607 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1612 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1613 DHCP_CLIENT_DONT_DESTROY(client
);
1614 char time_string
[FORMAT_TIMESPAN_MAX
];
1615 int r
= 0, notify_event
= 0;
1618 assert(client
->event
);
1621 switch (client
->state
) {
1622 case DHCP_STATE_SELECTING
:
1624 r
= client_handle_offer(client
, message
, len
);
1627 client
->state
= DHCP_STATE_REQUESTING
;
1628 client
->attempt
= 0;
1630 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1631 clock_boottime_or_monotonic(),
1633 client_timeout_resend
, client
,
1634 client
->event_priority
, "dhcp4-resend-timer", true);
1637 } else if (r
== -ENOMSG
)
1638 /* invalid message, let's ignore it */
1643 case DHCP_STATE_REBOOTING
:
1644 case DHCP_STATE_REQUESTING
:
1645 case DHCP_STATE_RENEWING
:
1646 case DHCP_STATE_REBINDING
:
1648 r
= client_handle_ack(client
, message
, len
);
1650 client
->start_delay
= 0;
1651 (void) event_source_disable(client
->timeout_resend
);
1652 client
->receive_message
=
1653 sd_event_source_unref(client
->receive_message
);
1654 client
->fd
= asynchronous_close(client
->fd
);
1656 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1657 DHCP_STATE_REBOOTING
))
1658 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1659 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1662 client
->state
= DHCP_STATE_BOUND
;
1663 client
->attempt
= 0;
1665 client
->last_addr
= client
->lease
->address
;
1667 r
= client_set_lease_timeouts(client
);
1669 log_dhcp_client(client
, "could not set lease timeouts");
1673 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
, client
->ip_service_type
);
1675 log_dhcp_client(client
, "could not bind UDP socket");
1681 client_initialize_io_events(client
, client_receive_message_udp
);
1684 client_notify(client
, notify_event
);
1685 if (client
->state
== DHCP_STATE_STOPPED
)
1689 } else if (r
== -EADDRNOTAVAIL
) {
1690 /* got a NAK, let's restart the client */
1691 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1693 r
= client_initialize(client
);
1697 r
= client_start_delayed(client
);
1701 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1702 client
->start_delay
, USEC_PER_SEC
));
1704 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1705 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1708 } else if (r
== -ENOMSG
)
1709 /* invalid message, let's ignore it */
1714 case DHCP_STATE_BOUND
:
1715 r
= client_handle_forcerenew(client
, message
, len
);
1717 r
= client_timeout_t1(NULL
, 0, client
);
1720 } else if (r
== -ENOMSG
)
1721 /* invalid message, let's ignore it */
1726 case DHCP_STATE_INIT
:
1727 case DHCP_STATE_INIT_REBOOT
:
1731 case DHCP_STATE_STOPPED
:
1738 client_stop(client
, r
);
1743 static int client_receive_message_udp(
1749 sd_dhcp_client
*client
= userdata
;
1750 _cleanup_free_ DHCPMessage
*message
= NULL
;
1751 const uint8_t *expected_chaddr
= NULL
;
1752 uint8_t expected_hlen
= 0;
1753 ssize_t len
, buflen
;
1758 buflen
= next_datagram_size_fd(fd
);
1759 if (buflen
== -ENETDOWN
) {
1760 /* the link is down. Don't return an error or the I/O event
1761 source will be disconnected and we won't be able to receive
1762 packets again when the link comes back. */
1768 message
= malloc0(buflen
);
1772 len
= recv(fd
, message
, buflen
, 0);
1774 /* see comment above for why we shouldn't error out on ENETDOWN. */
1775 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1778 return log_dhcp_client_errno(client
, errno
,
1779 "Could not receive message from UDP socket: %m");
1781 if ((size_t) len
< sizeof(DHCPMessage
)) {
1782 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1786 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1787 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1791 if (message
->op
!= BOOTREPLY
) {
1792 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1796 if (message
->htype
!= client
->arp_type
) {
1797 log_dhcp_client(client
, "Packet type does not match client type");
1801 if (client
->arp_type
== ARPHRD_ETHER
) {
1802 expected_hlen
= ETH_ALEN
;
1803 expected_chaddr
= &client
->mac_addr
[0];
1806 if (message
->hlen
!= expected_hlen
) {
1807 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1811 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1812 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1816 if (client
->state
!= DHCP_STATE_BOUND
&&
1817 be32toh(message
->xid
) != client
->xid
) {
1818 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1819 so ignore the xid in this case */
1820 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1821 be32toh(message
->xid
), client
->xid
);
1825 return client_handle_message(client
, message
, len
);
1828 static int client_receive_message_raw(
1834 sd_dhcp_client
*client
= userdata
;
1835 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1836 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1837 struct iovec iov
= {};
1838 struct msghdr msg
= {
1841 .msg_control
= cmsgbuf
,
1842 .msg_controllen
= sizeof(cmsgbuf
),
1844 struct cmsghdr
*cmsg
;
1845 bool checksum
= true;
1846 ssize_t buflen
, len
;
1852 buflen
= next_datagram_size_fd(fd
);
1853 if (buflen
== -ENETDOWN
)
1858 packet
= malloc0(buflen
);
1862 iov
= IOVEC_MAKE(packet
, buflen
);
1864 len
= recvmsg(fd
, &msg
, 0);
1866 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1869 return log_dhcp_client_errno(client
, errno
,
1870 "Could not receive message from raw socket: %m");
1871 } else if ((size_t)len
< sizeof(DHCPPacket
))
1874 CMSG_FOREACH(cmsg
, &msg
)
1875 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1876 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1877 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1878 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1880 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1884 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1888 len
-= DHCP_IP_UDP_SIZE
;
1890 return client_handle_message(client
, &packet
->dhcp
, len
);
1893 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1894 assert_return(client
, -EINVAL
);
1895 assert_return(client
->fd
>= 0, -EINVAL
);
1897 client
->start_delay
= 0;
1898 client
->attempt
= 1;
1899 client
->state
= DHCP_STATE_RENEWING
;
1901 return client_initialize_time_events(client
);
1904 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1907 assert_return(client
, -EINVAL
);
1909 r
= client_initialize(client
);
1913 /* RFC7844 section 3.3:
1914 SHOULD perform a complete four-way handshake, starting with a
1915 DHCPDISCOVER, to obtain a new address lease. If the client can
1916 ascertain that this is exactly the same network to which it was
1917 previously connected, and if the link-layer address did not change,
1918 the client MAY issue a DHCPREQUEST to try to reclaim the current
1920 if (client
->last_addr
&& !client
->anonymize
)
1921 client
->state
= DHCP_STATE_INIT_REBOOT
;
1923 r
= client_start(client
);
1925 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1930 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1931 assert_return(client
, -EINVAL
);
1933 client_send_release(client
);
1938 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1939 DHCP_CLIENT_DONT_DESTROY(client
);
1941 assert_return(client
, -EINVAL
);
1943 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1944 client
->state
= DHCP_STATE_STOPPED
;
1949 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1952 assert_return(client
, -EINVAL
);
1953 assert_return(!client
->event
, -EBUSY
);
1956 client
->event
= sd_event_ref(event
);
1958 r
= sd_event_default(&client
->event
);
1963 client
->event_priority
= priority
;
1968 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1969 assert_return(client
, -EINVAL
);
1971 client
->event
= sd_event_unref(client
->event
);
1976 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1977 assert_return(client
, NULL
);
1979 return client
->event
;
1982 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1985 log_dhcp_client(client
, "FREE");
1987 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1988 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1989 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1990 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1992 client_initialize(client
);
1994 sd_dhcp_client_detach_event(client
);
1996 sd_dhcp_lease_unref(client
->lease
);
1998 free(client
->req_opts
);
1999 free(client
->hostname
);
2000 free(client
->vendor_class_identifier
);
2001 client
->user_class
= strv_free(client
->user_class
);
2002 return mfree(client
);
2005 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
2007 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
2008 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
2010 assert_return(ret
, -EINVAL
);
2012 client
= new(sd_dhcp_client
, 1);
2016 *client
= (sd_dhcp_client
) {
2018 .state
= DHCP_STATE_INIT
,
2021 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2022 .port
= DHCP_PORT_CLIENT
,
2023 .anonymize
= !!anonymize
,
2024 .max_attempts
= (uint64_t) -1,
2025 .ip_service_type
= -1,
2027 /* NOTE: this could be moved to a function. */
2029 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2030 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2032 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2033 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2035 if (!client
->req_opts
)
2038 *ret
= TAKE_PTR(client
);