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
));
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) {
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
) {
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_request(sd_dhcp_client
*client
) {
865 _cleanup_free_ DHCPPacket
*request
= NULL
;
866 size_t optoffset
, optlen
;
871 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
875 switch (client
->state
) {
876 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
877 SELECTING should be REQUESTING)
880 case DHCP_STATE_REQUESTING
:
881 /* Client inserts the address of the selected server in ’server
882 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
883 filled in with the yiaddr value from the chosen DHCPOFFER.
886 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
887 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
888 4, &client
->lease
->server_address
);
892 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
893 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
894 4, &client
->lease
->address
);
900 case DHCP_STATE_INIT_REBOOT
:
901 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
902 option MUST be filled in with client’s notion of its previously
903 assigned address. ’ciaddr’ MUST be zero.
905 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
906 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
907 4, &client
->last_addr
);
912 case DHCP_STATE_RENEWING
:
913 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
914 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
918 case DHCP_STATE_REBINDING
:
919 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
920 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
923 This message MUST be broadcast to the 0xffffffff IP broadcast address.
925 request
->dhcp
.ciaddr
= client
->lease
->address
;
929 case DHCP_STATE_INIT
:
930 case DHCP_STATE_SELECTING
:
931 case DHCP_STATE_REBOOTING
:
932 case DHCP_STATE_BOUND
:
933 case DHCP_STATE_STOPPED
:
937 if (client
->hostname
) {
938 if (dns_name_is_single_label(client
->hostname
))
939 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
940 SD_DHCP_OPTION_HOST_NAME
,
941 strlen(client
->hostname
), client
->hostname
);
943 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
949 if (client
->vendor_class_identifier
) {
950 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
951 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
952 strlen(client
->vendor_class_identifier
),
953 client
->vendor_class_identifier
);
958 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
959 SD_DHCP_OPTION_END
, 0, NULL
);
963 if (client
->state
== DHCP_STATE_RENEWING
) {
964 r
= dhcp_network_send_udp_socket(client
->fd
,
965 client
->lease
->server_address
,
968 sizeof(DHCPMessage
) + optoffset
);
970 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
975 switch (client
->state
) {
977 case DHCP_STATE_REQUESTING
:
978 log_dhcp_client(client
, "REQUEST (requesting)");
981 case DHCP_STATE_INIT_REBOOT
:
982 log_dhcp_client(client
, "REQUEST (init-reboot)");
985 case DHCP_STATE_RENEWING
:
986 log_dhcp_client(client
, "REQUEST (renewing)");
989 case DHCP_STATE_REBINDING
:
990 log_dhcp_client(client
, "REQUEST (rebinding)");
994 log_dhcp_client(client
, "REQUEST (invalid)");
1001 static int client_start(sd_dhcp_client
*client
);
1003 static int client_timeout_resend(
1008 sd_dhcp_client
*client
= userdata
;
1009 DHCP_CLIENT_DONT_DESTROY(client
);
1010 usec_t next_timeout
= 0;
1017 assert(client
->event
);
1019 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1023 switch (client
->state
) {
1025 case DHCP_STATE_RENEWING
:
1027 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1031 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1035 case DHCP_STATE_REBINDING
:
1037 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1041 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1044 case DHCP_STATE_REBOOTING
:
1045 /* start over as we did not receive a timely ack or nak */
1046 r
= client_initialize(client
);
1050 r
= client_start(client
);
1054 log_dhcp_client(client
, "REBOOTED");
1058 case DHCP_STATE_INIT
:
1059 case DHCP_STATE_INIT_REBOOT
:
1060 case DHCP_STATE_SELECTING
:
1061 case DHCP_STATE_REQUESTING
:
1062 case DHCP_STATE_BOUND
:
1064 if (client
->attempt
< client
->max_attempts
)
1069 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1073 case DHCP_STATE_STOPPED
:
1078 next_timeout
+= (random_u32() & 0x1fffff);
1080 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1081 clock_boottime_or_monotonic(),
1082 next_timeout
, 10 * USEC_PER_MSEC
,
1083 client_timeout_resend
, client
,
1084 client
->event_priority
, "dhcp4-resend-timer", true);
1088 switch (client
->state
) {
1089 case DHCP_STATE_INIT
:
1090 r
= client_send_discover(client
);
1092 client
->state
= DHCP_STATE_SELECTING
;
1093 client
->attempt
= 0;
1094 } else if (client
->attempt
>= client
->max_attempts
)
1099 case DHCP_STATE_SELECTING
:
1100 r
= client_send_discover(client
);
1101 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1106 case DHCP_STATE_INIT_REBOOT
:
1107 case DHCP_STATE_REQUESTING
:
1108 case DHCP_STATE_RENEWING
:
1109 case DHCP_STATE_REBINDING
:
1110 r
= client_send_request(client
);
1111 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1114 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1115 client
->state
= DHCP_STATE_REBOOTING
;
1117 client
->request_sent
= time_now
;
1121 case DHCP_STATE_REBOOTING
:
1122 case DHCP_STATE_BOUND
:
1126 case DHCP_STATE_STOPPED
:
1134 client_stop(client
, r
);
1136 /* Errors were dealt with when stopping the client, don't spill
1137 errors into the event loop handler */
1141 static int client_initialize_io_events(
1142 sd_dhcp_client
*client
,
1143 sd_event_io_handler_t io_callback
) {
1148 assert(client
->event
);
1150 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1151 client
->fd
, EPOLLIN
, io_callback
,
1156 r
= sd_event_source_set_priority(client
->receive_message
,
1157 client
->event_priority
);
1161 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1167 client_stop(client
, r
);
1172 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1177 assert(client
->event
);
1179 if (client
->start_delay
) {
1180 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1181 usec
+= client
->start_delay
;
1184 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1185 clock_boottime_or_monotonic(),
1187 client_timeout_resend
, client
,
1188 client
->event_priority
, "dhcp4-resend-timer", true);
1190 client_stop(client
, r
);
1196 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1197 client_initialize_io_events(client
, io_callback
);
1198 client_initialize_time_events(client
);
1203 static int client_start_delayed(sd_dhcp_client
*client
) {
1206 assert_return(client
, -EINVAL
);
1207 assert_return(client
->event
, -EINVAL
);
1208 assert_return(client
->ifindex
> 0, -EINVAL
);
1209 assert_return(client
->fd
< 0, -EBUSY
);
1210 assert_return(client
->xid
== 0, -EINVAL
);
1211 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1213 client
->xid
= random_u32();
1215 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1216 client
->xid
, client
->mac_addr
,
1217 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1219 client_stop(client
, r
);
1224 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1225 client
->start_time
= now(clock_boottime_or_monotonic());
1227 return client_initialize_events(client
, client_receive_message_raw
);
1230 static int client_start(sd_dhcp_client
*client
) {
1231 client
->start_delay
= 0;
1232 return client_start_delayed(client
);
1235 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1236 sd_dhcp_client
*client
= userdata
;
1237 DHCP_CLIENT_DONT_DESTROY(client
);
1239 log_dhcp_client(client
, "EXPIRED");
1241 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1243 /* lease was lost, start over if not freed or stopped in callback */
1244 if (client
->state
!= DHCP_STATE_STOPPED
) {
1245 client_initialize(client
);
1246 client_start(client
);
1252 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1253 sd_dhcp_client
*client
= userdata
;
1254 DHCP_CLIENT_DONT_DESTROY(client
);
1259 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1260 client
->fd
= asynchronous_close(client
->fd
);
1262 client
->state
= DHCP_STATE_REBINDING
;
1263 client
->attempt
= 0;
1265 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1266 client
->xid
, client
->mac_addr
,
1267 client
->mac_addr_len
, client
->arp_type
,
1270 client_stop(client
, r
);
1275 return client_initialize_events(client
, client_receive_message_raw
);
1278 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1279 sd_dhcp_client
*client
= userdata
;
1280 DHCP_CLIENT_DONT_DESTROY(client
);
1282 client
->state
= DHCP_STATE_RENEWING
;
1283 client
->attempt
= 0;
1285 return client_initialize_time_events(client
);
1288 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1289 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1292 r
= dhcp_lease_new(&lease
);
1296 if (client
->client_id_len
) {
1297 r
= dhcp_lease_set_client_id(lease
,
1298 (uint8_t *) &client
->client_id
,
1299 client
->client_id_len
);
1304 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1305 if (r
!= DHCP_OFFER
) {
1306 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1310 lease
->next_server
= offer
->siaddr
;
1311 lease
->address
= offer
->yiaddr
;
1313 if (lease
->address
== 0 ||
1314 lease
->server_address
== 0 ||
1315 lease
->lifetime
== 0) {
1316 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1320 if (!lease
->have_subnet_mask
) {
1321 r
= dhcp_lease_set_default_subnet_mask(lease
);
1323 log_dhcp_client(client
,
1324 "received lease lacks subnet mask, "
1325 "and a fallback one cannot be generated, ignoring");
1330 sd_dhcp_lease_unref(client
->lease
);
1331 client
->lease
= TAKE_PTR(lease
);
1333 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1336 log_dhcp_client(client
, "OFFER");
1341 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1344 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1345 if (r
!= DHCP_FORCERENEW
)
1348 log_dhcp_client(client
, "FORCERENEW");
1353 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1354 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1355 _cleanup_free_
char *error_message
= NULL
;
1358 r
= dhcp_lease_new(&lease
);
1362 if (client
->client_id_len
) {
1363 r
= dhcp_lease_set_client_id(lease
,
1364 (uint8_t *) &client
->client_id
,
1365 client
->client_id_len
);
1370 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1371 if (r
== DHCP_NAK
) {
1372 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1373 return -EADDRNOTAVAIL
;
1376 if (r
!= DHCP_ACK
) {
1377 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1381 lease
->next_server
= ack
->siaddr
;
1383 lease
->address
= ack
->yiaddr
;
1385 if (lease
->address
== INADDR_ANY
||
1386 lease
->server_address
== INADDR_ANY
||
1387 lease
->lifetime
== 0) {
1388 log_dhcp_client(client
, "received lease lacks address, server "
1389 "address or lease lifetime, ignoring");
1393 if (lease
->subnet_mask
== INADDR_ANY
) {
1394 r
= dhcp_lease_set_default_subnet_mask(lease
);
1396 log_dhcp_client(client
,
1397 "received lease lacks subnet mask, "
1398 "and a fallback one cannot be generated, ignoring");
1403 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1404 if (client
->lease
) {
1405 if (client
->lease
->address
!= lease
->address
||
1406 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1407 client
->lease
->router
!= lease
->router
) {
1408 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1410 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1412 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1415 client
->lease
= TAKE_PTR(lease
);
1417 log_dhcp_client(client
, "ACK");
1422 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1424 assert(client
->request_sent
);
1425 assert(lifetime
> 0);
1432 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1433 + (random_u32() & 0x1fffff);
1436 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1438 uint64_t lifetime_timeout
;
1439 uint64_t t2_timeout
;
1440 uint64_t t1_timeout
;
1441 char time_string
[FORMAT_TIMESPAN_MAX
];
1445 assert(client
->event
);
1446 assert(client
->lease
);
1447 assert(client
->lease
->lifetime
);
1449 /* don't set timers for infinite leases */
1450 if (client
->lease
->lifetime
== 0xffffffff) {
1451 (void) event_source_disable(client
->timeout_t1
);
1452 (void) event_source_disable(client
->timeout_t2
);
1453 (void) event_source_disable(client
->timeout_expire
);
1458 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1461 assert(client
->request_sent
<= time_now
);
1463 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1464 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1465 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1466 /* both T1 and T2 are given */
1467 if (client
->lease
->t1
< client
->lease
->t2
&&
1468 client
->lease
->t2
< client
->lease
->lifetime
) {
1469 /* they are both valid */
1470 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1471 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1474 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1475 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1476 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1477 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1479 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1480 /* only T2 is given, and it is valid */
1481 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1482 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1483 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1484 if (t2_timeout
<= t1_timeout
) {
1485 /* the computed T1 would be invalid, so discard T2 */
1486 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1487 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1489 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1490 /* only T1 is given, and it is valid */
1491 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1492 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1493 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1494 if (t2_timeout
<= t1_timeout
) {
1495 /* the computed T2 would be invalid, so discard T1 */
1496 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1497 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1500 /* fall back to the default timeouts */
1501 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1502 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1503 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1504 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1507 /* arm lifetime timeout */
1508 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1509 clock_boottime_or_monotonic(),
1510 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1511 client_timeout_expire
, client
,
1512 client
->event_priority
, "dhcp4-lifetime", true);
1516 log_dhcp_client(client
, "lease expires in %s",
1517 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1519 /* don't arm earlier timeouts if this has already expired */
1520 if (lifetime_timeout
<= time_now
)
1523 /* arm T2 timeout */
1524 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1525 clock_boottime_or_monotonic(),
1526 t2_timeout
, 10 * USEC_PER_MSEC
,
1527 client_timeout_t2
, client
,
1528 client
->event_priority
, "dhcp4-t2-timeout", true);
1532 log_dhcp_client(client
, "T2 expires in %s",
1533 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1535 /* don't arm earlier timeout if this has already expired */
1536 if (t2_timeout
<= time_now
)
1539 /* arm T1 timeout */
1540 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1541 clock_boottime_or_monotonic(),
1542 t1_timeout
, 10 * USEC_PER_MSEC
,
1543 client_timeout_t1
, client
,
1544 client
->event_priority
, "dhcp4-t1-timer", true);
1548 log_dhcp_client(client
, "T1 expires in %s",
1549 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1554 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1555 DHCP_CLIENT_DONT_DESTROY(client
);
1556 char time_string
[FORMAT_TIMESPAN_MAX
];
1557 int r
= 0, notify_event
= 0;
1560 assert(client
->event
);
1563 switch (client
->state
) {
1564 case DHCP_STATE_SELECTING
:
1566 r
= client_handle_offer(client
, message
, len
);
1569 client
->state
= DHCP_STATE_REQUESTING
;
1570 client
->attempt
= 0;
1572 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1573 clock_boottime_or_monotonic(),
1575 client_timeout_resend
, client
,
1576 client
->event_priority
, "dhcp4-resend-timer", true);
1579 } else if (r
== -ENOMSG
)
1580 /* invalid message, let's ignore it */
1585 case DHCP_STATE_REBOOTING
:
1586 case DHCP_STATE_REQUESTING
:
1587 case DHCP_STATE_RENEWING
:
1588 case DHCP_STATE_REBINDING
:
1590 r
= client_handle_ack(client
, message
, len
);
1592 client
->start_delay
= 0;
1593 (void) event_source_disable(client
->timeout_resend
);
1594 client
->receive_message
=
1595 sd_event_source_unref(client
->receive_message
);
1596 client
->fd
= asynchronous_close(client
->fd
);
1598 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1599 DHCP_STATE_REBOOTING
))
1600 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1601 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1604 client
->state
= DHCP_STATE_BOUND
;
1605 client
->attempt
= 0;
1607 client
->last_addr
= client
->lease
->address
;
1609 r
= client_set_lease_timeouts(client
);
1611 log_dhcp_client(client
, "could not set lease timeouts");
1615 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1617 log_dhcp_client(client
, "could not bind UDP socket");
1623 client_initialize_io_events(client
, client_receive_message_udp
);
1626 client_notify(client
, notify_event
);
1627 if (client
->state
== DHCP_STATE_STOPPED
)
1631 } else if (r
== -EADDRNOTAVAIL
) {
1632 /* got a NAK, let's restart the client */
1633 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1635 r
= client_initialize(client
);
1639 r
= client_start_delayed(client
);
1643 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1644 client
->start_delay
, USEC_PER_SEC
));
1646 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1647 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1650 } else if (r
== -ENOMSG
)
1651 /* invalid message, let's ignore it */
1656 case DHCP_STATE_BOUND
:
1657 r
= client_handle_forcerenew(client
, message
, len
);
1659 r
= client_timeout_t1(NULL
, 0, client
);
1662 } else if (r
== -ENOMSG
)
1663 /* invalid message, let's ignore it */
1668 case DHCP_STATE_INIT
:
1669 case DHCP_STATE_INIT_REBOOT
:
1673 case DHCP_STATE_STOPPED
:
1680 client_stop(client
, r
);
1685 static int client_receive_message_udp(
1691 sd_dhcp_client
*client
= userdata
;
1692 _cleanup_free_ DHCPMessage
*message
= NULL
;
1693 const uint8_t *expected_chaddr
= NULL
;
1694 uint8_t expected_hlen
= 0;
1695 ssize_t len
, buflen
;
1700 buflen
= next_datagram_size_fd(fd
);
1701 if (buflen
== -ENETDOWN
) {
1702 /* the link is down. Don't return an error or the I/O event
1703 source will be disconnected and we won't be able to receive
1704 packets again when the link comes back. */
1710 message
= malloc0(buflen
);
1714 len
= recv(fd
, message
, buflen
, 0);
1716 /* see comment above for why we shouldn't error out on ENETDOWN. */
1717 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1720 return log_dhcp_client_errno(client
, errno
,
1721 "Could not receive message from UDP socket: %m");
1723 if ((size_t) len
< sizeof(DHCPMessage
)) {
1724 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1728 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1729 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1733 if (message
->op
!= BOOTREPLY
) {
1734 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1738 if (message
->htype
!= client
->arp_type
) {
1739 log_dhcp_client(client
, "Packet type does not match client type");
1743 if (client
->arp_type
== ARPHRD_ETHER
) {
1744 expected_hlen
= ETH_ALEN
;
1745 expected_chaddr
= &client
->mac_addr
[0];
1748 if (message
->hlen
!= expected_hlen
) {
1749 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1753 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1754 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1758 if (client
->state
!= DHCP_STATE_BOUND
&&
1759 be32toh(message
->xid
) != client
->xid
) {
1760 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1761 so ignore the xid in this case */
1762 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1763 be32toh(message
->xid
), client
->xid
);
1767 return client_handle_message(client
, message
, len
);
1770 static int client_receive_message_raw(
1776 sd_dhcp_client
*client
= userdata
;
1777 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1778 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1779 struct iovec iov
= {};
1780 struct msghdr msg
= {
1783 .msg_control
= cmsgbuf
,
1784 .msg_controllen
= sizeof(cmsgbuf
),
1786 struct cmsghdr
*cmsg
;
1787 bool checksum
= true;
1788 ssize_t buflen
, len
;
1794 buflen
= next_datagram_size_fd(fd
);
1795 if (buflen
== -ENETDOWN
)
1800 packet
= malloc0(buflen
);
1804 iov
= IOVEC_MAKE(packet
, buflen
);
1806 len
= recvmsg(fd
, &msg
, 0);
1808 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1811 return log_dhcp_client_errno(client
, errno
,
1812 "Could not receive message from raw socket: %m");
1813 } else if ((size_t)len
< sizeof(DHCPPacket
))
1816 CMSG_FOREACH(cmsg
, &msg
)
1817 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1818 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1819 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1820 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1822 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1826 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1830 len
-= DHCP_IP_UDP_SIZE
;
1832 return client_handle_message(client
, &packet
->dhcp
, len
);
1835 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1838 assert_return(client
, -EINVAL
);
1840 r
= client_initialize(client
);
1844 /* RFC7844 section 3.3:
1845 SHOULD perform a complete four-way handshake, starting with a
1846 DHCPDISCOVER, to obtain a new address lease. If the client can
1847 ascertain that this is exactly the same network to which it was
1848 previously connected, and if the link-layer address did not change,
1849 the client MAY issue a DHCPREQUEST to try to reclaim the current
1851 if (client
->last_addr
&& !client
->anonymize
)
1852 client
->state
= DHCP_STATE_INIT_REBOOT
;
1854 r
= client_start(client
);
1856 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1861 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1862 DHCP_CLIENT_DONT_DESTROY(client
);
1864 assert_return(client
, -EINVAL
);
1866 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1867 client
->state
= DHCP_STATE_STOPPED
;
1872 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1875 assert_return(client
, -EINVAL
);
1876 assert_return(!client
->event
, -EBUSY
);
1879 client
->event
= sd_event_ref(event
);
1881 r
= sd_event_default(&client
->event
);
1886 client
->event_priority
= priority
;
1891 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1892 assert_return(client
, -EINVAL
);
1894 client
->event
= sd_event_unref(client
->event
);
1899 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1900 assert_return(client
, NULL
);
1902 return client
->event
;
1905 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1908 log_dhcp_client(client
, "FREE");
1910 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1911 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1912 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1913 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1915 client_initialize(client
);
1917 sd_dhcp_client_detach_event(client
);
1919 sd_dhcp_lease_unref(client
->lease
);
1921 free(client
->req_opts
);
1922 free(client
->hostname
);
1923 free(client
->vendor_class_identifier
);
1924 client
->user_class
= strv_free(client
->user_class
);
1925 return mfree(client
);
1928 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1930 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1931 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1933 assert_return(ret
, -EINVAL
);
1935 client
= new(sd_dhcp_client
, 1);
1939 *client
= (sd_dhcp_client
) {
1941 .state
= DHCP_STATE_INIT
,
1944 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1945 .port
= DHCP_PORT_CLIENT
,
1946 .anonymize
= !!anonymize
,
1947 .max_attempts
= (uint64_t) -1,
1949 /* NOTE: this could be moved to a function. */
1951 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1952 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1954 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1955 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1957 if (!client
->req_opts
)
1960 *ret
= TAKE_PTR(client
);