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 MAX_CLIENT_ATTEMPT 64
37 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
38 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
40 struct sd_dhcp_client
{
46 sd_event_source
*timeout_resend
;
50 union sockaddr_union link
;
51 sd_event_source
*receive_message
;
52 bool request_broadcast
;
54 size_t req_opts_allocated
;
58 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
65 /* 0: Generic (non-LL) (RFC 2132) */
66 uint8_t data
[MAX_CLIENT_ID_LEN
];
69 /* 1: Ethernet Link-Layer (RFC 2132) */
70 uint8_t haddr
[ETH_ALEN
];
73 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
77 /* 255: Node-specific (RFC 4361) */
82 uint8_t data
[MAX_CLIENT_ID_LEN
];
88 char *vendor_class_identifier
;
95 sd_event_source
*timeout_t1
;
96 sd_event_source
*timeout_t2
;
97 sd_event_source
*timeout_expire
;
98 sd_dhcp_client_callback_t callback
;
100 sd_dhcp_lease
*lease
;
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_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
526 assert_return(client
, -EINVAL
);
528 if (!IN_SET(client
->state
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
529 return -EADDRNOTAVAIL
;
532 *ret
= client
->lease
;
537 static void client_notify(sd_dhcp_client
*client
, int event
) {
540 if (client
->callback
)
541 client
->callback(client
, event
, client
->userdata
);
544 static int client_initialize(sd_dhcp_client
*client
) {
545 assert_return(client
, -EINVAL
);
547 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
549 client
->fd
= asynchronous_close(client
->fd
);
551 (void) event_source_disable(client
->timeout_resend
);
552 (void) event_source_disable(client
->timeout_t1
);
553 (void) event_source_disable(client
->timeout_t2
);
554 (void) event_source_disable(client
->timeout_expire
);
558 client
->state
= DHCP_STATE_INIT
;
561 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
566 static void client_stop(sd_dhcp_client
*client
, int error
) {
570 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
571 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
572 log_dhcp_client(client
, "STOPPED");
574 log_dhcp_client(client
, "STOPPED: Unknown event");
576 client_notify(client
, error
);
578 client_initialize(client
);
581 static int client_message_init(
582 sd_dhcp_client
*client
,
586 size_t *_optoffset
) {
588 _cleanup_free_ DHCPPacket
*packet
= NULL
;
589 size_t optlen
, optoffset
, size
;
596 assert(client
->start_time
);
600 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
602 optlen
= DHCP_MIN_OPTIONS_SIZE
;
603 size
= sizeof(DHCPPacket
) + optlen
;
605 packet
= malloc0(size
);
609 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
610 client
->arp_type
, optlen
, &optoffset
);
614 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
615 refuse to issue an DHCP lease if 'secs' is set to zero */
616 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
619 assert(time_now
>= client
->start_time
);
621 /* seconds between sending first and last DISCOVER
622 * must always be strictly positive to deal with broken servers */
623 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
624 packet
->dhcp
.secs
= htobe16(secs
);
626 /* RFC2132 section 4.1
627 A client that cannot receive unicast IP datagrams until its protocol
628 software has been configured with an IP address SHOULD set the
629 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
630 DHCPREQUEST messages that client sends. The BROADCAST bit will
631 provide a hint to the DHCP server and BOOTP relay agent to broadcast
632 any messages to the client on the client's subnet.
634 Note: some interfaces needs this to be enabled, but some networks
635 needs this to be disabled as broadcasts are filteretd, so this
636 needs to be configurable */
637 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
638 packet
->dhcp
.flags
= htobe16(0x8000);
640 /* RFC2132 section 4.1.1:
641 The client MUST include its hardware address in the ’chaddr’ field, if
642 necessary for delivery of DHCP reply messages. Non-Ethernet
643 interfaces will leave 'chaddr' empty and use the client identifier
644 instead (eg, RFC 4390 section 2.1).
646 if (client
->arp_type
== ARPHRD_ETHER
)
647 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
649 /* If no client identifier exists, construct an RFC 4361-compliant one */
650 if (client
->client_id_len
== 0) {
653 client
->client_id
.type
= 255;
655 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
656 true, &client
->client_id
.ns
.iaid
);
660 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
664 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
667 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
668 Identifier option is not set */
669 if (client
->client_id_len
) {
670 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
671 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
672 client
->client_id_len
,
678 /* RFC2131 section 3.5:
679 in its initial DHCPDISCOVER or DHCPREQUEST message, a
680 client may provide the server with a list of specific
681 parameters the client is interested in. If the client
682 includes a list of parameters in a DHCPDISCOVER message,
683 it MUST include that list in any subsequent DHCPREQUEST
687 /* RFC7844 section 3:
688 MAY contain the Parameter Request List option. */
689 /* NOTE: in case that there would be an option to do not send
690 * any PRL at all, the size should be checked before sending */
691 if (client
->req_opts_size
> 0) {
692 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
693 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
694 client
->req_opts_size
, client
->req_opts
);
699 /* RFC2131 section 3.5:
700 The client SHOULD include the ’maximum DHCP message size’ option to
701 let the server know how large the server may make its DHCP messages.
703 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
704 than the defined default size unless the Maximum Message Size option
707 RFC3442 "Requirements to Avoid Sizing Constraints":
708 Because a full routing table can be quite large, the standard 576
709 octet maximum size for a DHCP message may be too short to contain
710 some legitimate Classless Static Route options. Because of this,
711 clients implementing the Classless Static Route option SHOULD send a
712 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
713 stack is capable of receiving larger IP datagrams. In this case, the
714 client SHOULD set the value of this option to at least the MTU of the
715 interface that the client is configuring. The client MAY set the
716 value of this option higher, up to the size of the largest UDP packet
717 it is prepared to accept. (Note that the value specified in the
718 Maximum DHCP Message Size option is the total maximum packet size,
719 including IP and UDP headers.)
721 /* RFC7844 section 3:
722 SHOULD NOT contain any other option. */
723 if (!client
->anonymize
) {
724 max_size
= htobe16(size
);
725 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
726 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
733 *_optoffset
= optoffset
;
734 *ret
= TAKE_PTR(packet
);
739 static int client_append_fqdn_option(
740 DHCPMessage
*message
,
745 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
748 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
749 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
750 buffer
[1] = 0; /* RCODE1 (deprecated) */
751 buffer
[2] = 0; /* RCODE2 (deprecated) */
753 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
755 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
756 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
761 static int dhcp_client_send_raw(
762 sd_dhcp_client
*client
,
766 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
767 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
769 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
773 static int client_send_discover(sd_dhcp_client
*client
) {
774 _cleanup_free_ DHCPPacket
*discover
= NULL
;
775 size_t optoffset
, optlen
;
779 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
781 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
782 &optlen
, &optoffset
);
786 /* the client may suggest values for the network address
787 and lease time in the DHCPDISCOVER message. The client may include
788 the ’requested IP address’ option to suggest that a particular IP
789 address be assigned, and may include the ’IP address lease time’
790 option to suggest the lease time it would like.
792 if (client
->last_addr
!= INADDR_ANY
) {
793 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
794 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
795 4, &client
->last_addr
);
800 if (client
->hostname
) {
801 /* According to RFC 4702 "clients that send the Client FQDN option in
802 their messages MUST NOT also send the Host Name option". Just send
803 one of the two depending on the hostname type.
805 if (dns_name_is_single_label(client
->hostname
)) {
806 /* it is unclear from RFC 2131 if client should send hostname in
807 DHCPDISCOVER but dhclient does and so we do as well
809 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
810 SD_DHCP_OPTION_HOST_NAME
,
811 strlen(client
->hostname
), client
->hostname
);
813 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
819 if (client
->vendor_class_identifier
) {
820 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
821 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
822 strlen(client
->vendor_class_identifier
),
823 client
->vendor_class_identifier
);
828 if (client
->user_class
) {
829 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
830 SD_DHCP_OPTION_USER_CLASS
,
831 strv_length(client
->user_class
),
837 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
838 SD_DHCP_OPTION_END
, 0, NULL
);
842 /* We currently ignore:
843 The client SHOULD wait a random time between one and ten seconds to
844 desynchronize the use of DHCP at startup.
846 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
850 log_dhcp_client(client
, "DISCOVER");
855 static int client_send_request(sd_dhcp_client
*client
) {
856 _cleanup_free_ DHCPPacket
*request
= NULL
;
857 size_t optoffset
, optlen
;
862 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
866 switch (client
->state
) {
867 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
868 SELECTING should be REQUESTING)
871 case DHCP_STATE_REQUESTING
:
872 /* Client inserts the address of the selected server in ’server
873 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
874 filled in with the yiaddr value from the chosen DHCPOFFER.
877 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
878 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
879 4, &client
->lease
->server_address
);
883 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
884 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
885 4, &client
->lease
->address
);
891 case DHCP_STATE_INIT_REBOOT
:
892 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
893 option MUST be filled in with client’s notion of its previously
894 assigned address. ’ciaddr’ MUST be zero.
896 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
897 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
898 4, &client
->last_addr
);
903 case DHCP_STATE_RENEWING
:
904 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
905 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
909 case DHCP_STATE_REBINDING
:
910 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
911 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
914 This message MUST be broadcast to the 0xffffffff IP broadcast address.
916 request
->dhcp
.ciaddr
= client
->lease
->address
;
920 case DHCP_STATE_INIT
:
921 case DHCP_STATE_SELECTING
:
922 case DHCP_STATE_REBOOTING
:
923 case DHCP_STATE_BOUND
:
924 case DHCP_STATE_STOPPED
:
928 if (client
->hostname
) {
929 if (dns_name_is_single_label(client
->hostname
))
930 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
931 SD_DHCP_OPTION_HOST_NAME
,
932 strlen(client
->hostname
), client
->hostname
);
934 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
940 if (client
->vendor_class_identifier
) {
941 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
942 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
943 strlen(client
->vendor_class_identifier
),
944 client
->vendor_class_identifier
);
949 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
950 SD_DHCP_OPTION_END
, 0, NULL
);
954 if (client
->state
== DHCP_STATE_RENEWING
) {
955 r
= dhcp_network_send_udp_socket(client
->fd
,
956 client
->lease
->server_address
,
959 sizeof(DHCPMessage
) + optoffset
);
961 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
966 switch (client
->state
) {
968 case DHCP_STATE_REQUESTING
:
969 log_dhcp_client(client
, "REQUEST (requesting)");
972 case DHCP_STATE_INIT_REBOOT
:
973 log_dhcp_client(client
, "REQUEST (init-reboot)");
976 case DHCP_STATE_RENEWING
:
977 log_dhcp_client(client
, "REQUEST (renewing)");
980 case DHCP_STATE_REBINDING
:
981 log_dhcp_client(client
, "REQUEST (rebinding)");
985 log_dhcp_client(client
, "REQUEST (invalid)");
992 static int client_start(sd_dhcp_client
*client
);
994 static int client_timeout_resend(
999 sd_dhcp_client
*client
= userdata
;
1000 DHCP_CLIENT_DONT_DESTROY(client
);
1001 usec_t next_timeout
= 0;
1008 assert(client
->event
);
1010 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1014 switch (client
->state
) {
1016 case DHCP_STATE_RENEWING
:
1018 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1022 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1026 case DHCP_STATE_REBINDING
:
1028 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1032 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1035 case DHCP_STATE_REBOOTING
:
1036 /* start over as we did not receive a timely ack or nak */
1037 r
= client_initialize(client
);
1041 r
= client_start(client
);
1045 log_dhcp_client(client
, "REBOOTED");
1049 case DHCP_STATE_INIT
:
1050 case DHCP_STATE_INIT_REBOOT
:
1051 case DHCP_STATE_SELECTING
:
1052 case DHCP_STATE_REQUESTING
:
1053 case DHCP_STATE_BOUND
:
1055 if (client
->attempt
< MAX_CLIENT_ATTEMPT
)
1056 client
->attempt
*= 2;
1060 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
1064 case DHCP_STATE_STOPPED
:
1069 next_timeout
+= (random_u32() & 0x1fffff);
1071 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1072 clock_boottime_or_monotonic(),
1073 next_timeout
, 10 * USEC_PER_MSEC
,
1074 client_timeout_resend
, client
,
1075 client
->event_priority
, "dhcp4-resend-timer", true);
1079 switch (client
->state
) {
1080 case DHCP_STATE_INIT
:
1081 r
= client_send_discover(client
);
1083 client
->state
= DHCP_STATE_SELECTING
;
1084 client
->attempt
= 1;
1086 if (client
->attempt
>= MAX_CLIENT_ATTEMPT
)
1092 case DHCP_STATE_SELECTING
:
1093 r
= client_send_discover(client
);
1094 if (r
< 0 && client
->attempt
>= MAX_CLIENT_ATTEMPT
)
1099 case DHCP_STATE_INIT_REBOOT
:
1100 case DHCP_STATE_REQUESTING
:
1101 case DHCP_STATE_RENEWING
:
1102 case DHCP_STATE_REBINDING
:
1103 r
= client_send_request(client
);
1104 if (r
< 0 && client
->attempt
>= MAX_CLIENT_ATTEMPT
)
1107 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1108 client
->state
= DHCP_STATE_REBOOTING
;
1110 client
->request_sent
= time_now
;
1114 case DHCP_STATE_REBOOTING
:
1115 case DHCP_STATE_BOUND
:
1119 case DHCP_STATE_STOPPED
:
1127 client_stop(client
, r
);
1129 /* Errors were dealt with when stopping the client, don't spill
1130 errors into the event loop handler */
1134 static int client_initialize_io_events(
1135 sd_dhcp_client
*client
,
1136 sd_event_io_handler_t io_callback
) {
1141 assert(client
->event
);
1143 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1144 client
->fd
, EPOLLIN
, io_callback
,
1149 r
= sd_event_source_set_priority(client
->receive_message
,
1150 client
->event_priority
);
1154 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1160 client_stop(client
, r
);
1165 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1170 assert(client
->event
);
1172 if (client
->start_delay
) {
1173 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1174 usec
+= client
->start_delay
;
1177 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1178 clock_boottime_or_monotonic(),
1180 client_timeout_resend
, client
,
1181 client
->event_priority
, "dhcp4-resend-timer", true);
1183 client_stop(client
, r
);
1189 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1190 client_initialize_io_events(client
, io_callback
);
1191 client_initialize_time_events(client
);
1196 static int client_start_delayed(sd_dhcp_client
*client
) {
1199 assert_return(client
, -EINVAL
);
1200 assert_return(client
->event
, -EINVAL
);
1201 assert_return(client
->ifindex
> 0, -EINVAL
);
1202 assert_return(client
->fd
< 0, -EBUSY
);
1203 assert_return(client
->xid
== 0, -EINVAL
);
1204 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1206 client
->xid
= random_u32();
1208 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1209 client
->xid
, client
->mac_addr
,
1210 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1212 client_stop(client
, r
);
1217 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1218 client
->start_time
= now(clock_boottime_or_monotonic());
1220 return client_initialize_events(client
, client_receive_message_raw
);
1223 static int client_start(sd_dhcp_client
*client
) {
1224 client
->start_delay
= 0;
1225 return client_start_delayed(client
);
1228 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1229 sd_dhcp_client
*client
= userdata
;
1230 DHCP_CLIENT_DONT_DESTROY(client
);
1232 log_dhcp_client(client
, "EXPIRED");
1234 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1236 /* lease was lost, start over if not freed or stopped in callback */
1237 if (client
->state
!= DHCP_STATE_STOPPED
) {
1238 client_initialize(client
);
1239 client_start(client
);
1245 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1246 sd_dhcp_client
*client
= userdata
;
1247 DHCP_CLIENT_DONT_DESTROY(client
);
1252 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1253 client
->fd
= asynchronous_close(client
->fd
);
1255 client
->state
= DHCP_STATE_REBINDING
;
1256 client
->attempt
= 1;
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
,
1263 client_stop(client
, r
);
1268 return client_initialize_events(client
, client_receive_message_raw
);
1271 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1272 sd_dhcp_client
*client
= userdata
;
1273 DHCP_CLIENT_DONT_DESTROY(client
);
1275 client
->state
= DHCP_STATE_RENEWING
;
1276 client
->attempt
= 1;
1278 return client_initialize_time_events(client
);
1281 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1282 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1285 r
= dhcp_lease_new(&lease
);
1289 if (client
->client_id_len
) {
1290 r
= dhcp_lease_set_client_id(lease
,
1291 (uint8_t *) &client
->client_id
,
1292 client
->client_id_len
);
1297 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1298 if (r
!= DHCP_OFFER
) {
1299 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1303 lease
->next_server
= offer
->siaddr
;
1304 lease
->address
= offer
->yiaddr
;
1306 if (lease
->address
== 0 ||
1307 lease
->server_address
== 0 ||
1308 lease
->lifetime
== 0) {
1309 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1313 if (!lease
->have_subnet_mask
) {
1314 r
= dhcp_lease_set_default_subnet_mask(lease
);
1316 log_dhcp_client(client
,
1317 "received lease lacks subnet mask, "
1318 "and a fallback one cannot be generated, ignoring");
1323 sd_dhcp_lease_unref(client
->lease
);
1324 client
->lease
= TAKE_PTR(lease
);
1326 log_dhcp_client(client
, "OFFER");
1331 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1334 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1335 if (r
!= DHCP_FORCERENEW
)
1338 log_dhcp_client(client
, "FORCERENEW");
1343 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1344 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1345 _cleanup_free_
char *error_message
= NULL
;
1348 r
= dhcp_lease_new(&lease
);
1352 if (client
->client_id_len
) {
1353 r
= dhcp_lease_set_client_id(lease
,
1354 (uint8_t *) &client
->client_id
,
1355 client
->client_id_len
);
1360 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1361 if (r
== DHCP_NAK
) {
1362 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1363 return -EADDRNOTAVAIL
;
1366 if (r
!= DHCP_ACK
) {
1367 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1371 lease
->next_server
= ack
->siaddr
;
1373 lease
->address
= ack
->yiaddr
;
1375 if (lease
->address
== INADDR_ANY
||
1376 lease
->server_address
== INADDR_ANY
||
1377 lease
->lifetime
== 0) {
1378 log_dhcp_client(client
, "received lease lacks address, server "
1379 "address or lease lifetime, ignoring");
1383 if (lease
->subnet_mask
== INADDR_ANY
) {
1384 r
= dhcp_lease_set_default_subnet_mask(lease
);
1386 log_dhcp_client(client
,
1387 "received lease lacks subnet mask, "
1388 "and a fallback one cannot be generated, ignoring");
1393 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1394 if (client
->lease
) {
1395 if (client
->lease
->address
!= lease
->address
||
1396 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1397 client
->lease
->router
!= lease
->router
) {
1398 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1400 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1402 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1405 client
->lease
= TAKE_PTR(lease
);
1407 log_dhcp_client(client
, "ACK");
1412 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1414 assert(client
->request_sent
);
1415 assert(lifetime
> 0);
1422 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1423 + (random_u32() & 0x1fffff);
1426 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1428 uint64_t lifetime_timeout
;
1429 uint64_t t2_timeout
;
1430 uint64_t t1_timeout
;
1431 char time_string
[FORMAT_TIMESPAN_MAX
];
1435 assert(client
->event
);
1436 assert(client
->lease
);
1437 assert(client
->lease
->lifetime
);
1439 /* don't set timers for infinite leases */
1440 if (client
->lease
->lifetime
== 0xffffffff) {
1441 (void) event_source_disable(client
->timeout_t1
);
1442 (void) event_source_disable(client
->timeout_t2
);
1443 (void) event_source_disable(client
->timeout_expire
);
1448 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1451 assert(client
->request_sent
<= time_now
);
1453 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1454 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1455 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1456 /* both T1 and T2 are given */
1457 if (client
->lease
->t1
< client
->lease
->t2
&&
1458 client
->lease
->t2
< client
->lease
->lifetime
) {
1459 /* they are both valid */
1460 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1461 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1464 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1465 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1466 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1467 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1469 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1470 /* only T2 is given, and it is valid */
1471 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1472 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1473 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1474 if (t2_timeout
<= t1_timeout
) {
1475 /* the computed T1 would be invalid, so discard T2 */
1476 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1477 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1479 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1480 /* only T1 is given, and it is valid */
1481 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1482 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1483 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1484 if (t2_timeout
<= t1_timeout
) {
1485 /* the computed T2 would be invalid, so discard T1 */
1486 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1487 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1490 /* fall back to the default timeouts */
1491 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1492 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1493 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1494 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1497 /* arm lifetime timeout */
1498 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1499 clock_boottime_or_monotonic(),
1500 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1501 client_timeout_expire
, client
,
1502 client
->event_priority
, "dhcp4-lifetime", true);
1506 log_dhcp_client(client
, "lease expires in %s",
1507 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1509 /* don't arm earlier timeouts if this has already expired */
1510 if (lifetime_timeout
<= time_now
)
1513 /* arm T2 timeout */
1514 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1515 clock_boottime_or_monotonic(),
1516 t2_timeout
, 10 * USEC_PER_MSEC
,
1517 client_timeout_t2
, client
,
1518 client
->event_priority
, "dhcp4-t2-timeout", true);
1522 log_dhcp_client(client
, "T2 expires in %s",
1523 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1525 /* don't arm earlier timeout if this has already expired */
1526 if (t2_timeout
<= time_now
)
1529 /* arm T1 timeout */
1530 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1531 clock_boottime_or_monotonic(),
1532 t1_timeout
, 10 * USEC_PER_MSEC
,
1533 client_timeout_t1
, client
,
1534 client
->event_priority
, "dhcp4-t1-timer", true);
1538 log_dhcp_client(client
, "T1 expires in %s",
1539 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1544 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1545 DHCP_CLIENT_DONT_DESTROY(client
);
1546 char time_string
[FORMAT_TIMESPAN_MAX
];
1547 int r
= 0, notify_event
= 0;
1550 assert(client
->event
);
1553 switch (client
->state
) {
1554 case DHCP_STATE_SELECTING
:
1556 r
= client_handle_offer(client
, message
, len
);
1559 client
->state
= DHCP_STATE_REQUESTING
;
1560 client
->attempt
= 1;
1562 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1563 clock_boottime_or_monotonic(),
1565 client_timeout_resend
, client
,
1566 client
->event_priority
, "dhcp4-resend-timer", true);
1569 } else if (r
== -ENOMSG
)
1570 /* invalid message, let's ignore it */
1575 case DHCP_STATE_REBOOTING
:
1576 case DHCP_STATE_REQUESTING
:
1577 case DHCP_STATE_RENEWING
:
1578 case DHCP_STATE_REBINDING
:
1580 r
= client_handle_ack(client
, message
, len
);
1582 client
->start_delay
= 0;
1583 (void) event_source_disable(client
->timeout_resend
);
1584 client
->receive_message
=
1585 sd_event_source_unref(client
->receive_message
);
1586 client
->fd
= asynchronous_close(client
->fd
);
1588 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1589 DHCP_STATE_REBOOTING
))
1590 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1591 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1594 client
->state
= DHCP_STATE_BOUND
;
1595 client
->attempt
= 1;
1597 client
->last_addr
= client
->lease
->address
;
1599 r
= client_set_lease_timeouts(client
);
1601 log_dhcp_client(client
, "could not set lease timeouts");
1605 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1607 log_dhcp_client(client
, "could not bind UDP socket");
1613 client_initialize_io_events(client
, client_receive_message_udp
);
1616 client_notify(client
, notify_event
);
1617 if (client
->state
== DHCP_STATE_STOPPED
)
1621 } else if (r
== -EADDRNOTAVAIL
) {
1622 /* got a NAK, let's restart the client */
1623 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1625 r
= client_initialize(client
);
1629 r
= client_start_delayed(client
);
1633 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1634 client
->start_delay
, USEC_PER_SEC
));
1636 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1637 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1640 } else if (r
== -ENOMSG
)
1641 /* invalid message, let's ignore it */
1646 case DHCP_STATE_BOUND
:
1647 r
= client_handle_forcerenew(client
, message
, len
);
1649 r
= client_timeout_t1(NULL
, 0, client
);
1652 } else if (r
== -ENOMSG
)
1653 /* invalid message, let's ignore it */
1658 case DHCP_STATE_INIT
:
1659 case DHCP_STATE_INIT_REBOOT
:
1663 case DHCP_STATE_STOPPED
:
1670 client_stop(client
, r
);
1675 static int client_receive_message_udp(
1681 sd_dhcp_client
*client
= userdata
;
1682 _cleanup_free_ DHCPMessage
*message
= NULL
;
1683 const uint8_t *expected_chaddr
= NULL
;
1684 uint8_t expected_hlen
= 0;
1685 ssize_t len
, buflen
;
1690 buflen
= next_datagram_size_fd(fd
);
1691 if (buflen
== -ENETDOWN
) {
1692 /* the link is down. Don't return an error or the I/O event
1693 source will be disconnected and we won't be able to receive
1694 packets again when the link comes back. */
1700 message
= malloc0(buflen
);
1704 len
= recv(fd
, message
, buflen
, 0);
1706 /* see comment above for why we shouldn't error out on ENETDOWN. */
1707 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1710 return log_dhcp_client_errno(client
, errno
,
1711 "Could not receive message from UDP socket: %m");
1713 if ((size_t) len
< sizeof(DHCPMessage
)) {
1714 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1718 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1719 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1723 if (message
->op
!= BOOTREPLY
) {
1724 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1728 if (message
->htype
!= client
->arp_type
) {
1729 log_dhcp_client(client
, "Packet type does not match client type");
1733 if (client
->arp_type
== ARPHRD_ETHER
) {
1734 expected_hlen
= ETH_ALEN
;
1735 expected_chaddr
= &client
->mac_addr
[0];
1738 if (message
->hlen
!= expected_hlen
) {
1739 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1743 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1744 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1748 if (client
->state
!= DHCP_STATE_BOUND
&&
1749 be32toh(message
->xid
) != client
->xid
) {
1750 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1751 so ignore the xid in this case */
1752 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1753 be32toh(message
->xid
), client
->xid
);
1757 return client_handle_message(client
, message
, len
);
1760 static int client_receive_message_raw(
1766 sd_dhcp_client
*client
= userdata
;
1767 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1768 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1769 struct iovec iov
= {};
1770 struct msghdr msg
= {
1773 .msg_control
= cmsgbuf
,
1774 .msg_controllen
= sizeof(cmsgbuf
),
1776 struct cmsghdr
*cmsg
;
1777 bool checksum
= true;
1778 ssize_t buflen
, len
;
1784 buflen
= next_datagram_size_fd(fd
);
1785 if (buflen
== -ENETDOWN
)
1790 packet
= malloc0(buflen
);
1794 iov
= IOVEC_MAKE(packet
, buflen
);
1796 len
= recvmsg(fd
, &msg
, 0);
1798 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1801 return log_dhcp_client_errno(client
, errno
,
1802 "Could not receive message from raw socket: %m");
1803 } else if ((size_t)len
< sizeof(DHCPPacket
))
1806 CMSG_FOREACH(cmsg
, &msg
)
1807 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1808 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1809 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1810 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1812 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1816 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1820 len
-= DHCP_IP_UDP_SIZE
;
1822 return client_handle_message(client
, &packet
->dhcp
, len
);
1825 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1828 assert_return(client
, -EINVAL
);
1830 r
= client_initialize(client
);
1834 /* RFC7844 section 3.3:
1835 SHOULD perform a complete four-way handshake, starting with a
1836 DHCPDISCOVER, to obtain a new address lease. If the client can
1837 ascertain that this is exactly the same network to which it was
1838 previously connected, and if the link-layer address did not change,
1839 the client MAY issue a DHCPREQUEST to try to reclaim the current
1841 if (client
->last_addr
&& !client
->anonymize
)
1842 client
->state
= DHCP_STATE_INIT_REBOOT
;
1844 r
= client_start(client
);
1846 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1851 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1852 DHCP_CLIENT_DONT_DESTROY(client
);
1854 assert_return(client
, -EINVAL
);
1856 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1857 client
->state
= DHCP_STATE_STOPPED
;
1862 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1865 assert_return(client
, -EINVAL
);
1866 assert_return(!client
->event
, -EBUSY
);
1869 client
->event
= sd_event_ref(event
);
1871 r
= sd_event_default(&client
->event
);
1876 client
->event_priority
= priority
;
1881 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1882 assert_return(client
, -EINVAL
);
1884 client
->event
= sd_event_unref(client
->event
);
1889 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1890 assert_return(client
, NULL
);
1892 return client
->event
;
1895 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1898 log_dhcp_client(client
, "FREE");
1900 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1901 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1902 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1903 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1905 client_initialize(client
);
1907 sd_dhcp_client_detach_event(client
);
1909 sd_dhcp_lease_unref(client
->lease
);
1911 free(client
->req_opts
);
1912 free(client
->hostname
);
1913 free(client
->vendor_class_identifier
);
1914 client
->user_class
= strv_free(client
->user_class
);
1915 return mfree(client
);
1918 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1920 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1921 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1923 assert_return(ret
, -EINVAL
);
1925 client
= new(sd_dhcp_client
, 1);
1929 *client
= (sd_dhcp_client
) {
1931 .state
= DHCP_STATE_INIT
,
1935 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1936 .port
= DHCP_PORT_CLIENT
,
1937 .anonymize
= !!anonymize
,
1939 /* NOTE: this could be moved to a function. */
1941 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1942 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1944 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1945 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1947 if (!client
->req_opts
)
1950 *ret
= TAKE_PTR(client
);