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(type
== DHCP_DISCOVER
|| type
== 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(client
->state
== DHCP_STATE_INIT
||
711 client
->state
== DHCP_STATE_SELECTING
);
713 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
714 &optlen
, &optoffset
);
718 /* the client may suggest values for the network address
719 and lease time in the DHCPDISCOVER message. The client may include
720 the ’requested IP address’ option to suggest that a particular IP
721 address be assigned, and may include the ’IP address lease time’
722 option to suggest the lease time it would like.
724 if (client
->last_addr
!= INADDR_ANY
) {
725 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
726 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
727 4, &client
->last_addr
);
732 if (client
->hostname
) {
733 /* According to RFC 4702 "clients that send the Client FQDN option in
734 their messages MUST NOT also send the Host Name option". Just send
735 one of the two depending on the hostname type.
737 if (dns_name_is_single_label(client
->hostname
)) {
738 /* it is unclear from RFC 2131 if client should send hostname in
739 DHCPDISCOVER but dhclient does and so we do as well
741 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
742 SD_DHCP_OPTION_HOST_NAME
,
743 strlen(client
->hostname
), client
->hostname
);
745 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
751 if (client
->vendor_class_identifier
) {
752 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
753 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
754 strlen(client
->vendor_class_identifier
),
755 client
->vendor_class_identifier
);
760 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
761 SD_DHCP_OPTION_END
, 0, NULL
);
765 /* We currently ignore:
766 The client SHOULD wait a random time between one and ten seconds to
767 desynchronize the use of DHCP at startup.
769 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
773 log_dhcp_client(client
, "DISCOVER");
778 static int client_send_request(sd_dhcp_client
*client
) {
779 _cleanup_free_ DHCPPacket
*request
= NULL
;
780 size_t optoffset
, optlen
;
785 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
789 switch (client
->state
) {
790 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
791 SELECTING should be REQUESTING)
794 case DHCP_STATE_REQUESTING
:
795 /* Client inserts the address of the selected server in ’server
796 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
797 filled in with the yiaddr value from the chosen DHCPOFFER.
800 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
801 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
802 4, &client
->lease
->server_address
);
806 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
807 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
808 4, &client
->lease
->address
);
814 case DHCP_STATE_INIT_REBOOT
:
815 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
816 option MUST be filled in with client’s notion of its previously
817 assigned address. ’ciaddr’ MUST be zero.
819 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
820 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
821 4, &client
->last_addr
);
826 case DHCP_STATE_RENEWING
:
827 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
828 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
833 case DHCP_STATE_REBINDING
:
834 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
835 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
838 This message MUST be broadcast to the 0xffffffff IP broadcast address.
840 request
->dhcp
.ciaddr
= client
->lease
->address
;
844 case DHCP_STATE_INIT
:
845 case DHCP_STATE_SELECTING
:
846 case DHCP_STATE_REBOOTING
:
847 case DHCP_STATE_BOUND
:
848 case DHCP_STATE_STOPPED
:
852 if (client
->hostname
) {
853 if (dns_name_is_single_label(client
->hostname
))
854 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
855 SD_DHCP_OPTION_HOST_NAME
,
856 strlen(client
->hostname
), client
->hostname
);
858 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
864 if (client
->vendor_class_identifier
) {
865 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
866 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
867 strlen(client
->vendor_class_identifier
),
868 client
->vendor_class_identifier
);
873 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
874 SD_DHCP_OPTION_END
, 0, NULL
);
878 if (client
->state
== DHCP_STATE_RENEWING
) {
879 r
= dhcp_network_send_udp_socket(client
->fd
,
880 client
->lease
->server_address
,
883 sizeof(DHCPMessage
) + optoffset
);
885 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
890 switch (client
->state
) {
892 case DHCP_STATE_REQUESTING
:
893 log_dhcp_client(client
, "REQUEST (requesting)");
896 case DHCP_STATE_INIT_REBOOT
:
897 log_dhcp_client(client
, "REQUEST (init-reboot)");
900 case DHCP_STATE_RENEWING
:
901 log_dhcp_client(client
, "REQUEST (renewing)");
904 case DHCP_STATE_REBINDING
:
905 log_dhcp_client(client
, "REQUEST (rebinding)");
909 log_dhcp_client(client
, "REQUEST (invalid)");
916 static int client_start(sd_dhcp_client
*client
);
918 static int client_timeout_resend(
923 sd_dhcp_client
*client
= userdata
;
924 DHCP_CLIENT_DONT_DESTROY(client
);
925 usec_t next_timeout
= 0;
932 assert(client
->event
);
934 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
938 switch (client
->state
) {
940 case DHCP_STATE_RENEWING
:
942 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
946 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
950 case DHCP_STATE_REBINDING
:
952 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
956 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
959 case DHCP_STATE_REBOOTING
:
960 /* start over as we did not receive a timely ack or nak */
961 r
= client_initialize(client
);
965 r
= client_start(client
);
969 log_dhcp_client(client
, "REBOOTED");
973 case DHCP_STATE_INIT
:
974 case DHCP_STATE_INIT_REBOOT
:
975 case DHCP_STATE_SELECTING
:
976 case DHCP_STATE_REQUESTING
:
977 case DHCP_STATE_BOUND
:
979 if (client
->attempt
< 64)
980 client
->attempt
*= 2;
982 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
986 case DHCP_STATE_STOPPED
:
991 next_timeout
+= (random_u32() & 0x1fffff);
993 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
995 r
= sd_event_add_time(client
->event
,
996 &client
->timeout_resend
,
997 clock_boottime_or_monotonic(),
998 next_timeout
, 10 * USEC_PER_MSEC
,
999 client_timeout_resend
, client
);
1003 r
= sd_event_source_set_priority(client
->timeout_resend
,
1004 client
->event_priority
);
1008 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1012 switch (client
->state
) {
1013 case DHCP_STATE_INIT
:
1014 r
= client_send_discover(client
);
1016 client
->state
= DHCP_STATE_SELECTING
;
1017 client
->attempt
= 1;
1019 if (client
->attempt
>= 64)
1025 case DHCP_STATE_SELECTING
:
1026 r
= client_send_discover(client
);
1027 if (r
< 0 && client
->attempt
>= 64)
1032 case DHCP_STATE_INIT_REBOOT
:
1033 case DHCP_STATE_REQUESTING
:
1034 case DHCP_STATE_RENEWING
:
1035 case DHCP_STATE_REBINDING
:
1036 r
= client_send_request(client
);
1037 if (r
< 0 && client
->attempt
>= 64)
1040 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1041 client
->state
= DHCP_STATE_REBOOTING
;
1043 client
->request_sent
= time_now
;
1047 case DHCP_STATE_REBOOTING
:
1048 case DHCP_STATE_BOUND
:
1052 case DHCP_STATE_STOPPED
:
1060 client_stop(client
, r
);
1062 /* Errors were dealt with when stopping the client, don't spill
1063 errors into the event loop handler */
1067 static int client_initialize_io_events(
1068 sd_dhcp_client
*client
,
1069 sd_event_io_handler_t io_callback
) {
1074 assert(client
->event
);
1076 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1077 client
->fd
, EPOLLIN
, io_callback
,
1082 r
= sd_event_source_set_priority(client
->receive_message
,
1083 client
->event_priority
);
1087 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1093 client_stop(client
, r
);
1098 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1103 assert(client
->event
);
1105 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1107 if (client
->start_delay
) {
1108 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1109 usec
+= client
->start_delay
;
1112 r
= sd_event_add_time(client
->event
,
1113 &client
->timeout_resend
,
1114 clock_boottime_or_monotonic(),
1116 client_timeout_resend
, client
);
1120 r
= sd_event_source_set_priority(client
->timeout_resend
,
1121 client
->event_priority
);
1125 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1131 client_stop(client
, r
);
1137 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1138 client_initialize_io_events(client
, io_callback
);
1139 client_initialize_time_events(client
);
1144 static int client_start_delayed(sd_dhcp_client
*client
) {
1147 assert_return(client
, -EINVAL
);
1148 assert_return(client
->event
, -EINVAL
);
1149 assert_return(client
->ifindex
> 0, -EINVAL
);
1150 assert_return(client
->fd
< 0, -EBUSY
);
1151 assert_return(client
->xid
== 0, -EINVAL
);
1152 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1154 client
->xid
= random_u32();
1156 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1157 client
->xid
, client
->mac_addr
,
1158 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1160 client_stop(client
, r
);
1165 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1166 client
->start_time
= now(clock_boottime_or_monotonic());
1168 return client_initialize_events(client
, client_receive_message_raw
);
1171 static int client_start(sd_dhcp_client
*client
) {
1172 client
->start_delay
= 0;
1173 return client_start_delayed(client
);
1176 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1177 sd_dhcp_client
*client
= userdata
;
1178 DHCP_CLIENT_DONT_DESTROY(client
);
1180 log_dhcp_client(client
, "EXPIRED");
1182 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1184 /* lease was lost, start over if not freed or stopped in callback */
1185 if (client
->state
!= DHCP_STATE_STOPPED
) {
1186 client_initialize(client
);
1187 client_start(client
);
1193 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1194 sd_dhcp_client
*client
= userdata
;
1195 DHCP_CLIENT_DONT_DESTROY(client
);
1200 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1201 client
->fd
= asynchronous_close(client
->fd
);
1203 client
->state
= DHCP_STATE_REBINDING
;
1204 client
->attempt
= 1;
1206 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1207 client
->xid
, client
->mac_addr
,
1208 client
->mac_addr_len
, client
->arp_type
,
1211 client_stop(client
, r
);
1216 return client_initialize_events(client
, client_receive_message_raw
);
1219 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1220 sd_dhcp_client
*client
= userdata
;
1221 DHCP_CLIENT_DONT_DESTROY(client
);
1223 client
->state
= DHCP_STATE_RENEWING
;
1224 client
->attempt
= 1;
1226 return client_initialize_time_events(client
);
1229 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1230 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1233 r
= dhcp_lease_new(&lease
);
1237 if (client
->client_id_len
) {
1238 r
= dhcp_lease_set_client_id(lease
,
1239 (uint8_t *) &client
->client_id
,
1240 client
->client_id_len
);
1245 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1246 if (r
!= DHCP_OFFER
) {
1247 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1251 lease
->next_server
= offer
->siaddr
;
1252 lease
->address
= offer
->yiaddr
;
1254 if (lease
->address
== 0 ||
1255 lease
->server_address
== 0 ||
1256 lease
->lifetime
== 0) {
1257 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1261 if (!lease
->have_subnet_mask
) {
1262 r
= dhcp_lease_set_default_subnet_mask(lease
);
1264 log_dhcp_client(client
, "received lease lacks subnet "
1265 "mask, and a fallback one can not be "
1266 "generated, ignoring");
1271 sd_dhcp_lease_unref(client
->lease
);
1272 client
->lease
= lease
;
1275 log_dhcp_client(client
, "OFFER");
1280 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1283 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1284 if (r
!= DHCP_FORCERENEW
)
1287 log_dhcp_client(client
, "FORCERENEW");
1292 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1293 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1294 _cleanup_free_
char *error_message
= NULL
;
1297 r
= dhcp_lease_new(&lease
);
1301 if (client
->client_id_len
) {
1302 r
= dhcp_lease_set_client_id(lease
,
1303 (uint8_t *) &client
->client_id
,
1304 client
->client_id_len
);
1309 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1310 if (r
== DHCP_NAK
) {
1311 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1312 return -EADDRNOTAVAIL
;
1315 if (r
!= DHCP_ACK
) {
1316 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1320 lease
->next_server
= ack
->siaddr
;
1322 lease
->address
= ack
->yiaddr
;
1324 if (lease
->address
== INADDR_ANY
||
1325 lease
->server_address
== INADDR_ANY
||
1326 lease
->lifetime
== 0) {
1327 log_dhcp_client(client
, "received lease lacks address, server "
1328 "address or lease lifetime, ignoring");
1332 if (lease
->subnet_mask
== INADDR_ANY
) {
1333 r
= dhcp_lease_set_default_subnet_mask(lease
);
1335 log_dhcp_client(client
, "received lease lacks subnet "
1336 "mask, and a fallback one can not be "
1337 "generated, ignoring");
1342 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1343 if (client
->lease
) {
1344 if (client
->lease
->address
!= lease
->address
||
1345 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1346 client
->lease
->router
!= lease
->router
) {
1347 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1349 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1351 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1354 client
->lease
= lease
;
1357 log_dhcp_client(client
, "ACK");
1362 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1364 assert(client
->request_sent
);
1365 assert(lifetime
> 0);
1372 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1373 + (random_u32() & 0x1fffff);
1376 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1378 uint64_t lifetime_timeout
;
1379 uint64_t t2_timeout
;
1380 uint64_t t1_timeout
;
1381 char time_string
[FORMAT_TIMESPAN_MAX
];
1385 assert(client
->event
);
1386 assert(client
->lease
);
1387 assert(client
->lease
->lifetime
);
1389 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1390 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1391 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1393 /* don't set timers for infinite leases */
1394 if (client
->lease
->lifetime
== 0xffffffff)
1397 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1400 assert(client
->request_sent
<= time_now
);
1402 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1403 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1404 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1405 /* both T1 and T2 are given */
1406 if (client
->lease
->t1
< client
->lease
->t2
&&
1407 client
->lease
->t2
< client
->lease
->lifetime
) {
1408 /* they are both valid */
1409 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1410 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1413 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1414 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1415 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1416 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1418 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1419 /* only T2 is given, and it is valid */
1420 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1421 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1422 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1423 if (t2_timeout
<= t1_timeout
) {
1424 /* the computed T1 would be invalid, so discard T2 */
1425 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1426 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1428 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1429 /* only T1 is given, and it is valid */
1430 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1431 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1432 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1433 if (t2_timeout
<= t1_timeout
) {
1434 /* the computed T2 would be invalid, so discard T1 */
1435 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1436 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1439 /* fall back to the default timeouts */
1440 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1441 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1442 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1443 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1446 /* arm lifetime timeout */
1447 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1448 clock_boottime_or_monotonic(),
1449 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1450 client_timeout_expire
, client
);
1454 r
= sd_event_source_set_priority(client
->timeout_expire
,
1455 client
->event_priority
);
1459 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1463 log_dhcp_client(client
, "lease expires in %s",
1464 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1466 /* don't arm earlier timeouts if this has already expired */
1467 if (lifetime_timeout
<= time_now
)
1470 /* arm T2 timeout */
1471 r
= sd_event_add_time(client
->event
,
1472 &client
->timeout_t2
,
1473 clock_boottime_or_monotonic(),
1476 client_timeout_t2
, client
);
1480 r
= sd_event_source_set_priority(client
->timeout_t2
,
1481 client
->event_priority
);
1485 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1489 log_dhcp_client(client
, "T2 expires in %s",
1490 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1492 /* don't arm earlier timeout if this has already expired */
1493 if (t2_timeout
<= time_now
)
1496 /* arm T1 timeout */
1497 r
= sd_event_add_time(client
->event
,
1498 &client
->timeout_t1
,
1499 clock_boottime_or_monotonic(),
1500 t1_timeout
, 10 * USEC_PER_MSEC
,
1501 client_timeout_t1
, client
);
1505 r
= sd_event_source_set_priority(client
->timeout_t1
,
1506 client
->event_priority
);
1510 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1514 log_dhcp_client(client
, "T1 expires in %s",
1515 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1520 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1521 DHCP_CLIENT_DONT_DESTROY(client
);
1522 char time_string
[FORMAT_TIMESPAN_MAX
];
1523 int r
= 0, notify_event
= 0;
1526 assert(client
->event
);
1529 switch (client
->state
) {
1530 case DHCP_STATE_SELECTING
:
1532 r
= client_handle_offer(client
, message
, len
);
1535 client
->timeout_resend
=
1536 sd_event_source_unref(client
->timeout_resend
);
1538 client
->state
= DHCP_STATE_REQUESTING
;
1539 client
->attempt
= 1;
1541 r
= sd_event_add_time(client
->event
,
1542 &client
->timeout_resend
,
1543 clock_boottime_or_monotonic(),
1545 client_timeout_resend
, client
);
1549 r
= sd_event_source_set_priority(client
->timeout_resend
,
1550 client
->event_priority
);
1554 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1557 } else if (r
== -ENOMSG
)
1558 /* invalid message, let's ignore it */
1563 case DHCP_STATE_REBOOTING
:
1564 case DHCP_STATE_REQUESTING
:
1565 case DHCP_STATE_RENEWING
:
1566 case DHCP_STATE_REBINDING
:
1568 r
= client_handle_ack(client
, message
, len
);
1570 client
->start_delay
= 0;
1571 client
->timeout_resend
=
1572 sd_event_source_unref(client
->timeout_resend
);
1573 client
->receive_message
=
1574 sd_event_source_unref(client
->receive_message
);
1575 client
->fd
= asynchronous_close(client
->fd
);
1577 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1578 DHCP_STATE_REBOOTING
))
1579 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1580 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1583 client
->state
= DHCP_STATE_BOUND
;
1584 client
->attempt
= 1;
1586 client
->last_addr
= client
->lease
->address
;
1588 r
= client_set_lease_timeouts(client
);
1590 log_dhcp_client(client
, "could not set lease timeouts");
1594 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1596 log_dhcp_client(client
, "could not bind UDP socket");
1602 client_initialize_io_events(client
, client_receive_message_udp
);
1605 client_notify(client
, notify_event
);
1606 if (client
->state
== DHCP_STATE_STOPPED
)
1610 } else if (r
== -EADDRNOTAVAIL
) {
1611 /* got a NAK, let's restart the client */
1612 client
->timeout_resend
=
1613 sd_event_source_unref(client
->timeout_resend
);
1615 r
= client_initialize(client
);
1619 r
= client_start_delayed(client
);
1623 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1624 client
->start_delay
, USEC_PER_SEC
));
1626 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1627 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1630 } else if (r
== -ENOMSG
)
1631 /* invalid message, let's ignore it */
1636 case DHCP_STATE_BOUND
:
1637 r
= client_handle_forcerenew(client
, message
, len
);
1639 r
= client_timeout_t1(NULL
, 0, client
);
1642 } else if (r
== -ENOMSG
)
1643 /* invalid message, let's ignore it */
1648 case DHCP_STATE_INIT
:
1649 case DHCP_STATE_INIT_REBOOT
:
1653 case DHCP_STATE_STOPPED
:
1660 client_stop(client
, r
);
1665 static int client_receive_message_udp(
1671 sd_dhcp_client
*client
= userdata
;
1672 _cleanup_free_ DHCPMessage
*message
= NULL
;
1673 const struct ether_addr zero_mac
= {};
1674 const struct ether_addr
*expected_chaddr
= NULL
;
1675 uint8_t expected_hlen
= 0;
1676 ssize_t len
, buflen
;
1681 buflen
= next_datagram_size_fd(fd
);
1685 message
= malloc0(buflen
);
1689 len
= recv(fd
, message
, buflen
, 0);
1691 if (errno
== EAGAIN
|| errno
== EINTR
)
1694 return log_dhcp_client_errno(client
, errno
,
1695 "Could not receive message from UDP socket: %m");
1697 if ((size_t) len
< sizeof(DHCPMessage
)) {
1698 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1702 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1703 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1707 if (message
->op
!= BOOTREPLY
) {
1708 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1712 if (message
->htype
!= client
->arp_type
) {
1713 log_dhcp_client(client
, "Packet type does not match client type");
1717 if (client
->arp_type
== ARPHRD_ETHER
) {
1718 expected_hlen
= ETH_ALEN
;
1719 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1721 /* Non-Ethernet links expect zero chaddr */
1723 expected_chaddr
= &zero_mac
;
1726 if (message
->hlen
!= expected_hlen
) {
1727 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1731 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1732 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1736 if (client
->state
!= DHCP_STATE_BOUND
&&
1737 be32toh(message
->xid
) != client
->xid
) {
1738 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1739 so ignore the xid in this case */
1740 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1741 be32toh(message
->xid
), client
->xid
);
1745 return client_handle_message(client
, message
, len
);
1748 static int client_receive_message_raw(
1754 sd_dhcp_client
*client
= userdata
;
1755 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1756 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1757 struct iovec iov
= {};
1758 struct msghdr msg
= {
1761 .msg_control
= cmsgbuf
,
1762 .msg_controllen
= sizeof(cmsgbuf
),
1764 struct cmsghdr
*cmsg
;
1765 bool checksum
= true;
1766 ssize_t buflen
, len
;
1772 buflen
= next_datagram_size_fd(fd
);
1776 packet
= malloc0(buflen
);
1780 iov
.iov_base
= packet
;
1781 iov
.iov_len
= buflen
;
1783 len
= recvmsg(fd
, &msg
, 0);
1785 if (errno
== EAGAIN
|| errno
== EINTR
)
1788 return log_dhcp_client_errno(client
, errno
,
1789 "Could not receive message from raw socket: %m");
1790 } else if ((size_t)len
< sizeof(DHCPPacket
))
1793 CMSG_FOREACH(cmsg
, &msg
) {
1794 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1795 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1796 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1797 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1799 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1804 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1808 len
-= DHCP_IP_UDP_SIZE
;
1810 return client_handle_message(client
, &packet
->dhcp
, len
);
1813 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1816 assert_return(client
, -EINVAL
);
1818 r
= client_initialize(client
);
1822 /* RFC7844 section 3.3:
1823 SHOULD perform a complete four-way handshake, starting with a
1824 DHCPDISCOVER, to obtain a new address lease. If the client can
1825 ascertain that this is exactly the same network to which it was
1826 previously connected, and if the link-layer address did not change,
1827 the client MAY issue a DHCPREQUEST to try to reclaim the current
1829 if (client
->last_addr
&& !client
->anonymize
)
1830 client
->state
= DHCP_STATE_INIT_REBOOT
;
1832 r
= client_start(client
);
1834 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1839 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1840 DHCP_CLIENT_DONT_DESTROY(client
);
1842 assert_return(client
, -EINVAL
);
1844 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1845 client
->state
= DHCP_STATE_STOPPED
;
1850 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1853 assert_return(client
, -EINVAL
);
1854 assert_return(!client
->event
, -EBUSY
);
1857 client
->event
= sd_event_ref(event
);
1859 r
= sd_event_default(&client
->event
);
1864 client
->event_priority
= priority
;
1869 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1870 assert_return(client
, -EINVAL
);
1872 client
->event
= sd_event_unref(client
->event
);
1877 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1878 assert_return(client
, NULL
);
1880 return client
->event
;
1883 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1888 assert(client
->n_ref
>= 1);
1894 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1899 assert(client
->n_ref
>= 1);
1902 if (client
->n_ref
> 0)
1905 log_dhcp_client(client
, "FREE");
1907 client_initialize(client
);
1909 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1911 sd_dhcp_client_detach_event(client
);
1913 sd_dhcp_lease_unref(client
->lease
);
1915 free(client
->req_opts
);
1916 free(client
->hostname
);
1917 free(client
->vendor_class_identifier
);
1918 return mfree(client
);
1921 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1922 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1924 assert_return(ret
, -EINVAL
);
1926 client
= new0(sd_dhcp_client
, 1);
1931 client
->state
= DHCP_STATE_INIT
;
1932 client
->ifindex
= -1;
1934 client
->attempt
= 1;
1935 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1936 client
->port
= DHCP_PORT_CLIENT
;
1938 client
->anonymize
= !!anonymize
;
1939 /* NOTE: this could be moved to a function. */
1941 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1942 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1944 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1945 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1947 if (!client
->req_opts
)