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 static int dhcp_client_set_iaid_duid(
358 sd_dhcp_client
*client
,
365 DHCP_CLIENT_DONT_DESTROY(client
);
369 assert_return(client
, -EINVAL
);
370 assert_return(duid_len
== 0 || duid
!= NULL
, -EINVAL
);
373 r
= dhcp_validate_duid_len(duid_type
, duid_len
);
378 zero(client
->client_id
);
379 client
->client_id
.type
= 255;
382 /* If IAID is not configured, generate it. */
384 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
385 client
->mac_addr_len
,
386 &client
->client_id
.ns
.iaid
);
390 client
->client_id
.ns
.iaid
= htobe32(iaid
);
394 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
395 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
396 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
397 } else if (duid_type
== DUID_TYPE_EN
) {
398 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
404 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
405 (append_iaid
? sizeof(client
->client_id
.ns
.iaid
) : 0);
407 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
408 log_dhcp_client(client
, "Configured IAID+DUID, restarting.");
409 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
410 sd_dhcp_client_start(client
);
416 int sd_dhcp_client_set_iaid_duid(
417 sd_dhcp_client
*client
,
422 return dhcp_client_set_iaid_duid(client
, iaid
, true, duid_type
, duid
, duid_len
);
425 int sd_dhcp_client_set_duid(
426 sd_dhcp_client
*client
,
430 return dhcp_client_set_iaid_duid(client
, 0, false, duid_type
, duid
, duid_len
);
433 int sd_dhcp_client_set_hostname(
434 sd_dhcp_client
*client
,
435 const char *hostname
) {
437 assert_return(client
, -EINVAL
);
439 /* Make sure hostnames qualify as DNS and as Linux hostnames */
441 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
444 return free_and_strdup(&client
->hostname
, hostname
);
447 int sd_dhcp_client_set_vendor_class_identifier(
448 sd_dhcp_client
*client
,
451 assert_return(client
, -EINVAL
);
453 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
456 int sd_dhcp_client_set_client_port(
457 sd_dhcp_client
*client
,
460 assert_return(client
, -EINVAL
);
467 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
468 assert_return(client
, -EINVAL
);
469 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
476 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
477 assert_return(client
, -EINVAL
);
479 if (!IN_SET(client
->state
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
480 return -EADDRNOTAVAIL
;
483 *ret
= client
->lease
;
488 static void client_notify(sd_dhcp_client
*client
, int event
) {
491 if (client
->callback
)
492 client
->callback(client
, event
, client
->userdata
);
495 static int client_initialize(sd_dhcp_client
*client
) {
496 assert_return(client
, -EINVAL
);
498 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
500 client
->fd
= asynchronous_close(client
->fd
);
502 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
504 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
505 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
506 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
510 client
->state
= DHCP_STATE_INIT
;
513 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
518 static void client_stop(sd_dhcp_client
*client
, int error
) {
522 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
523 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
524 log_dhcp_client(client
, "STOPPED");
526 log_dhcp_client(client
, "STOPPED: Unknown event");
528 client_notify(client
, error
);
530 client_initialize(client
);
533 static int client_message_init(
534 sd_dhcp_client
*client
,
538 size_t *_optoffset
) {
540 _cleanup_free_ DHCPPacket
*packet
= NULL
;
541 size_t optlen
, optoffset
, size
;
548 assert(client
->start_time
);
552 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
554 optlen
= DHCP_MIN_OPTIONS_SIZE
;
555 size
= sizeof(DHCPPacket
) + optlen
;
557 packet
= malloc0(size
);
561 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
562 client
->arp_type
, optlen
, &optoffset
);
566 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
567 refuse to issue an DHCP lease if 'secs' is set to zero */
568 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
571 assert(time_now
>= client
->start_time
);
573 /* seconds between sending first and last DISCOVER
574 * must always be strictly positive to deal with broken servers */
575 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
576 packet
->dhcp
.secs
= htobe16(secs
);
578 /* RFC2132 section 4.1
579 A client that cannot receive unicast IP datagrams until its protocol
580 software has been configured with an IP address SHOULD set the
581 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
582 DHCPREQUEST messages that client sends. The BROADCAST bit will
583 provide a hint to the DHCP server and BOOTP relay agent to broadcast
584 any messages to the client on the client's subnet.
586 Note: some interfaces needs this to be enabled, but some networks
587 needs this to be disabled as broadcasts are filteretd, so this
588 needs to be configurable */
589 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
590 packet
->dhcp
.flags
= htobe16(0x8000);
592 /* RFC2132 section 4.1.1:
593 The client MUST include its hardware address in the ’chaddr’ field, if
594 necessary for delivery of DHCP reply messages. Non-Ethernet
595 interfaces will leave 'chaddr' empty and use the client identifier
596 instead (eg, RFC 4390 section 2.1).
598 if (client
->arp_type
== ARPHRD_ETHER
)
599 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
601 /* If no client identifier exists, construct an RFC 4361-compliant one */
602 if (client
->client_id_len
== 0) {
605 client
->client_id
.type
= 255;
607 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
611 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
615 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
618 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
619 Identifier option is not set */
620 if (client
->client_id_len
) {
621 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
622 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
623 client
->client_id_len
,
629 /* RFC2131 section 3.5:
630 in its initial DHCPDISCOVER or DHCPREQUEST message, a
631 client may provide the server with a list of specific
632 parameters the client is interested in. If the client
633 includes a list of parameters in a DHCPDISCOVER message,
634 it MUST include that list in any subsequent DHCPREQUEST
638 /* RFC7844 section 3:
639 MAY contain the Parameter Request List option. */
640 /* NOTE: in case that there would be an option to do not send
641 * any PRL at all, the size should be checked before sending */
642 if (client
->req_opts_size
> 0) {
643 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
644 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
645 client
->req_opts_size
, client
->req_opts
);
650 /* RFC2131 section 3.5:
651 The client SHOULD include the ’maximum DHCP message size’ option to
652 let the server know how large the server may make its DHCP messages.
654 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
655 than the defined default size unless the Maximum Messge Size option
658 RFC3442 "Requirements to Avoid Sizing Constraints":
659 Because a full routing table can be quite large, the standard 576
660 octet maximum size for a DHCP message may be too short to contain
661 some legitimate Classless Static Route options. Because of this,
662 clients implementing the Classless Static Route option SHOULD send a
663 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
664 stack is capable of receiving larger IP datagrams. In this case, the
665 client SHOULD set the value of this option to at least the MTU of the
666 interface that the client is configuring. The client MAY set the
667 value of this option higher, up to the size of the largest UDP packet
668 it is prepared to accept. (Note that the value specified in the
669 Maximum DHCP Message Size option is the total maximum packet size,
670 including IP and UDP headers.)
672 /* RFC7844 section 3:
673 SHOULD NOT contain any other option. */
674 if (!client
->anonymize
) {
675 max_size
= htobe16(size
);
676 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
677 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
684 *_optoffset
= optoffset
;
685 *ret
= TAKE_PTR(packet
);
690 static int client_append_fqdn_option(
691 DHCPMessage
*message
,
696 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
699 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
700 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
701 buffer
[1] = 0; /* RCODE1 (deprecated) */
702 buffer
[2] = 0; /* RCODE2 (deprecated) */
704 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
706 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
707 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
712 static int dhcp_client_send_raw(
713 sd_dhcp_client
*client
,
717 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
718 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
720 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
724 static int client_send_discover(sd_dhcp_client
*client
) {
725 _cleanup_free_ DHCPPacket
*discover
= NULL
;
726 size_t optoffset
, optlen
;
730 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
732 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
733 &optlen
, &optoffset
);
737 /* the client may suggest values for the network address
738 and lease time in the DHCPDISCOVER message. The client may include
739 the ’requested IP address’ option to suggest that a particular IP
740 address be assigned, and may include the ’IP address lease time’
741 option to suggest the lease time it would like.
743 if (client
->last_addr
!= INADDR_ANY
) {
744 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
745 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
746 4, &client
->last_addr
);
751 if (client
->hostname
) {
752 /* According to RFC 4702 "clients that send the Client FQDN option in
753 their messages MUST NOT also send the Host Name option". Just send
754 one of the two depending on the hostname type.
756 if (dns_name_is_single_label(client
->hostname
)) {
757 /* it is unclear from RFC 2131 if client should send hostname in
758 DHCPDISCOVER but dhclient does and so we do as well
760 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
761 SD_DHCP_OPTION_HOST_NAME
,
762 strlen(client
->hostname
), client
->hostname
);
764 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
770 if (client
->vendor_class_identifier
) {
771 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
772 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
773 strlen(client
->vendor_class_identifier
),
774 client
->vendor_class_identifier
);
779 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
780 SD_DHCP_OPTION_END
, 0, NULL
);
784 /* We currently ignore:
785 The client SHOULD wait a random time between one and ten seconds to
786 desynchronize the use of DHCP at startup.
788 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
792 log_dhcp_client(client
, "DISCOVER");
797 static int client_send_request(sd_dhcp_client
*client
) {
798 _cleanup_free_ DHCPPacket
*request
= NULL
;
799 size_t optoffset
, optlen
;
804 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
808 switch (client
->state
) {
809 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
810 SELECTING should be REQUESTING)
813 case DHCP_STATE_REQUESTING
:
814 /* Client inserts the address of the selected server in ’server
815 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
816 filled in with the yiaddr value from the chosen DHCPOFFER.
819 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
820 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
821 4, &client
->lease
->server_address
);
825 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
826 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
827 4, &client
->lease
->address
);
833 case DHCP_STATE_INIT_REBOOT
:
834 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
835 option MUST be filled in with client’s notion of its previously
836 assigned address. ’ciaddr’ MUST be zero.
838 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
839 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
840 4, &client
->last_addr
);
845 case DHCP_STATE_RENEWING
:
846 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
847 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
848 client’s IP address.
851 case DHCP_STATE_REBINDING
:
852 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
853 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
854 client’s IP address.
856 This message MUST be broadcast to the 0xffffffff IP broadcast address.
858 request
->dhcp
.ciaddr
= client
->lease
->address
;
862 case DHCP_STATE_INIT
:
863 case DHCP_STATE_SELECTING
:
864 case DHCP_STATE_REBOOTING
:
865 case DHCP_STATE_BOUND
:
866 case DHCP_STATE_STOPPED
:
870 if (client
->hostname
) {
871 if (dns_name_is_single_label(client
->hostname
))
872 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
873 SD_DHCP_OPTION_HOST_NAME
,
874 strlen(client
->hostname
), client
->hostname
);
876 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
882 if (client
->vendor_class_identifier
) {
883 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
884 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
885 strlen(client
->vendor_class_identifier
),
886 client
->vendor_class_identifier
);
891 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
892 SD_DHCP_OPTION_END
, 0, NULL
);
896 if (client
->state
== DHCP_STATE_RENEWING
) {
897 r
= dhcp_network_send_udp_socket(client
->fd
,
898 client
->lease
->server_address
,
901 sizeof(DHCPMessage
) + optoffset
);
903 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
908 switch (client
->state
) {
910 case DHCP_STATE_REQUESTING
:
911 log_dhcp_client(client
, "REQUEST (requesting)");
914 case DHCP_STATE_INIT_REBOOT
:
915 log_dhcp_client(client
, "REQUEST (init-reboot)");
918 case DHCP_STATE_RENEWING
:
919 log_dhcp_client(client
, "REQUEST (renewing)");
922 case DHCP_STATE_REBINDING
:
923 log_dhcp_client(client
, "REQUEST (rebinding)");
927 log_dhcp_client(client
, "REQUEST (invalid)");
934 static int client_start(sd_dhcp_client
*client
);
936 static int client_timeout_resend(
941 sd_dhcp_client
*client
= userdata
;
942 DHCP_CLIENT_DONT_DESTROY(client
);
943 usec_t next_timeout
= 0;
950 assert(client
->event
);
952 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
956 switch (client
->state
) {
958 case DHCP_STATE_RENEWING
:
960 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
964 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
968 case DHCP_STATE_REBINDING
:
970 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
974 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
977 case DHCP_STATE_REBOOTING
:
978 /* start over as we did not receive a timely ack or nak */
979 r
= client_initialize(client
);
983 r
= client_start(client
);
987 log_dhcp_client(client
, "REBOOTED");
991 case DHCP_STATE_INIT
:
992 case DHCP_STATE_INIT_REBOOT
:
993 case DHCP_STATE_SELECTING
:
994 case DHCP_STATE_REQUESTING
:
995 case DHCP_STATE_BOUND
:
997 if (client
->attempt
< 64)
998 client
->attempt
*= 2;
1000 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
1004 case DHCP_STATE_STOPPED
:
1009 next_timeout
+= (random_u32() & 0x1fffff);
1011 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1013 r
= sd_event_add_time(client
->event
,
1014 &client
->timeout_resend
,
1015 clock_boottime_or_monotonic(),
1016 next_timeout
, 10 * USEC_PER_MSEC
,
1017 client_timeout_resend
, client
);
1021 r
= sd_event_source_set_priority(client
->timeout_resend
,
1022 client
->event_priority
);
1026 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1030 switch (client
->state
) {
1031 case DHCP_STATE_INIT
:
1032 r
= client_send_discover(client
);
1034 client
->state
= DHCP_STATE_SELECTING
;
1035 client
->attempt
= 1;
1037 if (client
->attempt
>= 64)
1043 case DHCP_STATE_SELECTING
:
1044 r
= client_send_discover(client
);
1045 if (r
< 0 && client
->attempt
>= 64)
1050 case DHCP_STATE_INIT_REBOOT
:
1051 case DHCP_STATE_REQUESTING
:
1052 case DHCP_STATE_RENEWING
:
1053 case DHCP_STATE_REBINDING
:
1054 r
= client_send_request(client
);
1055 if (r
< 0 && client
->attempt
>= 64)
1058 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1059 client
->state
= DHCP_STATE_REBOOTING
;
1061 client
->request_sent
= time_now
;
1065 case DHCP_STATE_REBOOTING
:
1066 case DHCP_STATE_BOUND
:
1070 case DHCP_STATE_STOPPED
:
1078 client_stop(client
, r
);
1080 /* Errors were dealt with when stopping the client, don't spill
1081 errors into the event loop handler */
1085 static int client_initialize_io_events(
1086 sd_dhcp_client
*client
,
1087 sd_event_io_handler_t io_callback
) {
1092 assert(client
->event
);
1094 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1095 client
->fd
, EPOLLIN
, io_callback
,
1100 r
= sd_event_source_set_priority(client
->receive_message
,
1101 client
->event_priority
);
1105 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1111 client_stop(client
, r
);
1116 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1121 assert(client
->event
);
1123 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1125 if (client
->start_delay
) {
1126 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1127 usec
+= client
->start_delay
;
1130 r
= sd_event_add_time(client
->event
,
1131 &client
->timeout_resend
,
1132 clock_boottime_or_monotonic(),
1134 client_timeout_resend
, client
);
1138 r
= sd_event_source_set_priority(client
->timeout_resend
,
1139 client
->event_priority
);
1143 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1149 client_stop(client
, r
);
1155 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1156 client_initialize_io_events(client
, io_callback
);
1157 client_initialize_time_events(client
);
1162 static int client_start_delayed(sd_dhcp_client
*client
) {
1165 assert_return(client
, -EINVAL
);
1166 assert_return(client
->event
, -EINVAL
);
1167 assert_return(client
->ifindex
> 0, -EINVAL
);
1168 assert_return(client
->fd
< 0, -EBUSY
);
1169 assert_return(client
->xid
== 0, -EINVAL
);
1170 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1172 client
->xid
= random_u32();
1174 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1175 client
->xid
, client
->mac_addr
,
1176 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1178 client_stop(client
, r
);
1183 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1184 client
->start_time
= now(clock_boottime_or_monotonic());
1186 return client_initialize_events(client
, client_receive_message_raw
);
1189 static int client_start(sd_dhcp_client
*client
) {
1190 client
->start_delay
= 0;
1191 return client_start_delayed(client
);
1194 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1195 sd_dhcp_client
*client
= userdata
;
1196 DHCP_CLIENT_DONT_DESTROY(client
);
1198 log_dhcp_client(client
, "EXPIRED");
1200 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1202 /* lease was lost, start over if not freed or stopped in callback */
1203 if (client
->state
!= DHCP_STATE_STOPPED
) {
1204 client_initialize(client
);
1205 client_start(client
);
1211 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1212 sd_dhcp_client
*client
= userdata
;
1213 DHCP_CLIENT_DONT_DESTROY(client
);
1218 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1219 client
->fd
= asynchronous_close(client
->fd
);
1221 client
->state
= DHCP_STATE_REBINDING
;
1222 client
->attempt
= 1;
1224 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1225 client
->xid
, client
->mac_addr
,
1226 client
->mac_addr_len
, client
->arp_type
,
1229 client_stop(client
, r
);
1234 return client_initialize_events(client
, client_receive_message_raw
);
1237 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1238 sd_dhcp_client
*client
= userdata
;
1239 DHCP_CLIENT_DONT_DESTROY(client
);
1241 client
->state
= DHCP_STATE_RENEWING
;
1242 client
->attempt
= 1;
1244 return client_initialize_time_events(client
);
1247 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1248 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1251 r
= dhcp_lease_new(&lease
);
1255 if (client
->client_id_len
) {
1256 r
= dhcp_lease_set_client_id(lease
,
1257 (uint8_t *) &client
->client_id
,
1258 client
->client_id_len
);
1263 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1264 if (r
!= DHCP_OFFER
) {
1265 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1269 lease
->next_server
= offer
->siaddr
;
1270 lease
->address
= offer
->yiaddr
;
1272 if (lease
->address
== 0 ||
1273 lease
->server_address
== 0 ||
1274 lease
->lifetime
== 0) {
1275 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1279 if (!lease
->have_subnet_mask
) {
1280 r
= dhcp_lease_set_default_subnet_mask(lease
);
1282 log_dhcp_client(client
,
1283 "received lease lacks subnet mask, "
1284 "and a fallback one cannot be generated, ignoring");
1289 sd_dhcp_lease_unref(client
->lease
);
1290 client
->lease
= TAKE_PTR(lease
);
1292 log_dhcp_client(client
, "OFFER");
1297 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1300 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1301 if (r
!= DHCP_FORCERENEW
)
1304 log_dhcp_client(client
, "FORCERENEW");
1309 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1310 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1311 _cleanup_free_
char *error_message
= NULL
;
1314 r
= dhcp_lease_new(&lease
);
1318 if (client
->client_id_len
) {
1319 r
= dhcp_lease_set_client_id(lease
,
1320 (uint8_t *) &client
->client_id
,
1321 client
->client_id_len
);
1326 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1327 if (r
== DHCP_NAK
) {
1328 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1329 return -EADDRNOTAVAIL
;
1332 if (r
!= DHCP_ACK
) {
1333 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1337 lease
->next_server
= ack
->siaddr
;
1339 lease
->address
= ack
->yiaddr
;
1341 if (lease
->address
== INADDR_ANY
||
1342 lease
->server_address
== INADDR_ANY
||
1343 lease
->lifetime
== 0) {
1344 log_dhcp_client(client
, "received lease lacks address, server "
1345 "address or lease lifetime, ignoring");
1349 if (lease
->subnet_mask
== INADDR_ANY
) {
1350 r
= dhcp_lease_set_default_subnet_mask(lease
);
1352 log_dhcp_client(client
,
1353 "received lease lacks subnet mask, "
1354 "and a fallback one cannot be generated, ignoring");
1359 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1360 if (client
->lease
) {
1361 if (client
->lease
->address
!= lease
->address
||
1362 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1363 client
->lease
->router
!= lease
->router
) {
1364 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1366 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1368 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1371 client
->lease
= TAKE_PTR(lease
);
1373 log_dhcp_client(client
, "ACK");
1378 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1380 assert(client
->request_sent
);
1381 assert(lifetime
> 0);
1388 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1389 + (random_u32() & 0x1fffff);
1392 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1394 uint64_t lifetime_timeout
;
1395 uint64_t t2_timeout
;
1396 uint64_t t1_timeout
;
1397 char time_string
[FORMAT_TIMESPAN_MAX
];
1401 assert(client
->event
);
1402 assert(client
->lease
);
1403 assert(client
->lease
->lifetime
);
1405 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1406 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1407 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1409 /* don't set timers for infinite leases */
1410 if (client
->lease
->lifetime
== 0xffffffff)
1413 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1416 assert(client
->request_sent
<= time_now
);
1418 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1419 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1420 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1421 /* both T1 and T2 are given */
1422 if (client
->lease
->t1
< client
->lease
->t2
&&
1423 client
->lease
->t2
< client
->lease
->lifetime
) {
1424 /* they are both valid */
1425 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1426 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1429 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1430 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1431 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1432 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1434 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1435 /* only T2 is given, and it is valid */
1436 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1437 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1438 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1439 if (t2_timeout
<= t1_timeout
) {
1440 /* the computed T1 would be invalid, so discard T2 */
1441 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1442 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1444 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1445 /* only T1 is given, and it is valid */
1446 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1447 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1448 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1449 if (t2_timeout
<= t1_timeout
) {
1450 /* the computed T2 would be invalid, so discard T1 */
1451 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1452 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1455 /* fall back to the default timeouts */
1456 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1457 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1458 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1459 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1462 /* arm lifetime timeout */
1463 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1464 clock_boottime_or_monotonic(),
1465 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1466 client_timeout_expire
, client
);
1470 r
= sd_event_source_set_priority(client
->timeout_expire
,
1471 client
->event_priority
);
1475 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1479 log_dhcp_client(client
, "lease expires in %s",
1480 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1482 /* don't arm earlier timeouts if this has already expired */
1483 if (lifetime_timeout
<= time_now
)
1486 /* arm T2 timeout */
1487 r
= sd_event_add_time(client
->event
,
1488 &client
->timeout_t2
,
1489 clock_boottime_or_monotonic(),
1492 client_timeout_t2
, client
);
1496 r
= sd_event_source_set_priority(client
->timeout_t2
,
1497 client
->event_priority
);
1501 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1505 log_dhcp_client(client
, "T2 expires in %s",
1506 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1508 /* don't arm earlier timeout if this has already expired */
1509 if (t2_timeout
<= time_now
)
1512 /* arm T1 timeout */
1513 r
= sd_event_add_time(client
->event
,
1514 &client
->timeout_t1
,
1515 clock_boottime_or_monotonic(),
1516 t1_timeout
, 10 * USEC_PER_MSEC
,
1517 client_timeout_t1
, client
);
1521 r
= sd_event_source_set_priority(client
->timeout_t1
,
1522 client
->event_priority
);
1526 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1530 log_dhcp_client(client
, "T1 expires in %s",
1531 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1536 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1537 DHCP_CLIENT_DONT_DESTROY(client
);
1538 char time_string
[FORMAT_TIMESPAN_MAX
];
1539 int r
= 0, notify_event
= 0;
1542 assert(client
->event
);
1545 switch (client
->state
) {
1546 case DHCP_STATE_SELECTING
:
1548 r
= client_handle_offer(client
, message
, len
);
1551 client
->timeout_resend
=
1552 sd_event_source_unref(client
->timeout_resend
);
1554 client
->state
= DHCP_STATE_REQUESTING
;
1555 client
->attempt
= 1;
1557 r
= sd_event_add_time(client
->event
,
1558 &client
->timeout_resend
,
1559 clock_boottime_or_monotonic(),
1561 client_timeout_resend
, client
);
1565 r
= sd_event_source_set_priority(client
->timeout_resend
,
1566 client
->event_priority
);
1570 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1573 } else if (r
== -ENOMSG
)
1574 /* invalid message, let's ignore it */
1579 case DHCP_STATE_REBOOTING
:
1580 case DHCP_STATE_REQUESTING
:
1581 case DHCP_STATE_RENEWING
:
1582 case DHCP_STATE_REBINDING
:
1584 r
= client_handle_ack(client
, message
, len
);
1586 client
->start_delay
= 0;
1587 client
->timeout_resend
=
1588 sd_event_source_unref(client
->timeout_resend
);
1589 client
->receive_message
=
1590 sd_event_source_unref(client
->receive_message
);
1591 client
->fd
= asynchronous_close(client
->fd
);
1593 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1594 DHCP_STATE_REBOOTING
))
1595 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1596 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1599 client
->state
= DHCP_STATE_BOUND
;
1600 client
->attempt
= 1;
1602 client
->last_addr
= client
->lease
->address
;
1604 r
= client_set_lease_timeouts(client
);
1606 log_dhcp_client(client
, "could not set lease timeouts");
1610 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1612 log_dhcp_client(client
, "could not bind UDP socket");
1618 client_initialize_io_events(client
, client_receive_message_udp
);
1621 client_notify(client
, notify_event
);
1622 if (client
->state
== DHCP_STATE_STOPPED
)
1626 } else if (r
== -EADDRNOTAVAIL
) {
1627 /* got a NAK, let's restart the client */
1628 client
->timeout_resend
=
1629 sd_event_source_unref(client
->timeout_resend
);
1631 r
= client_initialize(client
);
1635 r
= client_start_delayed(client
);
1639 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1640 client
->start_delay
, USEC_PER_SEC
));
1642 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1643 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1646 } else if (r
== -ENOMSG
)
1647 /* invalid message, let's ignore it */
1652 case DHCP_STATE_BOUND
:
1653 r
= client_handle_forcerenew(client
, message
, len
);
1655 r
= client_timeout_t1(NULL
, 0, client
);
1658 } else if (r
== -ENOMSG
)
1659 /* invalid message, let's ignore it */
1664 case DHCP_STATE_INIT
:
1665 case DHCP_STATE_INIT_REBOOT
:
1669 case DHCP_STATE_STOPPED
:
1676 client_stop(client
, r
);
1681 static int client_receive_message_udp(
1687 sd_dhcp_client
*client
= userdata
;
1688 _cleanup_free_ DHCPMessage
*message
= NULL
;
1689 const struct ether_addr zero_mac
= {};
1690 const struct ether_addr
*expected_chaddr
= NULL
;
1691 uint8_t expected_hlen
= 0;
1692 ssize_t len
, buflen
;
1697 buflen
= next_datagram_size_fd(fd
);
1701 message
= malloc0(buflen
);
1705 len
= recv(fd
, message
, buflen
, 0);
1707 if (IN_SET(errno
, EAGAIN
, EINTR
))
1710 return log_dhcp_client_errno(client
, errno
,
1711 "Could not receive message from UDP socket: %m");
1713 if ((size_t) len
< sizeof(DHCPMessage
)) {
1714 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1718 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1719 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1723 if (message
->op
!= BOOTREPLY
) {
1724 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1728 if (message
->htype
!= client
->arp_type
) {
1729 log_dhcp_client(client
, "Packet type does not match client type");
1733 if (client
->arp_type
== ARPHRD_ETHER
) {
1734 expected_hlen
= ETH_ALEN
;
1735 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1737 /* Non-Ethernet links expect zero chaddr */
1739 expected_chaddr
= &zero_mac
;
1742 if (message
->hlen
!= expected_hlen
) {
1743 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1747 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1748 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1752 if (client
->state
!= DHCP_STATE_BOUND
&&
1753 be32toh(message
->xid
) != client
->xid
) {
1754 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1755 so ignore the xid in this case */
1756 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1757 be32toh(message
->xid
), client
->xid
);
1761 return client_handle_message(client
, message
, len
);
1764 static int client_receive_message_raw(
1770 sd_dhcp_client
*client
= userdata
;
1771 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1772 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1773 struct iovec iov
= {};
1774 struct msghdr msg
= {
1777 .msg_control
= cmsgbuf
,
1778 .msg_controllen
= sizeof(cmsgbuf
),
1780 struct cmsghdr
*cmsg
;
1781 bool checksum
= true;
1782 ssize_t buflen
, len
;
1788 buflen
= next_datagram_size_fd(fd
);
1792 packet
= malloc0(buflen
);
1796 iov
.iov_base
= packet
;
1797 iov
.iov_len
= buflen
;
1799 len
= recvmsg(fd
, &msg
, 0);
1801 if (IN_SET(errno
, EAGAIN
, EINTR
))
1804 return log_dhcp_client_errno(client
, errno
,
1805 "Could not receive message from raw socket: %m");
1806 } else if ((size_t)len
< sizeof(DHCPPacket
))
1809 CMSG_FOREACH(cmsg
, &msg
) {
1810 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1811 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1812 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1813 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1815 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1820 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1824 len
-= DHCP_IP_UDP_SIZE
;
1826 return client_handle_message(client
, &packet
->dhcp
, len
);
1829 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1832 assert_return(client
, -EINVAL
);
1834 r
= client_initialize(client
);
1838 /* RFC7844 section 3.3:
1839 SHOULD perform a complete four-way handshake, starting with a
1840 DHCPDISCOVER, to obtain a new address lease. If the client can
1841 ascertain that this is exactly the same network to which it was
1842 previously connected, and if the link-layer address did not change,
1843 the client MAY issue a DHCPREQUEST to try to reclaim the current
1845 if (client
->last_addr
&& !client
->anonymize
)
1846 client
->state
= DHCP_STATE_INIT_REBOOT
;
1848 r
= client_start(client
);
1850 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1855 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1856 DHCP_CLIENT_DONT_DESTROY(client
);
1858 assert_return(client
, -EINVAL
);
1860 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1861 client
->state
= DHCP_STATE_STOPPED
;
1866 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1869 assert_return(client
, -EINVAL
);
1870 assert_return(!client
->event
, -EBUSY
);
1873 client
->event
= sd_event_ref(event
);
1875 r
= sd_event_default(&client
->event
);
1880 client
->event_priority
= priority
;
1885 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1886 assert_return(client
, -EINVAL
);
1888 client
->event
= sd_event_unref(client
->event
);
1893 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1894 assert_return(client
, NULL
);
1896 return client
->event
;
1899 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1904 assert(client
->n_ref
>= 1);
1910 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1915 assert(client
->n_ref
>= 1);
1918 if (client
->n_ref
> 0)
1921 log_dhcp_client(client
, "FREE");
1923 client_initialize(client
);
1925 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1927 sd_dhcp_client_detach_event(client
);
1929 sd_dhcp_lease_unref(client
->lease
);
1931 free(client
->req_opts
);
1932 free(client
->hostname
);
1933 free(client
->vendor_class_identifier
);
1934 return mfree(client
);
1937 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1938 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1940 assert_return(ret
, -EINVAL
);
1942 client
= new0(sd_dhcp_client
, 1);
1947 client
->state
= DHCP_STATE_INIT
;
1948 client
->ifindex
= -1;
1950 client
->attempt
= 1;
1951 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1952 client
->port
= DHCP_PORT_CLIENT
;
1954 client
->anonymize
= !!anonymize
;
1955 /* NOTE: this could be moved to a function. */
1957 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1958 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1960 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1961 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1963 if (!client
->req_opts
)
1966 *ret
= TAKE_PTR(client
);