1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright (C) 2013 Intel Corporation. All rights reserved.
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <net/ethernet.h>
23 #include <net/if_arp.h>
27 #include <sys/ioctl.h>
28 #include <linux/if_infiniband.h>
30 #include "sd-dhcp-client.h"
32 #include "alloc-util.h"
34 #include "dhcp-identifier.h"
35 #include "dhcp-internal.h"
36 #include "dhcp-lease-internal.h"
37 #include "dhcp-protocol.h"
38 #include "dns-domain.h"
39 #include "hostname-util.h"
40 #include "random-util.h"
41 #include "string-util.h"
44 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
45 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
47 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
48 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
50 struct sd_dhcp_client
{
56 sd_event_source
*timeout_resend
;
60 union sockaddr_union link
;
61 sd_event_source
*receive_message
;
62 bool request_broadcast
;
64 size_t req_opts_allocated
;
68 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
75 /* 0: Generic (non-LL) (RFC 2132) */
76 uint8_t data
[MAX_CLIENT_ID_LEN
];
79 /* 1: Ethernet Link-Layer (RFC 2132) */
80 uint8_t haddr
[ETH_ALEN
];
83 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
87 /* 255: Node-specific (RFC 4361) */
92 uint8_t data
[MAX_CLIENT_ID_LEN
];
98 char *vendor_class_identifier
;
102 unsigned int attempt
;
104 sd_event_source
*timeout_t1
;
105 sd_event_source
*timeout_t2
;
106 sd_event_source
*timeout_expire
;
107 sd_dhcp_client_callback_t callback
;
109 sd_dhcp_lease
*lease
;
113 static const uint8_t default_req_opts
[] = {
114 SD_DHCP_OPTION_SUBNET_MASK
,
115 SD_DHCP_OPTION_ROUTER
,
116 SD_DHCP_OPTION_HOST_NAME
,
117 SD_DHCP_OPTION_DOMAIN_NAME
,
118 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
121 /* RFC7844 section 3:
122 MAY contain the Parameter Request List option.
124 The client intending to protect its privacy SHOULD only request a
125 minimal number of options in the PRL and SHOULD also randomly shuffle
126 the ordering of option codes in the PRL. If this random ordering
127 cannot be implemented, the client MAY order the option codes in the
128 PRL by option code number (lowest to highest).
130 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
131 static const uint8_t default_req_opts_anonymize
[] = {
132 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
133 SD_DHCP_OPTION_ROUTER
, /* 3 */
134 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
135 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
136 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
137 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
138 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
139 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
140 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
141 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
142 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
143 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
144 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
147 static int client_receive_message_raw(
152 static int client_receive_message_udp(
157 static void client_stop(sd_dhcp_client
*client
, int error
);
159 int sd_dhcp_client_set_callback(
160 sd_dhcp_client
*client
,
161 sd_dhcp_client_callback_t cb
,
164 assert_return(client
, -EINVAL
);
166 client
->callback
= cb
;
167 client
->userdata
= userdata
;
172 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
173 assert_return(client
, -EINVAL
);
175 client
->request_broadcast
= !!broadcast
;
180 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
183 assert_return(client
, -EINVAL
);
184 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
188 case SD_DHCP_OPTION_PAD
:
189 case SD_DHCP_OPTION_OVERLOAD
:
190 case SD_DHCP_OPTION_MESSAGE_TYPE
:
191 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
192 case SD_DHCP_OPTION_END
:
199 for (i
= 0; i
< client
->req_opts_size
; i
++)
200 if (client
->req_opts
[i
] == option
)
203 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
204 client
->req_opts_size
+ 1))
207 client
->req_opts
[client
->req_opts_size
++] = option
;
212 int sd_dhcp_client_set_request_address(
213 sd_dhcp_client
*client
,
214 const struct in_addr
*last_addr
) {
216 assert_return(client
, -EINVAL
);
217 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
220 client
->last_addr
= last_addr
->s_addr
;
222 client
->last_addr
= INADDR_ANY
;
227 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
229 assert_return(client
, -EINVAL
);
230 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
231 assert_return(ifindex
> 0, -EINVAL
);
233 client
->ifindex
= ifindex
;
237 int sd_dhcp_client_set_mac(
238 sd_dhcp_client
*client
,
243 DHCP_CLIENT_DONT_DESTROY(client
);
244 bool need_restart
= false;
246 assert_return(client
, -EINVAL
);
247 assert_return(addr
, -EINVAL
);
248 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
249 assert_return(arp_type
> 0, -EINVAL
);
251 if (arp_type
== ARPHRD_ETHER
)
252 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
253 else if (arp_type
== ARPHRD_INFINIBAND
)
254 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
258 if (client
->mac_addr_len
== addr_len
&&
259 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
262 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
263 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
265 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
268 memcpy(&client
->mac_addr
, addr
, addr_len
);
269 client
->mac_addr_len
= addr_len
;
270 client
->arp_type
= arp_type
;
272 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
273 sd_dhcp_client_start(client
);
278 int sd_dhcp_client_get_client_id(
279 sd_dhcp_client
*client
,
281 const uint8_t **data
,
284 assert_return(client
, -EINVAL
);
285 assert_return(type
, -EINVAL
);
286 assert_return(data
, -EINVAL
);
287 assert_return(data_len
, -EINVAL
);
292 if (client
->client_id_len
) {
293 *type
= client
->client_id
.type
;
294 *data
= client
->client_id
.raw
.data
;
295 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
301 int sd_dhcp_client_set_client_id(
302 sd_dhcp_client
*client
,
307 DHCP_CLIENT_DONT_DESTROY(client
);
308 bool need_restart
= false;
310 assert_return(client
, -EINVAL
);
311 assert_return(data
, -EINVAL
);
312 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
317 if (data_len
!= ETH_ALEN
)
321 case ARPHRD_INFINIBAND
:
322 if (data_len
!= INFINIBAND_ALEN
)
330 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
331 client
->client_id
.type
== type
&&
332 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
335 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
336 log_dhcp_client(client
, "Changing client ID on running DHCP "
337 "client, restarting");
339 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
342 client
->client_id
.type
= type
;
343 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
344 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
346 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
347 sd_dhcp_client_start(client
);
353 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
354 * without further modification. Otherwise, if duid_type is supported, DUID
355 * is set based on that type. Otherwise, an error is returned.
357 int sd_dhcp_client_set_iaid_duid(
358 sd_dhcp_client
*client
,
364 DHCP_CLIENT_DONT_DESTROY(client
);
368 assert_return(client
, -EINVAL
);
369 assert_return(duid_len
== 0 || duid
!= NULL
, -EINVAL
);
372 r
= dhcp_validate_duid_len(duid_type
, duid_len
);
377 zero(client
->client_id
);
378 client
->client_id
.type
= 255;
380 /* If IAID is not configured, generate it. */
382 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
383 client
->mac_addr_len
,
384 &client
->client_id
.ns
.iaid
);
388 client
->client_id
.ns
.iaid
= htobe32(iaid
);
391 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
392 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
393 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
394 } else if (duid_type
== DUID_TYPE_EN
) {
395 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
401 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
402 sizeof(client
->client_id
.ns
.iaid
);
404 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
405 log_dhcp_client(client
, "Configured IAID+DUID, restarting.");
406 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
407 sd_dhcp_client_start(client
);
413 int sd_dhcp_client_set_hostname(
414 sd_dhcp_client
*client
,
415 const char *hostname
) {
417 assert_return(client
, -EINVAL
);
419 /* Make sure hostnames qualify as DNS and as Linux hostnames */
421 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
424 return free_and_strdup(&client
->hostname
, hostname
);
427 int sd_dhcp_client_set_vendor_class_identifier(
428 sd_dhcp_client
*client
,
431 assert_return(client
, -EINVAL
);
433 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
436 int sd_dhcp_client_set_client_port(
437 sd_dhcp_client
*client
,
440 assert_return(client
, -EINVAL
);
447 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
448 assert_return(client
, -EINVAL
);
449 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
456 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
457 assert_return(client
, -EINVAL
);
459 if (!IN_SET(client
->state
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
460 return -EADDRNOTAVAIL
;
463 *ret
= client
->lease
;
468 static void client_notify(sd_dhcp_client
*client
, int event
) {
471 if (client
->callback
)
472 client
->callback(client
, event
, client
->userdata
);
475 static int client_initialize(sd_dhcp_client
*client
) {
476 assert_return(client
, -EINVAL
);
478 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
480 client
->fd
= asynchronous_close(client
->fd
);
482 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
484 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
485 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
486 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
490 client
->state
= DHCP_STATE_INIT
;
493 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
498 static void client_stop(sd_dhcp_client
*client
, int error
) {
502 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
503 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
504 log_dhcp_client(client
, "STOPPED");
506 log_dhcp_client(client
, "STOPPED: Unknown event");
508 client_notify(client
, error
);
510 client_initialize(client
);
513 static int client_message_init(
514 sd_dhcp_client
*client
,
518 size_t *_optoffset
) {
520 _cleanup_free_ DHCPPacket
*packet
= NULL
;
521 size_t optlen
, optoffset
, size
;
528 assert(client
->start_time
);
532 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
534 optlen
= DHCP_MIN_OPTIONS_SIZE
;
535 size
= sizeof(DHCPPacket
) + optlen
;
537 packet
= malloc0(size
);
541 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
542 client
->arp_type
, optlen
, &optoffset
);
546 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
547 refuse to issue an DHCP lease if 'secs' is set to zero */
548 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
551 assert(time_now
>= client
->start_time
);
553 /* seconds between sending first and last DISCOVER
554 * must always be strictly positive to deal with broken servers */
555 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
556 packet
->dhcp
.secs
= htobe16(secs
);
558 /* RFC2132 section 4.1
559 A client that cannot receive unicast IP datagrams until its protocol
560 software has been configured with an IP address SHOULD set the
561 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
562 DHCPREQUEST messages that client sends. The BROADCAST bit will
563 provide a hint to the DHCP server and BOOTP relay agent to broadcast
564 any messages to the client on the client's subnet.
566 Note: some interfaces needs this to be enabled, but some networks
567 needs this to be disabled as broadcasts are filteretd, so this
568 needs to be configurable */
569 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
570 packet
->dhcp
.flags
= htobe16(0x8000);
572 /* RFC2132 section 4.1.1:
573 The client MUST include its hardware address in the ’chaddr’ field, if
574 necessary for delivery of DHCP reply messages. Non-Ethernet
575 interfaces will leave 'chaddr' empty and use the client identifier
576 instead (eg, RFC 4390 section 2.1).
578 if (client
->arp_type
== ARPHRD_ETHER
)
579 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
581 /* If no client identifier exists, construct an RFC 4361-compliant one */
582 if (client
->client_id_len
== 0) {
585 client
->client_id
.type
= 255;
587 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
591 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
595 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
598 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
599 Identifier option is not set */
600 if (client
->client_id_len
) {
601 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
602 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
603 client
->client_id_len
,
609 /* RFC2131 section 3.5:
610 in its initial DHCPDISCOVER or DHCPREQUEST message, a
611 client may provide the server with a list of specific
612 parameters the client is interested in. If the client
613 includes a list of parameters in a DHCPDISCOVER message,
614 it MUST include that list in any subsequent DHCPREQUEST
618 /* RFC7844 section 3:
619 MAY contain the Parameter Request List option. */
620 /* NOTE: in case that there would be an option to do not send
621 * any PRL at all, the size should be checked before sending */
622 if (client
->req_opts_size
> 0) {
623 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
624 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
625 client
->req_opts_size
, client
->req_opts
);
630 /* RFC2131 section 3.5:
631 The client SHOULD include the ’maximum DHCP message size’ option to
632 let the server know how large the server may make its DHCP messages.
634 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
635 than the defined default size unless the Maximum Messge Size option
638 RFC3442 "Requirements to Avoid Sizing Constraints":
639 Because a full routing table can be quite large, the standard 576
640 octet maximum size for a DHCP message may be too short to contain
641 some legitimate Classless Static Route options. Because of this,
642 clients implementing the Classless Static Route option SHOULD send a
643 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
644 stack is capable of receiving larger IP datagrams. In this case, the
645 client SHOULD set the value of this option to at least the MTU of the
646 interface that the client is configuring. The client MAY set the
647 value of this option higher, up to the size of the largest UDP packet
648 it is prepared to accept. (Note that the value specified in the
649 Maximum DHCP Message Size option is the total maximum packet size,
650 including IP and UDP headers.)
652 /* RFC7844 section 3:
653 SHOULD NOT contain any other option. */
654 if (!client
->anonymize
) {
655 max_size
= htobe16(size
);
656 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
657 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
664 *_optoffset
= optoffset
;
671 static int client_append_fqdn_option(
672 DHCPMessage
*message
,
677 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
680 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
681 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
682 buffer
[1] = 0; /* RCODE1 (deprecated) */
683 buffer
[2] = 0; /* RCODE2 (deprecated) */
685 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
687 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
688 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
693 static int dhcp_client_send_raw(
694 sd_dhcp_client
*client
,
698 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
699 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
701 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
705 static int client_send_discover(sd_dhcp_client
*client
) {
706 _cleanup_free_ DHCPPacket
*discover
= NULL
;
707 size_t optoffset
, optlen
;
711 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, 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
829 client’s IP address.
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
836 client’s IP address.
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 (IN_SET(errno
, EAGAIN
, 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 (IN_SET(errno
, EAGAIN
, 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
)