2 This file is part of systemd.
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <net/ethernet.h>
22 #include <net/if_arp.h>
26 #include <sys/ioctl.h>
27 #include <linux/if_infiniband.h>
29 #include "sd-dhcp-client.h"
31 #include "alloc-util.h"
33 #include "dhcp-identifier.h"
34 #include "dhcp-internal.h"
35 #include "dhcp-lease-internal.h"
36 #include "dhcp-protocol.h"
37 #include "dns-domain.h"
38 #include "hostname-util.h"
39 #include "random-util.h"
40 #include "string-util.h"
43 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
44 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
46 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
47 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
49 struct sd_dhcp_client
{
55 sd_event_source
*timeout_resend
;
59 union sockaddr_union link
;
60 sd_event_source
*receive_message
;
61 bool request_broadcast
;
63 size_t req_opts_allocated
;
67 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
74 /* 0: Generic (non-LL) (RFC 2132) */
75 uint8_t data
[MAX_CLIENT_ID_LEN
];
78 /* 1: Ethernet Link-Layer (RFC 2132) */
79 uint8_t haddr
[ETH_ALEN
];
82 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
86 /* 255: Node-specific (RFC 4361) */
91 uint8_t data
[MAX_CLIENT_ID_LEN
];
97 char *vendor_class_identifier
;
101 unsigned int attempt
;
103 sd_event_source
*timeout_t1
;
104 sd_event_source
*timeout_t2
;
105 sd_event_source
*timeout_expire
;
106 sd_dhcp_client_callback_t callback
;
108 sd_dhcp_lease
*lease
;
112 static const uint8_t default_req_opts
[] = {
113 SD_DHCP_OPTION_SUBNET_MASK
,
114 SD_DHCP_OPTION_ROUTER
,
115 SD_DHCP_OPTION_HOST_NAME
,
116 SD_DHCP_OPTION_DOMAIN_NAME
,
117 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
120 /* RFC7844 section 3:
121 MAY contain the Parameter Request List option.
123 The client intending to protect its privacy SHOULD only request a
124 minimal number of options in the PRL and SHOULD also randomly shuffle
125 the ordering of option codes in the PRL. If this random ordering
126 cannot be implemented, the client MAY order the option codes in the
127 PRL by option code number (lowest to highest).
129 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
130 static const uint8_t default_req_opts_anonymize
[] = {
131 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
132 SD_DHCP_OPTION_ROUTER
, /* 3 */
133 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
134 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
135 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
136 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
137 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
138 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
139 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
140 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
141 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
142 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
143 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
146 static int client_receive_message_raw(
151 static int client_receive_message_udp(
156 static void client_stop(sd_dhcp_client
*client
, int error
);
158 int sd_dhcp_client_set_callback(
159 sd_dhcp_client
*client
,
160 sd_dhcp_client_callback_t cb
,
163 assert_return(client
, -EINVAL
);
165 client
->callback
= cb
;
166 client
->userdata
= userdata
;
171 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
172 assert_return(client
, -EINVAL
);
174 client
->request_broadcast
= !!broadcast
;
179 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
182 assert_return(client
, -EINVAL
);
183 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
187 case SD_DHCP_OPTION_PAD
:
188 case SD_DHCP_OPTION_OVERLOAD
:
189 case SD_DHCP_OPTION_MESSAGE_TYPE
:
190 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
191 case SD_DHCP_OPTION_END
:
198 for (i
= 0; i
< client
->req_opts_size
; i
++)
199 if (client
->req_opts
[i
] == option
)
202 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
203 client
->req_opts_size
+ 1))
206 client
->req_opts
[client
->req_opts_size
++] = option
;
211 int sd_dhcp_client_set_request_address(
212 sd_dhcp_client
*client
,
213 const struct in_addr
*last_addr
) {
215 assert_return(client
, -EINVAL
);
216 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
219 client
->last_addr
= last_addr
->s_addr
;
221 client
->last_addr
= INADDR_ANY
;
226 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
228 assert_return(client
, -EINVAL
);
229 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
230 assert_return(ifindex
> 0, -EINVAL
);
232 client
->ifindex
= ifindex
;
236 int sd_dhcp_client_set_mac(
237 sd_dhcp_client
*client
,
242 DHCP_CLIENT_DONT_DESTROY(client
);
243 bool need_restart
= false;
245 assert_return(client
, -EINVAL
);
246 assert_return(addr
, -EINVAL
);
247 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
248 assert_return(arp_type
> 0, -EINVAL
);
250 if (arp_type
== ARPHRD_ETHER
)
251 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
252 else if (arp_type
== ARPHRD_INFINIBAND
)
253 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
257 if (client
->mac_addr_len
== addr_len
&&
258 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
261 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
262 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
264 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
267 memcpy(&client
->mac_addr
, addr
, addr_len
);
268 client
->mac_addr_len
= addr_len
;
269 client
->arp_type
= arp_type
;
271 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
272 sd_dhcp_client_start(client
);
277 int sd_dhcp_client_get_client_id(
278 sd_dhcp_client
*client
,
280 const uint8_t **data
,
283 assert_return(client
, -EINVAL
);
284 assert_return(type
, -EINVAL
);
285 assert_return(data
, -EINVAL
);
286 assert_return(data_len
, -EINVAL
);
291 if (client
->client_id_len
) {
292 *type
= client
->client_id
.type
;
293 *data
= client
->client_id
.raw
.data
;
294 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
300 int sd_dhcp_client_set_client_id(
301 sd_dhcp_client
*client
,
306 DHCP_CLIENT_DONT_DESTROY(client
);
307 bool need_restart
= false;
309 assert_return(client
, -EINVAL
);
310 assert_return(data
, -EINVAL
);
311 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
316 if (data_len
!= ETH_ALEN
)
320 case ARPHRD_INFINIBAND
:
321 if (data_len
!= INFINIBAND_ALEN
)
329 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
330 client
->client_id
.type
== type
&&
331 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
334 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
335 log_dhcp_client(client
, "Changing client ID on running DHCP "
336 "client, restarting");
338 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
341 client
->client_id
.type
= type
;
342 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
343 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
345 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
346 sd_dhcp_client_start(client
);
352 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
353 * without further modification. Otherwise, if duid_type is supported, DUID
354 * is set based on that type. Otherwise, an error is returned.
356 int sd_dhcp_client_set_iaid_duid(
357 sd_dhcp_client
*client
,
363 DHCP_CLIENT_DONT_DESTROY(client
);
367 assert_return(client
, -EINVAL
);
368 assert_return(duid_len
== 0 || duid
!= NULL
, -EINVAL
);
371 r
= dhcp_validate_duid_len(duid_type
, duid_len
);
376 zero(client
->client_id
);
377 client
->client_id
.type
= 255;
379 /* If IAID is not configured, generate it. */
381 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
382 client
->mac_addr_len
,
383 &client
->client_id
.ns
.iaid
);
387 client
->client_id
.ns
.iaid
= htobe32(iaid
);
390 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
391 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
392 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
393 } else if (duid_type
== DUID_TYPE_EN
) {
394 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
400 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
401 sizeof(client
->client_id
.ns
.iaid
);
403 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
404 log_dhcp_client(client
, "Configured IAID+DUID, restarting.");
405 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
406 sd_dhcp_client_start(client
);
412 int sd_dhcp_client_set_hostname(
413 sd_dhcp_client
*client
,
414 const char *hostname
) {
416 assert_return(client
, -EINVAL
);
418 /* Refuse hostnames that neither qualify as DNS nor as Linux hosntames */
420 !(hostname_is_valid(hostname
, false) || dns_name_is_valid(hostname
) > 0))
423 return free_and_strdup(&client
->hostname
, hostname
);
426 int sd_dhcp_client_set_vendor_class_identifier(
427 sd_dhcp_client
*client
,
430 assert_return(client
, -EINVAL
);
432 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
435 int sd_dhcp_client_set_client_port(
436 sd_dhcp_client
*client
,
439 assert_return(client
, -EINVAL
);
446 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
447 assert_return(client
, -EINVAL
);
448 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
455 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
456 assert_return(client
, -EINVAL
);
458 if (!IN_SET(client
->state
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
459 return -EADDRNOTAVAIL
;
462 *ret
= client
->lease
;
467 static void client_notify(sd_dhcp_client
*client
, int event
) {
470 if (client
->callback
)
471 client
->callback(client
, event
, client
->userdata
);
474 static int client_initialize(sd_dhcp_client
*client
) {
475 assert_return(client
, -EINVAL
);
477 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
479 client
->fd
= asynchronous_close(client
->fd
);
481 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
483 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
484 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
485 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
489 client
->state
= DHCP_STATE_INIT
;
492 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
497 static void client_stop(sd_dhcp_client
*client
, int error
) {
501 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
502 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
503 log_dhcp_client(client
, "STOPPED");
505 log_dhcp_client(client
, "STOPPED: Unknown event");
507 client_notify(client
, error
);
509 client_initialize(client
);
512 static int client_message_init(
513 sd_dhcp_client
*client
,
517 size_t *_optoffset
) {
519 _cleanup_free_ DHCPPacket
*packet
= NULL
;
520 size_t optlen
, optoffset
, size
;
527 assert(client
->start_time
);
531 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
533 optlen
= DHCP_MIN_OPTIONS_SIZE
;
534 size
= sizeof(DHCPPacket
) + optlen
;
536 packet
= malloc0(size
);
540 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
541 client
->arp_type
, optlen
, &optoffset
);
545 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
546 refuse to issue an DHCP lease if 'secs' is set to zero */
547 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
550 assert(time_now
>= client
->start_time
);
552 /* seconds between sending first and last DISCOVER
553 * must always be strictly positive to deal with broken servers */
554 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
555 packet
->dhcp
.secs
= htobe16(secs
);
557 /* RFC2132 section 4.1
558 A client that cannot receive unicast IP datagrams until its protocol
559 software has been configured with an IP address SHOULD set the
560 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
561 DHCPREQUEST messages that client sends. The BROADCAST bit will
562 provide a hint to the DHCP server and BOOTP relay agent to broadcast
563 any messages to the client on the client's subnet.
565 Note: some interfaces needs this to be enabled, but some networks
566 needs this to be disabled as broadcasts are filteretd, so this
567 needs to be configurable */
568 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
569 packet
->dhcp
.flags
= htobe16(0x8000);
571 /* RFC2132 section 4.1.1:
572 The client MUST include its hardware address in the ’chaddr’ field, if
573 necessary for delivery of DHCP reply messages. Non-Ethernet
574 interfaces will leave 'chaddr' empty and use the client identifier
575 instead (eg, RFC 4390 section 2.1).
577 if (client
->arp_type
== ARPHRD_ETHER
)
578 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
580 /* If no client identifier exists, construct an RFC 4361-compliant one */
581 if (client
->client_id_len
== 0) {
584 client
->client_id
.type
= 255;
586 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
590 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
594 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
597 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
598 Identifier option is not set */
599 if (client
->client_id_len
) {
600 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
601 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
602 client
->client_id_len
,
608 /* RFC2131 section 3.5:
609 in its initial DHCPDISCOVER or DHCPREQUEST message, a
610 client may provide the server with a list of specific
611 parameters the client is interested in. If the client
612 includes a list of parameters in a DHCPDISCOVER message,
613 it MUST include that list in any subsequent DHCPREQUEST
617 /* RFC7844 section 3:
618 MAY contain the Parameter Request List option. */
619 /* NOTE: in case that there would be an option to do not send
620 * any PRL at all, the size should be checked before sending */
621 if (client
->req_opts_size
> 0) {
622 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
623 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
624 client
->req_opts_size
, client
->req_opts
);
629 /* RFC2131 section 3.5:
630 The client SHOULD include the ’maximum DHCP message size’ option to
631 let the server know how large the server may make its DHCP messages.
633 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
634 than the defined default size unless the Maximum Messge Size option
637 RFC3442 "Requirements to Avoid Sizing Constraints":
638 Because a full routing table can be quite large, the standard 576
639 octet maximum size for a DHCP message may be too short to contain
640 some legitimate Classless Static Route options. Because of this,
641 clients implementing the Classless Static Route option SHOULD send a
642 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
643 stack is capable of receiving larger IP datagrams. In this case, the
644 client SHOULD set the value of this option to at least the MTU of the
645 interface that the client is configuring. The client MAY set the
646 value of this option higher, up to the size of the largest UDP packet
647 it is prepared to accept. (Note that the value specified in the
648 Maximum DHCP Message Size option is the total maximum packet size,
649 including IP and UDP headers.)
651 /* RFC7844 section 3:
652 SHOULD NOT contain any other option. */
653 if (!client
->anonymize
) {
654 max_size
= htobe16(size
);
655 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
656 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
663 *_optoffset
= optoffset
;
670 static int client_append_fqdn_option(
671 DHCPMessage
*message
,
676 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
679 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
680 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
681 buffer
[1] = 0; /* RCODE1 (deprecated) */
682 buffer
[2] = 0; /* RCODE2 (deprecated) */
684 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
686 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
687 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
692 static int dhcp_client_send_raw(
693 sd_dhcp_client
*client
,
697 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
698 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
700 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
704 static int client_send_discover(sd_dhcp_client
*client
) {
705 _cleanup_free_ DHCPPacket
*discover
= NULL
;
706 size_t optoffset
, optlen
;
710 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
712 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
713 &optlen
, &optoffset
);
717 /* the client may suggest values for the network address
718 and lease time in the DHCPDISCOVER message. The client may include
719 the ’requested IP address’ option to suggest that a particular IP
720 address be assigned, and may include the ’IP address lease time’
721 option to suggest the lease time it would like.
723 if (client
->last_addr
!= INADDR_ANY
) {
724 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
725 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
726 4, &client
->last_addr
);
731 if (client
->hostname
) {
732 /* According to RFC 4702 "clients that send the Client FQDN option in
733 their messages MUST NOT also send the Host Name option". Just send
734 one of the two depending on the hostname type.
736 if (dns_name_is_single_label(client
->hostname
)) {
737 /* it is unclear from RFC 2131 if client should send hostname in
738 DHCPDISCOVER but dhclient does and so we do as well
740 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
741 SD_DHCP_OPTION_HOST_NAME
,
742 strlen(client
->hostname
), client
->hostname
);
744 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
750 if (client
->vendor_class_identifier
) {
751 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
752 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
753 strlen(client
->vendor_class_identifier
),
754 client
->vendor_class_identifier
);
759 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
760 SD_DHCP_OPTION_END
, 0, NULL
);
764 /* We currently ignore:
765 The client SHOULD wait a random time between one and ten seconds to
766 desynchronize the use of DHCP at startup.
768 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
772 log_dhcp_client(client
, "DISCOVER");
777 static int client_send_request(sd_dhcp_client
*client
) {
778 _cleanup_free_ DHCPPacket
*request
= NULL
;
779 size_t optoffset
, optlen
;
784 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
788 switch (client
->state
) {
789 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
790 SELECTING should be REQUESTING)
793 case DHCP_STATE_REQUESTING
:
794 /* Client inserts the address of the selected server in ’server
795 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
796 filled in with the yiaddr value from the chosen DHCPOFFER.
799 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
800 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
801 4, &client
->lease
->server_address
);
805 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
806 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
807 4, &client
->lease
->address
);
813 case DHCP_STATE_INIT_REBOOT
:
814 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
815 option MUST be filled in with client’s notion of its previously
816 assigned address. ’ciaddr’ MUST be zero.
818 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
819 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
820 4, &client
->last_addr
);
825 case DHCP_STATE_RENEWING
:
826 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
827 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
828 client’s IP address.
832 case DHCP_STATE_REBINDING
:
833 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
834 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
835 client’s IP address.
837 This message MUST be broadcast to the 0xffffffff IP broadcast address.
839 request
->dhcp
.ciaddr
= client
->lease
->address
;
843 case DHCP_STATE_INIT
:
844 case DHCP_STATE_SELECTING
:
845 case DHCP_STATE_REBOOTING
:
846 case DHCP_STATE_BOUND
:
847 case DHCP_STATE_STOPPED
:
851 if (client
->hostname
) {
852 if (dns_name_is_single_label(client
->hostname
))
853 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
854 SD_DHCP_OPTION_HOST_NAME
,
855 strlen(client
->hostname
), client
->hostname
);
857 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
863 if (client
->vendor_class_identifier
) {
864 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
865 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
866 strlen(client
->vendor_class_identifier
),
867 client
->vendor_class_identifier
);
872 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
873 SD_DHCP_OPTION_END
, 0, NULL
);
877 if (client
->state
== DHCP_STATE_RENEWING
) {
878 r
= dhcp_network_send_udp_socket(client
->fd
,
879 client
->lease
->server_address
,
882 sizeof(DHCPMessage
) + optoffset
);
884 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
889 switch (client
->state
) {
891 case DHCP_STATE_REQUESTING
:
892 log_dhcp_client(client
, "REQUEST (requesting)");
895 case DHCP_STATE_INIT_REBOOT
:
896 log_dhcp_client(client
, "REQUEST (init-reboot)");
899 case DHCP_STATE_RENEWING
:
900 log_dhcp_client(client
, "REQUEST (renewing)");
903 case DHCP_STATE_REBINDING
:
904 log_dhcp_client(client
, "REQUEST (rebinding)");
908 log_dhcp_client(client
, "REQUEST (invalid)");
915 static int client_start(sd_dhcp_client
*client
);
917 static int client_timeout_resend(
922 sd_dhcp_client
*client
= userdata
;
923 DHCP_CLIENT_DONT_DESTROY(client
);
924 usec_t next_timeout
= 0;
931 assert(client
->event
);
933 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
937 switch (client
->state
) {
939 case DHCP_STATE_RENEWING
:
941 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
945 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
949 case DHCP_STATE_REBINDING
:
951 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
955 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
958 case DHCP_STATE_REBOOTING
:
959 /* start over as we did not receive a timely ack or nak */
960 r
= client_initialize(client
);
964 r
= client_start(client
);
968 log_dhcp_client(client
, "REBOOTED");
972 case DHCP_STATE_INIT
:
973 case DHCP_STATE_INIT_REBOOT
:
974 case DHCP_STATE_SELECTING
:
975 case DHCP_STATE_REQUESTING
:
976 case DHCP_STATE_BOUND
:
978 if (client
->attempt
< 64)
979 client
->attempt
*= 2;
981 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
985 case DHCP_STATE_STOPPED
:
990 next_timeout
+= (random_u32() & 0x1fffff);
992 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
994 r
= sd_event_add_time(client
->event
,
995 &client
->timeout_resend
,
996 clock_boottime_or_monotonic(),
997 next_timeout
, 10 * USEC_PER_MSEC
,
998 client_timeout_resend
, client
);
1002 r
= sd_event_source_set_priority(client
->timeout_resend
,
1003 client
->event_priority
);
1007 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1011 switch (client
->state
) {
1012 case DHCP_STATE_INIT
:
1013 r
= client_send_discover(client
);
1015 client
->state
= DHCP_STATE_SELECTING
;
1016 client
->attempt
= 1;
1018 if (client
->attempt
>= 64)
1024 case DHCP_STATE_SELECTING
:
1025 r
= client_send_discover(client
);
1026 if (r
< 0 && client
->attempt
>= 64)
1031 case DHCP_STATE_INIT_REBOOT
:
1032 case DHCP_STATE_REQUESTING
:
1033 case DHCP_STATE_RENEWING
:
1034 case DHCP_STATE_REBINDING
:
1035 r
= client_send_request(client
);
1036 if (r
< 0 && client
->attempt
>= 64)
1039 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1040 client
->state
= DHCP_STATE_REBOOTING
;
1042 client
->request_sent
= time_now
;
1046 case DHCP_STATE_REBOOTING
:
1047 case DHCP_STATE_BOUND
:
1051 case DHCP_STATE_STOPPED
:
1059 client_stop(client
, r
);
1061 /* Errors were dealt with when stopping the client, don't spill
1062 errors into the event loop handler */
1066 static int client_initialize_io_events(
1067 sd_dhcp_client
*client
,
1068 sd_event_io_handler_t io_callback
) {
1073 assert(client
->event
);
1075 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1076 client
->fd
, EPOLLIN
, io_callback
,
1081 r
= sd_event_source_set_priority(client
->receive_message
,
1082 client
->event_priority
);
1086 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1092 client_stop(client
, r
);
1097 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1102 assert(client
->event
);
1104 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1106 if (client
->start_delay
) {
1107 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1108 usec
+= client
->start_delay
;
1111 r
= sd_event_add_time(client
->event
,
1112 &client
->timeout_resend
,
1113 clock_boottime_or_monotonic(),
1115 client_timeout_resend
, client
);
1119 r
= sd_event_source_set_priority(client
->timeout_resend
,
1120 client
->event_priority
);
1124 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1130 client_stop(client
, r
);
1136 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1137 client_initialize_io_events(client
, io_callback
);
1138 client_initialize_time_events(client
);
1143 static int client_start_delayed(sd_dhcp_client
*client
) {
1146 assert_return(client
, -EINVAL
);
1147 assert_return(client
->event
, -EINVAL
);
1148 assert_return(client
->ifindex
> 0, -EINVAL
);
1149 assert_return(client
->fd
< 0, -EBUSY
);
1150 assert_return(client
->xid
== 0, -EINVAL
);
1151 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1153 client
->xid
= random_u32();
1155 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1156 client
->xid
, client
->mac_addr
,
1157 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1159 client_stop(client
, r
);
1164 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1165 client
->start_time
= now(clock_boottime_or_monotonic());
1167 return client_initialize_events(client
, client_receive_message_raw
);
1170 static int client_start(sd_dhcp_client
*client
) {
1171 client
->start_delay
= 0;
1172 return client_start_delayed(client
);
1175 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1176 sd_dhcp_client
*client
= userdata
;
1177 DHCP_CLIENT_DONT_DESTROY(client
);
1179 log_dhcp_client(client
, "EXPIRED");
1181 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1183 /* lease was lost, start over if not freed or stopped in callback */
1184 if (client
->state
!= DHCP_STATE_STOPPED
) {
1185 client_initialize(client
);
1186 client_start(client
);
1192 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1193 sd_dhcp_client
*client
= userdata
;
1194 DHCP_CLIENT_DONT_DESTROY(client
);
1199 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1200 client
->fd
= asynchronous_close(client
->fd
);
1202 client
->state
= DHCP_STATE_REBINDING
;
1203 client
->attempt
= 1;
1205 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1206 client
->xid
, client
->mac_addr
,
1207 client
->mac_addr_len
, client
->arp_type
,
1210 client_stop(client
, r
);
1215 return client_initialize_events(client
, client_receive_message_raw
);
1218 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1219 sd_dhcp_client
*client
= userdata
;
1220 DHCP_CLIENT_DONT_DESTROY(client
);
1222 client
->state
= DHCP_STATE_RENEWING
;
1223 client
->attempt
= 1;
1225 return client_initialize_time_events(client
);
1228 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1229 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1232 r
= dhcp_lease_new(&lease
);
1236 if (client
->client_id_len
) {
1237 r
= dhcp_lease_set_client_id(lease
,
1238 (uint8_t *) &client
->client_id
,
1239 client
->client_id_len
);
1244 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1245 if (r
!= DHCP_OFFER
) {
1246 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1250 lease
->next_server
= offer
->siaddr
;
1251 lease
->address
= offer
->yiaddr
;
1253 if (lease
->address
== 0 ||
1254 lease
->server_address
== 0 ||
1255 lease
->lifetime
== 0) {
1256 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1260 if (!lease
->have_subnet_mask
) {
1261 r
= dhcp_lease_set_default_subnet_mask(lease
);
1263 log_dhcp_client(client
, "received lease lacks subnet "
1264 "mask, and a fallback one can not be "
1265 "generated, ignoring");
1270 sd_dhcp_lease_unref(client
->lease
);
1271 client
->lease
= lease
;
1274 log_dhcp_client(client
, "OFFER");
1279 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1282 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1283 if (r
!= DHCP_FORCERENEW
)
1286 log_dhcp_client(client
, "FORCERENEW");
1291 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1292 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1293 _cleanup_free_
char *error_message
= NULL
;
1296 r
= dhcp_lease_new(&lease
);
1300 if (client
->client_id_len
) {
1301 r
= dhcp_lease_set_client_id(lease
,
1302 (uint8_t *) &client
->client_id
,
1303 client
->client_id_len
);
1308 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1309 if (r
== DHCP_NAK
) {
1310 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1311 return -EADDRNOTAVAIL
;
1314 if (r
!= DHCP_ACK
) {
1315 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1319 lease
->next_server
= ack
->siaddr
;
1321 lease
->address
= ack
->yiaddr
;
1323 if (lease
->address
== INADDR_ANY
||
1324 lease
->server_address
== INADDR_ANY
||
1325 lease
->lifetime
== 0) {
1326 log_dhcp_client(client
, "received lease lacks address, server "
1327 "address or lease lifetime, ignoring");
1331 if (lease
->subnet_mask
== INADDR_ANY
) {
1332 r
= dhcp_lease_set_default_subnet_mask(lease
);
1334 log_dhcp_client(client
, "received lease lacks subnet "
1335 "mask, and a fallback one can not be "
1336 "generated, ignoring");
1341 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1342 if (client
->lease
) {
1343 if (client
->lease
->address
!= lease
->address
||
1344 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1345 client
->lease
->router
!= lease
->router
) {
1346 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1348 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1350 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1353 client
->lease
= lease
;
1356 log_dhcp_client(client
, "ACK");
1361 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1363 assert(client
->request_sent
);
1364 assert(lifetime
> 0);
1371 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1372 + (random_u32() & 0x1fffff);
1375 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1377 uint64_t lifetime_timeout
;
1378 uint64_t t2_timeout
;
1379 uint64_t t1_timeout
;
1380 char time_string
[FORMAT_TIMESPAN_MAX
];
1384 assert(client
->event
);
1385 assert(client
->lease
);
1386 assert(client
->lease
->lifetime
);
1388 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1389 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1390 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1392 /* don't set timers for infinite leases */
1393 if (client
->lease
->lifetime
== 0xffffffff)
1396 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1399 assert(client
->request_sent
<= time_now
);
1401 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1402 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1403 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1404 /* both T1 and T2 are given */
1405 if (client
->lease
->t1
< client
->lease
->t2
&&
1406 client
->lease
->t2
< client
->lease
->lifetime
) {
1407 /* they are both valid */
1408 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1409 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1412 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1413 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1414 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1415 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1417 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1418 /* only T2 is given, and it is valid */
1419 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1420 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1421 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1422 if (t2_timeout
<= t1_timeout
) {
1423 /* the computed T1 would be invalid, so discard T2 */
1424 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1425 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1427 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1428 /* only T1 is given, and it is valid */
1429 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1430 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1431 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1432 if (t2_timeout
<= t1_timeout
) {
1433 /* the computed T2 would be invalid, so discard T1 */
1434 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1435 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1438 /* fall back to the default timeouts */
1439 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1440 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1441 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1442 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1445 /* arm lifetime timeout */
1446 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1447 clock_boottime_or_monotonic(),
1448 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1449 client_timeout_expire
, client
);
1453 r
= sd_event_source_set_priority(client
->timeout_expire
,
1454 client
->event_priority
);
1458 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1462 log_dhcp_client(client
, "lease expires in %s",
1463 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1465 /* don't arm earlier timeouts if this has already expired */
1466 if (lifetime_timeout
<= time_now
)
1469 /* arm T2 timeout */
1470 r
= sd_event_add_time(client
->event
,
1471 &client
->timeout_t2
,
1472 clock_boottime_or_monotonic(),
1475 client_timeout_t2
, client
);
1479 r
= sd_event_source_set_priority(client
->timeout_t2
,
1480 client
->event_priority
);
1484 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1488 log_dhcp_client(client
, "T2 expires in %s",
1489 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1491 /* don't arm earlier timeout if this has already expired */
1492 if (t2_timeout
<= time_now
)
1495 /* arm T1 timeout */
1496 r
= sd_event_add_time(client
->event
,
1497 &client
->timeout_t1
,
1498 clock_boottime_or_monotonic(),
1499 t1_timeout
, 10 * USEC_PER_MSEC
,
1500 client_timeout_t1
, client
);
1504 r
= sd_event_source_set_priority(client
->timeout_t1
,
1505 client
->event_priority
);
1509 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1513 log_dhcp_client(client
, "T1 expires in %s",
1514 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1519 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1520 DHCP_CLIENT_DONT_DESTROY(client
);
1521 char time_string
[FORMAT_TIMESPAN_MAX
];
1522 int r
= 0, notify_event
= 0;
1525 assert(client
->event
);
1528 switch (client
->state
) {
1529 case DHCP_STATE_SELECTING
:
1531 r
= client_handle_offer(client
, message
, len
);
1534 client
->timeout_resend
=
1535 sd_event_source_unref(client
->timeout_resend
);
1537 client
->state
= DHCP_STATE_REQUESTING
;
1538 client
->attempt
= 1;
1540 r
= sd_event_add_time(client
->event
,
1541 &client
->timeout_resend
,
1542 clock_boottime_or_monotonic(),
1544 client_timeout_resend
, client
);
1548 r
= sd_event_source_set_priority(client
->timeout_resend
,
1549 client
->event_priority
);
1553 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1556 } else if (r
== -ENOMSG
)
1557 /* invalid message, let's ignore it */
1562 case DHCP_STATE_REBOOTING
:
1563 case DHCP_STATE_REQUESTING
:
1564 case DHCP_STATE_RENEWING
:
1565 case DHCP_STATE_REBINDING
:
1567 r
= client_handle_ack(client
, message
, len
);
1569 client
->start_delay
= 0;
1570 client
->timeout_resend
=
1571 sd_event_source_unref(client
->timeout_resend
);
1572 client
->receive_message
=
1573 sd_event_source_unref(client
->receive_message
);
1574 client
->fd
= asynchronous_close(client
->fd
);
1576 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1577 DHCP_STATE_REBOOTING
))
1578 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1579 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1582 client
->state
= DHCP_STATE_BOUND
;
1583 client
->attempt
= 1;
1585 client
->last_addr
= client
->lease
->address
;
1587 r
= client_set_lease_timeouts(client
);
1589 log_dhcp_client(client
, "could not set lease timeouts");
1593 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1595 log_dhcp_client(client
, "could not bind UDP socket");
1601 client_initialize_io_events(client
, client_receive_message_udp
);
1604 client_notify(client
, notify_event
);
1605 if (client
->state
== DHCP_STATE_STOPPED
)
1609 } else if (r
== -EADDRNOTAVAIL
) {
1610 /* got a NAK, let's restart the client */
1611 client
->timeout_resend
=
1612 sd_event_source_unref(client
->timeout_resend
);
1614 r
= client_initialize(client
);
1618 r
= client_start_delayed(client
);
1622 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1623 client
->start_delay
, USEC_PER_SEC
));
1625 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1626 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1629 } else if (r
== -ENOMSG
)
1630 /* invalid message, let's ignore it */
1635 case DHCP_STATE_BOUND
:
1636 r
= client_handle_forcerenew(client
, message
, len
);
1638 r
= client_timeout_t1(NULL
, 0, client
);
1641 } else if (r
== -ENOMSG
)
1642 /* invalid message, let's ignore it */
1647 case DHCP_STATE_INIT
:
1648 case DHCP_STATE_INIT_REBOOT
:
1652 case DHCP_STATE_STOPPED
:
1659 client_stop(client
, r
);
1664 static int client_receive_message_udp(
1670 sd_dhcp_client
*client
= userdata
;
1671 _cleanup_free_ DHCPMessage
*message
= NULL
;
1672 const struct ether_addr zero_mac
= {};
1673 const struct ether_addr
*expected_chaddr
= NULL
;
1674 uint8_t expected_hlen
= 0;
1675 ssize_t len
, buflen
;
1680 buflen
= next_datagram_size_fd(fd
);
1684 message
= malloc0(buflen
);
1688 len
= recv(fd
, message
, buflen
, 0);
1690 if (IN_SET(errno
, EAGAIN
, EINTR
))
1693 return log_dhcp_client_errno(client
, errno
,
1694 "Could not receive message from UDP socket: %m");
1696 if ((size_t) len
< sizeof(DHCPMessage
)) {
1697 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1701 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1702 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1706 if (message
->op
!= BOOTREPLY
) {
1707 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1711 if (message
->htype
!= client
->arp_type
) {
1712 log_dhcp_client(client
, "Packet type does not match client type");
1716 if (client
->arp_type
== ARPHRD_ETHER
) {
1717 expected_hlen
= ETH_ALEN
;
1718 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1720 /* Non-Ethernet links expect zero chaddr */
1722 expected_chaddr
= &zero_mac
;
1725 if (message
->hlen
!= expected_hlen
) {
1726 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1730 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1731 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1735 if (client
->state
!= DHCP_STATE_BOUND
&&
1736 be32toh(message
->xid
) != client
->xid
) {
1737 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1738 so ignore the xid in this case */
1739 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1740 be32toh(message
->xid
), client
->xid
);
1744 return client_handle_message(client
, message
, len
);
1747 static int client_receive_message_raw(
1753 sd_dhcp_client
*client
= userdata
;
1754 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1755 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1756 struct iovec iov
= {};
1757 struct msghdr msg
= {
1760 .msg_control
= cmsgbuf
,
1761 .msg_controllen
= sizeof(cmsgbuf
),
1763 struct cmsghdr
*cmsg
;
1764 bool checksum
= true;
1765 ssize_t buflen
, len
;
1771 buflen
= next_datagram_size_fd(fd
);
1775 packet
= malloc0(buflen
);
1779 iov
.iov_base
= packet
;
1780 iov
.iov_len
= buflen
;
1782 len
= recvmsg(fd
, &msg
, 0);
1784 if (IN_SET(errno
, EAGAIN
, EINTR
))
1787 return log_dhcp_client_errno(client
, errno
,
1788 "Could not receive message from raw socket: %m");
1789 } else if ((size_t)len
< sizeof(DHCPPacket
))
1792 CMSG_FOREACH(cmsg
, &msg
) {
1793 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1794 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1795 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1796 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1798 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1803 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1807 len
-= DHCP_IP_UDP_SIZE
;
1809 return client_handle_message(client
, &packet
->dhcp
, len
);
1812 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1815 assert_return(client
, -EINVAL
);
1817 r
= client_initialize(client
);
1821 /* RFC7844 section 3.3:
1822 SHOULD perform a complete four-way handshake, starting with a
1823 DHCPDISCOVER, to obtain a new address lease. If the client can
1824 ascertain that this is exactly the same network to which it was
1825 previously connected, and if the link-layer address did not change,
1826 the client MAY issue a DHCPREQUEST to try to reclaim the current
1828 if (client
->last_addr
&& !client
->anonymize
)
1829 client
->state
= DHCP_STATE_INIT_REBOOT
;
1831 r
= client_start(client
);
1833 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1838 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1839 DHCP_CLIENT_DONT_DESTROY(client
);
1841 assert_return(client
, -EINVAL
);
1843 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1844 client
->state
= DHCP_STATE_STOPPED
;
1849 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1852 assert_return(client
, -EINVAL
);
1853 assert_return(!client
->event
, -EBUSY
);
1856 client
->event
= sd_event_ref(event
);
1858 r
= sd_event_default(&client
->event
);
1863 client
->event_priority
= priority
;
1868 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1869 assert_return(client
, -EINVAL
);
1871 client
->event
= sd_event_unref(client
->event
);
1876 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1877 assert_return(client
, NULL
);
1879 return client
->event
;
1882 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1887 assert(client
->n_ref
>= 1);
1893 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1898 assert(client
->n_ref
>= 1);
1901 if (client
->n_ref
> 0)
1904 log_dhcp_client(client
, "FREE");
1906 client_initialize(client
);
1908 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1910 sd_dhcp_client_detach_event(client
);
1912 sd_dhcp_lease_unref(client
->lease
);
1914 free(client
->req_opts
);
1915 free(client
->hostname
);
1916 free(client
->vendor_class_identifier
);
1917 return mfree(client
);
1920 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1921 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1923 assert_return(ret
, -EINVAL
);
1925 client
= new0(sd_dhcp_client
, 1);
1930 client
->state
= DHCP_STATE_INIT
;
1931 client
->ifindex
= -1;
1933 client
->attempt
= 1;
1934 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1935 client
->port
= DHCP_PORT_CLIENT
;
1937 client
->anonymize
= !!anonymize
;
1938 /* NOTE: this could be moved to a function. */
1940 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1941 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1943 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1944 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1946 if (!client
->req_opts
)