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
;
103 static const uint8_t default_req_opts
[] = {
104 SD_DHCP_OPTION_SUBNET_MASK
,
105 SD_DHCP_OPTION_ROUTER
,
106 SD_DHCP_OPTION_HOST_NAME
,
107 SD_DHCP_OPTION_DOMAIN_NAME
,
108 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
111 /* RFC7844 section 3:
112 MAY contain the Parameter Request List option.
114 The client intending to protect its privacy SHOULD only request a
115 minimal number of options in the PRL and SHOULD also randomly shuffle
116 the ordering of option codes in the PRL. If this random ordering
117 cannot be implemented, the client MAY order the option codes in the
118 PRL by option code number (lowest to highest).
120 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
121 static const uint8_t default_req_opts_anonymize
[] = {
122 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
123 SD_DHCP_OPTION_ROUTER
, /* 3 */
124 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
125 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
126 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
127 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
128 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
129 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
130 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
131 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
132 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
133 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
134 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
137 static int client_receive_message_raw(
142 static int client_receive_message_udp(
147 static void client_stop(sd_dhcp_client
*client
, int error
);
149 int sd_dhcp_client_set_callback(
150 sd_dhcp_client
*client
,
151 sd_dhcp_client_callback_t cb
,
154 assert_return(client
, -EINVAL
);
156 client
->callback
= cb
;
157 client
->userdata
= userdata
;
162 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
163 assert_return(client
, -EINVAL
);
165 client
->request_broadcast
= !!broadcast
;
170 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
173 assert_return(client
, -EINVAL
);
174 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
178 case SD_DHCP_OPTION_PAD
:
179 case SD_DHCP_OPTION_OVERLOAD
:
180 case SD_DHCP_OPTION_MESSAGE_TYPE
:
181 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
182 case SD_DHCP_OPTION_END
:
189 for (i
= 0; i
< client
->req_opts_size
; i
++)
190 if (client
->req_opts
[i
] == option
)
193 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
194 client
->req_opts_size
+ 1))
197 client
->req_opts
[client
->req_opts_size
++] = option
;
202 int sd_dhcp_client_set_request_address(
203 sd_dhcp_client
*client
,
204 const struct in_addr
*last_addr
) {
206 assert_return(client
, -EINVAL
);
207 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
210 client
->last_addr
= last_addr
->s_addr
;
212 client
->last_addr
= INADDR_ANY
;
217 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
219 assert_return(client
, -EINVAL
);
220 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
221 assert_return(ifindex
> 0, -EINVAL
);
223 client
->ifindex
= ifindex
;
227 int sd_dhcp_client_set_mac(
228 sd_dhcp_client
*client
,
233 DHCP_CLIENT_DONT_DESTROY(client
);
234 bool need_restart
= false;
236 assert_return(client
, -EINVAL
);
237 assert_return(addr
, -EINVAL
);
238 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
239 assert_return(arp_type
> 0, -EINVAL
);
241 if (arp_type
== ARPHRD_ETHER
)
242 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
243 else if (arp_type
== ARPHRD_INFINIBAND
)
244 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
248 if (client
->mac_addr_len
== addr_len
&&
249 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
252 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
253 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
255 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
258 memcpy(&client
->mac_addr
, addr
, addr_len
);
259 client
->mac_addr_len
= addr_len
;
260 client
->arp_type
= arp_type
;
262 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
263 sd_dhcp_client_start(client
);
268 int sd_dhcp_client_get_client_id(
269 sd_dhcp_client
*client
,
271 const uint8_t **data
,
274 assert_return(client
, -EINVAL
);
275 assert_return(type
, -EINVAL
);
276 assert_return(data
, -EINVAL
);
277 assert_return(data_len
, -EINVAL
);
282 if (client
->client_id_len
) {
283 *type
= client
->client_id
.type
;
284 *data
= client
->client_id
.raw
.data
;
285 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
291 int sd_dhcp_client_set_client_id(
292 sd_dhcp_client
*client
,
297 DHCP_CLIENT_DONT_DESTROY(client
);
298 bool need_restart
= false;
300 assert_return(client
, -EINVAL
);
301 assert_return(data
, -EINVAL
);
302 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
304 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
305 client
->client_id
.type
== type
&&
306 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
309 /* For hardware types, log debug message about unexpected data length.
311 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
312 * last last 8 bytes of the address are stable and suitable to put into
313 * the client-id. The caller is advised to account for that. */
314 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
315 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
316 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
317 "unexpected address length %zu",
320 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
321 log_dhcp_client(client
, "Changing client ID on running DHCP "
322 "client, restarting");
324 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
327 client
->client_id
.type
= type
;
328 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
329 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
331 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
332 sd_dhcp_client_start(client
);
338 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
339 * without further modification. Otherwise, if duid_type is supported, DUID
340 * is set based on that type. Otherwise, an error is returned.
342 static int dhcp_client_set_iaid_duid_internal(
343 sd_dhcp_client
*client
,
352 DHCP_CLIENT_DONT_DESTROY(client
);
356 assert_return(client
, -EINVAL
);
357 assert_return(duid_len
== 0 || duid
, -EINVAL
);
360 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
365 zero(client
->client_id
);
366 client
->client_id
.type
= 255;
370 client
->client_id
.ns
.iaid
= htobe32(iaid
);
372 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
373 client
->mac_addr_len
,
375 &client
->client_id
.ns
.iaid
);
382 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
383 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
384 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
388 if (client
->mac_addr_len
== 0)
391 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
396 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
401 if (client
->mac_addr_len
== 0)
404 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
409 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
417 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
418 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
420 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
421 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
422 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
423 sd_dhcp_client_start(client
);
429 int sd_dhcp_client_set_iaid_duid(
430 sd_dhcp_client
*client
,
436 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
439 int sd_dhcp_client_set_iaid_duid_llt(
440 sd_dhcp_client
*client
,
444 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
447 int sd_dhcp_client_set_duid(
448 sd_dhcp_client
*client
,
452 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
455 int sd_dhcp_client_set_duid_llt(
456 sd_dhcp_client
*client
,
458 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
461 int sd_dhcp_client_set_hostname(
462 sd_dhcp_client
*client
,
463 const char *hostname
) {
465 assert_return(client
, -EINVAL
);
467 /* Make sure hostnames qualify as DNS and as Linux hostnames */
469 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
472 return free_and_strdup(&client
->hostname
, hostname
);
475 int sd_dhcp_client_set_vendor_class_identifier(
476 sd_dhcp_client
*client
,
479 assert_return(client
, -EINVAL
);
481 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
484 int sd_dhcp_client_set_user_class(
485 sd_dhcp_client
*client
,
486 const char* const* user_class
) {
488 _cleanup_strv_free_
char **s
= NULL
;
491 STRV_FOREACH(p
, (char **) user_class
)
492 if (strlen(*p
) > 255)
493 return -ENAMETOOLONG
;
495 s
= strv_copy((char **) user_class
);
499 client
->user_class
= TAKE_PTR(s
);
504 int sd_dhcp_client_set_client_port(
505 sd_dhcp_client
*client
,
508 assert_return(client
, -EINVAL
);
515 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
516 assert_return(client
, -EINVAL
);
517 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
524 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
525 assert_return(client
, -EINVAL
);
527 client
->max_attempts
= max_attempts
;
532 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
533 assert_return(client
, -EINVAL
);
535 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
536 return -EADDRNOTAVAIL
;
539 *ret
= client
->lease
;
544 static int client_notify(sd_dhcp_client
*client
, int event
) {
547 if (client
->callback
)
548 return client
->callback(client
, event
, client
->userdata
);
553 static int client_initialize(sd_dhcp_client
*client
) {
554 assert_return(client
, -EINVAL
);
556 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
558 client
->fd
= asynchronous_close(client
->fd
);
560 (void) event_source_disable(client
->timeout_resend
);
561 (void) event_source_disable(client
->timeout_t1
);
562 (void) event_source_disable(client
->timeout_t2
);
563 (void) event_source_disable(client
->timeout_expire
);
567 client
->state
= DHCP_STATE_INIT
;
570 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
575 static void client_stop(sd_dhcp_client
*client
, int error
) {
579 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
580 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
581 log_dhcp_client(client
, "STOPPED");
583 log_dhcp_client(client
, "STOPPED: Unknown event");
585 client_notify(client
, error
);
587 client_initialize(client
);
590 static int client_message_init(
591 sd_dhcp_client
*client
,
595 size_t *_optoffset
) {
597 _cleanup_free_ DHCPPacket
*packet
= NULL
;
598 size_t optlen
, optoffset
, size
;
605 assert(client
->start_time
);
609 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
));
611 optlen
= DHCP_MIN_OPTIONS_SIZE
;
612 size
= sizeof(DHCPPacket
) + optlen
;
614 packet
= malloc0(size
);
618 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
619 client
->arp_type
, optlen
, &optoffset
);
623 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
624 refuse to issue an DHCP lease if 'secs' is set to zero */
625 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
628 assert(time_now
>= client
->start_time
);
630 /* seconds between sending first and last DISCOVER
631 * must always be strictly positive to deal with broken servers */
632 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
633 packet
->dhcp
.secs
= htobe16(secs
);
635 /* RFC2132 section 4.1
636 A client that cannot receive unicast IP datagrams until its protocol
637 software has been configured with an IP address SHOULD set the
638 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
639 DHCPREQUEST messages that client sends. The BROADCAST bit will
640 provide a hint to the DHCP server and BOOTP relay agent to broadcast
641 any messages to the client on the client's subnet.
643 Note: some interfaces needs this to be enabled, but some networks
644 needs this to be disabled as broadcasts are filteretd, so this
645 needs to be configurable */
646 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
647 packet
->dhcp
.flags
= htobe16(0x8000);
649 /* RFC2132 section 4.1.1:
650 The client MUST include its hardware address in the ’chaddr’ field, if
651 necessary for delivery of DHCP reply messages. Non-Ethernet
652 interfaces will leave 'chaddr' empty and use the client identifier
653 instead (eg, RFC 4390 section 2.1).
655 if (client
->arp_type
== ARPHRD_ETHER
)
656 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
658 /* If no client identifier exists, construct an RFC 4361-compliant one */
659 if (client
->client_id_len
== 0) {
662 client
->client_id
.type
= 255;
664 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
665 true, &client
->client_id
.ns
.iaid
);
669 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
673 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
676 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
677 Identifier option is not set */
678 if (client
->client_id_len
) {
679 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
680 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
681 client
->client_id_len
,
687 /* RFC2131 section 3.5:
688 in its initial DHCPDISCOVER or DHCPREQUEST message, a
689 client may provide the server with a list of specific
690 parameters the client is interested in. If the client
691 includes a list of parameters in a DHCPDISCOVER message,
692 it MUST include that list in any subsequent DHCPREQUEST
696 /* RFC7844 section 3:
697 MAY contain the Parameter Request List option. */
698 /* NOTE: in case that there would be an option to do not send
699 * any PRL at all, the size should be checked before sending */
700 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
701 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
702 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
703 client
->req_opts_size
, client
->req_opts
);
708 /* RFC2131 section 3.5:
709 The client SHOULD include the ’maximum DHCP message size’ option to
710 let the server know how large the server may make its DHCP messages.
712 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
713 than the defined default size unless the Maximum Message Size option
716 RFC3442 "Requirements to Avoid Sizing Constraints":
717 Because a full routing table can be quite large, the standard 576
718 octet maximum size for a DHCP message may be too short to contain
719 some legitimate Classless Static Route options. Because of this,
720 clients implementing the Classless Static Route option SHOULD send a
721 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
722 stack is capable of receiving larger IP datagrams. In this case, the
723 client SHOULD set the value of this option to at least the MTU of the
724 interface that the client is configuring. The client MAY set the
725 value of this option higher, up to the size of the largest UDP packet
726 it is prepared to accept. (Note that the value specified in the
727 Maximum DHCP Message Size option is the total maximum packet size,
728 including IP and UDP headers.)
730 /* RFC7844 section 3:
731 SHOULD NOT contain any other option. */
732 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
733 max_size
= htobe16(size
);
734 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
735 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
742 *_optoffset
= optoffset
;
743 *ret
= TAKE_PTR(packet
);
748 static int client_append_fqdn_option(
749 DHCPMessage
*message
,
754 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
757 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
758 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
759 buffer
[1] = 0; /* RCODE1 (deprecated) */
760 buffer
[2] = 0; /* RCODE2 (deprecated) */
762 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
764 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
765 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
770 static int dhcp_client_send_raw(
771 sd_dhcp_client
*client
,
775 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
776 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
778 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
782 static int client_send_discover(sd_dhcp_client
*client
) {
783 _cleanup_free_ DHCPPacket
*discover
= NULL
;
784 size_t optoffset
, optlen
;
788 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
790 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
791 &optlen
, &optoffset
);
795 /* the client may suggest values for the network address
796 and lease time in the DHCPDISCOVER message. The client may include
797 the ’requested IP address’ option to suggest that a particular IP
798 address be assigned, and may include the ’IP address lease time’
799 option to suggest the lease time it would like.
801 if (client
->last_addr
!= INADDR_ANY
) {
802 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
803 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
804 4, &client
->last_addr
);
809 if (client
->hostname
) {
810 /* According to RFC 4702 "clients that send the Client FQDN option in
811 their messages MUST NOT also send the Host Name option". Just send
812 one of the two depending on the hostname type.
814 if (dns_name_is_single_label(client
->hostname
)) {
815 /* it is unclear from RFC 2131 if client should send hostname in
816 DHCPDISCOVER but dhclient does and so we do as well
818 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
819 SD_DHCP_OPTION_HOST_NAME
,
820 strlen(client
->hostname
), client
->hostname
);
822 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
828 if (client
->vendor_class_identifier
) {
829 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
830 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
831 strlen(client
->vendor_class_identifier
),
832 client
->vendor_class_identifier
);
837 if (client
->user_class
) {
838 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
839 SD_DHCP_OPTION_USER_CLASS
,
840 strv_length(client
->user_class
),
846 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
847 SD_DHCP_OPTION_END
, 0, NULL
);
851 /* We currently ignore:
852 The client SHOULD wait a random time between one and ten seconds to
853 desynchronize the use of DHCP at startup.
855 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
859 log_dhcp_client(client
, "DISCOVER");
864 static int client_send_release(sd_dhcp_client
*client
) {
865 _cleanup_free_ DHCPPacket
*release
= NULL
;
866 size_t optoffset
, optlen
;
870 assert(!IN_SET(client
->state
, DHCP_STATE_STOPPED
));
872 r
= client_message_init(client
, &release
, DHCP_RELEASE
,
873 &optlen
, &optoffset
);
877 /* Fill up release IP and MAC */
878 release
->dhcp
.ciaddr
= client
->lease
->address
;
879 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
881 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
882 SD_DHCP_OPTION_END
, 0, NULL
);
886 r
= dhcp_network_send_udp_socket(client
->fd
,
887 client
->lease
->server_address
,
890 sizeof(DHCPMessage
) + optoffset
);
894 log_dhcp_client(client
, "RELEASE");
899 static int client_send_request(sd_dhcp_client
*client
) {
900 _cleanup_free_ DHCPPacket
*request
= NULL
;
901 size_t optoffset
, optlen
;
906 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
910 switch (client
->state
) {
911 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
912 SELECTING should be REQUESTING)
915 case DHCP_STATE_REQUESTING
:
916 /* Client inserts the address of the selected server in ’server
917 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
918 filled in with the yiaddr value from the chosen DHCPOFFER.
921 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
922 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
923 4, &client
->lease
->server_address
);
927 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
928 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
929 4, &client
->lease
->address
);
935 case DHCP_STATE_INIT_REBOOT
:
936 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
937 option MUST be filled in with client’s notion of its previously
938 assigned address. ’ciaddr’ MUST be zero.
940 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
941 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
942 4, &client
->last_addr
);
947 case DHCP_STATE_RENEWING
:
948 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
949 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
953 case DHCP_STATE_REBINDING
:
954 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
955 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
958 This message MUST be broadcast to the 0xffffffff IP broadcast address.
960 request
->dhcp
.ciaddr
= client
->lease
->address
;
964 case DHCP_STATE_INIT
:
965 case DHCP_STATE_SELECTING
:
966 case DHCP_STATE_REBOOTING
:
967 case DHCP_STATE_BOUND
:
968 case DHCP_STATE_STOPPED
:
972 if (client
->hostname
) {
973 if (dns_name_is_single_label(client
->hostname
))
974 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
975 SD_DHCP_OPTION_HOST_NAME
,
976 strlen(client
->hostname
), client
->hostname
);
978 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
984 if (client
->vendor_class_identifier
) {
985 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
986 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
987 strlen(client
->vendor_class_identifier
),
988 client
->vendor_class_identifier
);
993 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
994 SD_DHCP_OPTION_END
, 0, NULL
);
998 if (client
->state
== DHCP_STATE_RENEWING
) {
999 r
= dhcp_network_send_udp_socket(client
->fd
,
1000 client
->lease
->server_address
,
1003 sizeof(DHCPMessage
) + optoffset
);
1005 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1010 switch (client
->state
) {
1012 case DHCP_STATE_REQUESTING
:
1013 log_dhcp_client(client
, "REQUEST (requesting)");
1016 case DHCP_STATE_INIT_REBOOT
:
1017 log_dhcp_client(client
, "REQUEST (init-reboot)");
1020 case DHCP_STATE_RENEWING
:
1021 log_dhcp_client(client
, "REQUEST (renewing)");
1024 case DHCP_STATE_REBINDING
:
1025 log_dhcp_client(client
, "REQUEST (rebinding)");
1029 log_dhcp_client(client
, "REQUEST (invalid)");
1036 static int client_start(sd_dhcp_client
*client
);
1038 static int client_timeout_resend(
1043 sd_dhcp_client
*client
= userdata
;
1044 DHCP_CLIENT_DONT_DESTROY(client
);
1045 usec_t next_timeout
= 0;
1052 assert(client
->event
);
1054 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1058 switch (client
->state
) {
1060 case DHCP_STATE_RENEWING
:
1062 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1066 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1070 case DHCP_STATE_REBINDING
:
1072 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1076 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1079 case DHCP_STATE_REBOOTING
:
1080 /* start over as we did not receive a timely ack or nak */
1081 r
= client_initialize(client
);
1085 r
= client_start(client
);
1089 log_dhcp_client(client
, "REBOOTED");
1093 case DHCP_STATE_INIT
:
1094 case DHCP_STATE_INIT_REBOOT
:
1095 case DHCP_STATE_SELECTING
:
1096 case DHCP_STATE_REQUESTING
:
1097 case DHCP_STATE_BOUND
:
1099 if (client
->attempt
< client
->max_attempts
)
1104 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1108 case DHCP_STATE_STOPPED
:
1113 next_timeout
+= (random_u32() & 0x1fffff);
1115 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1116 clock_boottime_or_monotonic(),
1117 next_timeout
, 10 * USEC_PER_MSEC
,
1118 client_timeout_resend
, client
,
1119 client
->event_priority
, "dhcp4-resend-timer", true);
1123 switch (client
->state
) {
1124 case DHCP_STATE_INIT
:
1125 r
= client_send_discover(client
);
1127 client
->state
= DHCP_STATE_SELECTING
;
1128 client
->attempt
= 0;
1129 } else if (client
->attempt
>= client
->max_attempts
)
1134 case DHCP_STATE_SELECTING
:
1135 r
= client_send_discover(client
);
1136 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1141 case DHCP_STATE_INIT_REBOOT
:
1142 case DHCP_STATE_REQUESTING
:
1143 case DHCP_STATE_RENEWING
:
1144 case DHCP_STATE_REBINDING
:
1145 r
= client_send_request(client
);
1146 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1149 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1150 client
->state
= DHCP_STATE_REBOOTING
;
1152 client
->request_sent
= time_now
;
1156 case DHCP_STATE_REBOOTING
:
1157 case DHCP_STATE_BOUND
:
1161 case DHCP_STATE_STOPPED
:
1169 client_stop(client
, r
);
1171 /* Errors were dealt with when stopping the client, don't spill
1172 errors into the event loop handler */
1176 static int client_initialize_io_events(
1177 sd_dhcp_client
*client
,
1178 sd_event_io_handler_t io_callback
) {
1183 assert(client
->event
);
1185 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1186 client
->fd
, EPOLLIN
, io_callback
,
1191 r
= sd_event_source_set_priority(client
->receive_message
,
1192 client
->event_priority
);
1196 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1202 client_stop(client
, r
);
1207 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1212 assert(client
->event
);
1214 if (client
->start_delay
) {
1215 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1216 usec
+= client
->start_delay
;
1219 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1220 clock_boottime_or_monotonic(),
1222 client_timeout_resend
, client
,
1223 client
->event_priority
, "dhcp4-resend-timer", true);
1225 client_stop(client
, r
);
1231 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1232 client_initialize_io_events(client
, io_callback
);
1233 client_initialize_time_events(client
);
1238 static int client_start_delayed(sd_dhcp_client
*client
) {
1241 assert_return(client
, -EINVAL
);
1242 assert_return(client
->event
, -EINVAL
);
1243 assert_return(client
->ifindex
> 0, -EINVAL
);
1244 assert_return(client
->fd
< 0, -EBUSY
);
1245 assert_return(client
->xid
== 0, -EINVAL
);
1246 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1248 client
->xid
= random_u32();
1250 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1251 client
->xid
, client
->mac_addr
,
1252 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1254 client_stop(client
, r
);
1259 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1260 client
->start_time
= now(clock_boottime_or_monotonic());
1262 return client_initialize_events(client
, client_receive_message_raw
);
1265 static int client_start(sd_dhcp_client
*client
) {
1266 client
->start_delay
= 0;
1267 return client_start_delayed(client
);
1270 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1271 sd_dhcp_client
*client
= userdata
;
1272 DHCP_CLIENT_DONT_DESTROY(client
);
1274 log_dhcp_client(client
, "EXPIRED");
1276 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1278 /* lease was lost, start over if not freed or stopped in callback */
1279 if (client
->state
!= DHCP_STATE_STOPPED
) {
1280 client_initialize(client
);
1281 client_start(client
);
1287 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1288 sd_dhcp_client
*client
= userdata
;
1289 DHCP_CLIENT_DONT_DESTROY(client
);
1294 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1295 client
->fd
= asynchronous_close(client
->fd
);
1297 client
->state
= DHCP_STATE_REBINDING
;
1298 client
->attempt
= 0;
1300 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1301 client
->xid
, client
->mac_addr
,
1302 client
->mac_addr_len
, client
->arp_type
,
1305 client_stop(client
, r
);
1310 return client_initialize_events(client
, client_receive_message_raw
);
1313 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1314 sd_dhcp_client
*client
= userdata
;
1315 DHCP_CLIENT_DONT_DESTROY(client
);
1317 client
->state
= DHCP_STATE_RENEWING
;
1318 client
->attempt
= 0;
1320 return client_initialize_time_events(client
);
1323 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1324 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1327 r
= dhcp_lease_new(&lease
);
1331 if (client
->client_id_len
) {
1332 r
= dhcp_lease_set_client_id(lease
,
1333 (uint8_t *) &client
->client_id
,
1334 client
->client_id_len
);
1339 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1340 if (r
!= DHCP_OFFER
) {
1341 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1345 lease
->next_server
= offer
->siaddr
;
1346 lease
->address
= offer
->yiaddr
;
1348 if (lease
->address
== 0 ||
1349 lease
->server_address
== 0 ||
1350 lease
->lifetime
== 0) {
1351 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1355 if (!lease
->have_subnet_mask
) {
1356 r
= dhcp_lease_set_default_subnet_mask(lease
);
1358 log_dhcp_client(client
,
1359 "received lease lacks subnet mask, "
1360 "and a fallback one cannot be generated, ignoring");
1365 sd_dhcp_lease_unref(client
->lease
);
1366 client
->lease
= TAKE_PTR(lease
);
1368 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1371 log_dhcp_client(client
, "OFFER");
1376 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1379 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1380 if (r
!= DHCP_FORCERENEW
)
1383 log_dhcp_client(client
, "FORCERENEW");
1388 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1389 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1390 _cleanup_free_
char *error_message
= NULL
;
1393 r
= dhcp_lease_new(&lease
);
1397 if (client
->client_id_len
) {
1398 r
= dhcp_lease_set_client_id(lease
,
1399 (uint8_t *) &client
->client_id
,
1400 client
->client_id_len
);
1405 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1406 if (r
== DHCP_NAK
) {
1407 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1408 return -EADDRNOTAVAIL
;
1411 if (r
!= DHCP_ACK
) {
1412 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1416 lease
->next_server
= ack
->siaddr
;
1418 lease
->address
= ack
->yiaddr
;
1420 if (lease
->address
== INADDR_ANY
||
1421 lease
->server_address
== INADDR_ANY
||
1422 lease
->lifetime
== 0) {
1423 log_dhcp_client(client
, "received lease lacks address, server "
1424 "address or lease lifetime, ignoring");
1428 if (lease
->subnet_mask
== INADDR_ANY
) {
1429 r
= dhcp_lease_set_default_subnet_mask(lease
);
1431 log_dhcp_client(client
,
1432 "received lease lacks subnet mask, "
1433 "and a fallback one cannot be generated, ignoring");
1438 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1439 if (client
->lease
) {
1440 if (client
->lease
->address
!= lease
->address
||
1441 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1442 client
->lease
->router
!= lease
->router
) {
1443 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1445 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1447 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1450 client
->lease
= TAKE_PTR(lease
);
1452 log_dhcp_client(client
, "ACK");
1457 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1459 assert(client
->request_sent
);
1460 assert(lifetime
> 0);
1467 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1468 + (random_u32() & 0x1fffff);
1471 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1473 uint64_t lifetime_timeout
;
1474 uint64_t t2_timeout
;
1475 uint64_t t1_timeout
;
1476 char time_string
[FORMAT_TIMESPAN_MAX
];
1480 assert(client
->event
);
1481 assert(client
->lease
);
1482 assert(client
->lease
->lifetime
);
1484 /* don't set timers for infinite leases */
1485 if (client
->lease
->lifetime
== 0xffffffff) {
1486 (void) event_source_disable(client
->timeout_t1
);
1487 (void) event_source_disable(client
->timeout_t2
);
1488 (void) event_source_disable(client
->timeout_expire
);
1493 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1496 assert(client
->request_sent
<= time_now
);
1498 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1499 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1500 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1501 /* both T1 and T2 are given */
1502 if (client
->lease
->t1
< client
->lease
->t2
&&
1503 client
->lease
->t2
< client
->lease
->lifetime
) {
1504 /* they are both valid */
1505 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1506 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1509 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1510 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1511 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1512 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1514 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1515 /* only T2 is given, and it is valid */
1516 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1517 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1518 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1519 if (t2_timeout
<= t1_timeout
) {
1520 /* the computed T1 would be invalid, so discard T2 */
1521 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1522 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1524 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1525 /* only T1 is given, and it is valid */
1526 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1527 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1528 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1529 if (t2_timeout
<= t1_timeout
) {
1530 /* the computed T2 would be invalid, so discard T1 */
1531 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1532 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1535 /* fall back to the default timeouts */
1536 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1537 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1538 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1539 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1542 /* arm lifetime timeout */
1543 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1544 clock_boottime_or_monotonic(),
1545 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1546 client_timeout_expire
, client
,
1547 client
->event_priority
, "dhcp4-lifetime", true);
1551 log_dhcp_client(client
, "lease expires in %s",
1552 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1554 /* don't arm earlier timeouts if this has already expired */
1555 if (lifetime_timeout
<= time_now
)
1558 /* arm T2 timeout */
1559 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1560 clock_boottime_or_monotonic(),
1561 t2_timeout
, 10 * USEC_PER_MSEC
,
1562 client_timeout_t2
, client
,
1563 client
->event_priority
, "dhcp4-t2-timeout", true);
1567 log_dhcp_client(client
, "T2 expires in %s",
1568 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1570 /* don't arm earlier timeout if this has already expired */
1571 if (t2_timeout
<= time_now
)
1574 /* arm T1 timeout */
1575 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1576 clock_boottime_or_monotonic(),
1577 t1_timeout
, 10 * USEC_PER_MSEC
,
1578 client_timeout_t1
, client
,
1579 client
->event_priority
, "dhcp4-t1-timer", true);
1583 log_dhcp_client(client
, "T1 expires in %s",
1584 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1589 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1590 DHCP_CLIENT_DONT_DESTROY(client
);
1591 char time_string
[FORMAT_TIMESPAN_MAX
];
1592 int r
= 0, notify_event
= 0;
1595 assert(client
->event
);
1598 switch (client
->state
) {
1599 case DHCP_STATE_SELECTING
:
1601 r
= client_handle_offer(client
, message
, len
);
1604 client
->state
= DHCP_STATE_REQUESTING
;
1605 client
->attempt
= 0;
1607 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1608 clock_boottime_or_monotonic(),
1610 client_timeout_resend
, client
,
1611 client
->event_priority
, "dhcp4-resend-timer", true);
1614 } else if (r
== -ENOMSG
)
1615 /* invalid message, let's ignore it */
1620 case DHCP_STATE_REBOOTING
:
1621 case DHCP_STATE_REQUESTING
:
1622 case DHCP_STATE_RENEWING
:
1623 case DHCP_STATE_REBINDING
:
1625 r
= client_handle_ack(client
, message
, len
);
1627 client
->start_delay
= 0;
1628 (void) event_source_disable(client
->timeout_resend
);
1629 client
->receive_message
=
1630 sd_event_source_unref(client
->receive_message
);
1631 client
->fd
= asynchronous_close(client
->fd
);
1633 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1634 DHCP_STATE_REBOOTING
))
1635 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1636 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1639 client
->state
= DHCP_STATE_BOUND
;
1640 client
->attempt
= 0;
1642 client
->last_addr
= client
->lease
->address
;
1644 r
= client_set_lease_timeouts(client
);
1646 log_dhcp_client(client
, "could not set lease timeouts");
1650 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1652 log_dhcp_client(client
, "could not bind UDP socket");
1658 client_initialize_io_events(client
, client_receive_message_udp
);
1661 client_notify(client
, notify_event
);
1662 if (client
->state
== DHCP_STATE_STOPPED
)
1666 } else if (r
== -EADDRNOTAVAIL
) {
1667 /* got a NAK, let's restart the client */
1668 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1670 r
= client_initialize(client
);
1674 r
= client_start_delayed(client
);
1678 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1679 client
->start_delay
, USEC_PER_SEC
));
1681 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1682 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1685 } else if (r
== -ENOMSG
)
1686 /* invalid message, let's ignore it */
1691 case DHCP_STATE_BOUND
:
1692 r
= client_handle_forcerenew(client
, message
, len
);
1694 r
= client_timeout_t1(NULL
, 0, client
);
1697 } else if (r
== -ENOMSG
)
1698 /* invalid message, let's ignore it */
1703 case DHCP_STATE_INIT
:
1704 case DHCP_STATE_INIT_REBOOT
:
1708 case DHCP_STATE_STOPPED
:
1715 client_stop(client
, r
);
1720 static int client_receive_message_udp(
1726 sd_dhcp_client
*client
= userdata
;
1727 _cleanup_free_ DHCPMessage
*message
= NULL
;
1728 const uint8_t *expected_chaddr
= NULL
;
1729 uint8_t expected_hlen
= 0;
1730 ssize_t len
, buflen
;
1735 buflen
= next_datagram_size_fd(fd
);
1736 if (buflen
== -ENETDOWN
) {
1737 /* the link is down. Don't return an error or the I/O event
1738 source will be disconnected and we won't be able to receive
1739 packets again when the link comes back. */
1745 message
= malloc0(buflen
);
1749 len
= recv(fd
, message
, buflen
, 0);
1751 /* see comment above for why we shouldn't error out on ENETDOWN. */
1752 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1755 return log_dhcp_client_errno(client
, errno
,
1756 "Could not receive message from UDP socket: %m");
1758 if ((size_t) len
< sizeof(DHCPMessage
)) {
1759 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1763 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1764 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1768 if (message
->op
!= BOOTREPLY
) {
1769 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1773 if (message
->htype
!= client
->arp_type
) {
1774 log_dhcp_client(client
, "Packet type does not match client type");
1778 if (client
->arp_type
== ARPHRD_ETHER
) {
1779 expected_hlen
= ETH_ALEN
;
1780 expected_chaddr
= &client
->mac_addr
[0];
1783 if (message
->hlen
!= expected_hlen
) {
1784 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1788 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1789 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1793 if (client
->state
!= DHCP_STATE_BOUND
&&
1794 be32toh(message
->xid
) != client
->xid
) {
1795 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1796 so ignore the xid in this case */
1797 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1798 be32toh(message
->xid
), client
->xid
);
1802 return client_handle_message(client
, message
, len
);
1805 static int client_receive_message_raw(
1811 sd_dhcp_client
*client
= userdata
;
1812 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1813 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1814 struct iovec iov
= {};
1815 struct msghdr msg
= {
1818 .msg_control
= cmsgbuf
,
1819 .msg_controllen
= sizeof(cmsgbuf
),
1821 struct cmsghdr
*cmsg
;
1822 bool checksum
= true;
1823 ssize_t buflen
, len
;
1829 buflen
= next_datagram_size_fd(fd
);
1830 if (buflen
== -ENETDOWN
)
1835 packet
= malloc0(buflen
);
1839 iov
= IOVEC_MAKE(packet
, buflen
);
1841 len
= recvmsg(fd
, &msg
, 0);
1843 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1846 return log_dhcp_client_errno(client
, errno
,
1847 "Could not receive message from raw socket: %m");
1848 } else if ((size_t)len
< sizeof(DHCPPacket
))
1851 CMSG_FOREACH(cmsg
, &msg
)
1852 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1853 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1854 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1855 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1857 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1861 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1865 len
-= DHCP_IP_UDP_SIZE
;
1867 return client_handle_message(client
, &packet
->dhcp
, len
);
1870 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1873 assert_return(client
, -EINVAL
);
1875 r
= client_initialize(client
);
1879 /* RFC7844 section 3.3:
1880 SHOULD perform a complete four-way handshake, starting with a
1881 DHCPDISCOVER, to obtain a new address lease. If the client can
1882 ascertain that this is exactly the same network to which it was
1883 previously connected, and if the link-layer address did not change,
1884 the client MAY issue a DHCPREQUEST to try to reclaim the current
1886 if (client
->last_addr
&& !client
->anonymize
)
1887 client
->state
= DHCP_STATE_INIT_REBOOT
;
1889 r
= client_start(client
);
1891 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1896 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1897 assert_return(client
, -EINVAL
);
1899 client_send_release(client
);
1904 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1905 DHCP_CLIENT_DONT_DESTROY(client
);
1907 assert_return(client
, -EINVAL
);
1909 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1910 client
->state
= DHCP_STATE_STOPPED
;
1915 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1918 assert_return(client
, -EINVAL
);
1919 assert_return(!client
->event
, -EBUSY
);
1922 client
->event
= sd_event_ref(event
);
1924 r
= sd_event_default(&client
->event
);
1929 client
->event_priority
= priority
;
1934 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1935 assert_return(client
, -EINVAL
);
1937 client
->event
= sd_event_unref(client
->event
);
1942 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1943 assert_return(client
, NULL
);
1945 return client
->event
;
1948 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1951 log_dhcp_client(client
, "FREE");
1953 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1954 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1955 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1956 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1958 client_initialize(client
);
1960 sd_dhcp_client_detach_event(client
);
1962 sd_dhcp_lease_unref(client
->lease
);
1964 free(client
->req_opts
);
1965 free(client
->hostname
);
1966 free(client
->vendor_class_identifier
);
1967 client
->user_class
= strv_free(client
->user_class
);
1968 return mfree(client
);
1971 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1973 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1974 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1976 assert_return(ret
, -EINVAL
);
1978 client
= new(sd_dhcp_client
, 1);
1982 *client
= (sd_dhcp_client
) {
1984 .state
= DHCP_STATE_INIT
,
1987 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1988 .port
= DHCP_PORT_CLIENT
,
1989 .anonymize
= !!anonymize
,
1990 .max_attempts
= (uint64_t) -1,
1992 /* NOTE: this could be moved to a function. */
1994 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1995 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1997 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1998 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2000 if (!client
->req_opts
)
2003 *ret
= TAKE_PTR(client
);