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
;
691 static int client_append_fqdn_option(
692 DHCPMessage
*message
,
697 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
700 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
701 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
702 buffer
[1] = 0; /* RCODE1 (deprecated) */
703 buffer
[2] = 0; /* RCODE2 (deprecated) */
705 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
707 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
708 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
713 static int dhcp_client_send_raw(
714 sd_dhcp_client
*client
,
718 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
719 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
721 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
725 static int client_send_discover(sd_dhcp_client
*client
) {
726 _cleanup_free_ DHCPPacket
*discover
= NULL
;
727 size_t optoffset
, optlen
;
731 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
733 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
734 &optlen
, &optoffset
);
738 /* the client may suggest values for the network address
739 and lease time in the DHCPDISCOVER message. The client may include
740 the ’requested IP address’ option to suggest that a particular IP
741 address be assigned, and may include the ’IP address lease time’
742 option to suggest the lease time it would like.
744 if (client
->last_addr
!= INADDR_ANY
) {
745 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
746 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
747 4, &client
->last_addr
);
752 if (client
->hostname
) {
753 /* According to RFC 4702 "clients that send the Client FQDN option in
754 their messages MUST NOT also send the Host Name option". Just send
755 one of the two depending on the hostname type.
757 if (dns_name_is_single_label(client
->hostname
)) {
758 /* it is unclear from RFC 2131 if client should send hostname in
759 DHCPDISCOVER but dhclient does and so we do as well
761 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
762 SD_DHCP_OPTION_HOST_NAME
,
763 strlen(client
->hostname
), client
->hostname
);
765 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
771 if (client
->vendor_class_identifier
) {
772 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
773 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
774 strlen(client
->vendor_class_identifier
),
775 client
->vendor_class_identifier
);
780 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
781 SD_DHCP_OPTION_END
, 0, NULL
);
785 /* We currently ignore:
786 The client SHOULD wait a random time between one and ten seconds to
787 desynchronize the use of DHCP at startup.
789 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
793 log_dhcp_client(client
, "DISCOVER");
798 static int client_send_request(sd_dhcp_client
*client
) {
799 _cleanup_free_ DHCPPacket
*request
= NULL
;
800 size_t optoffset
, optlen
;
805 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
809 switch (client
->state
) {
810 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
811 SELECTING should be REQUESTING)
814 case DHCP_STATE_REQUESTING
:
815 /* Client inserts the address of the selected server in ’server
816 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
817 filled in with the yiaddr value from the chosen DHCPOFFER.
820 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
821 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
822 4, &client
->lease
->server_address
);
826 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
827 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
828 4, &client
->lease
->address
);
834 case DHCP_STATE_INIT_REBOOT
:
835 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
836 option MUST be filled in with client’s notion of its previously
837 assigned address. ’ciaddr’ MUST be zero.
839 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
840 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
841 4, &client
->last_addr
);
846 case DHCP_STATE_RENEWING
:
847 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
848 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
849 client’s IP address.
852 case DHCP_STATE_REBINDING
:
853 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
854 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
855 client’s IP address.
857 This message MUST be broadcast to the 0xffffffff IP broadcast address.
859 request
->dhcp
.ciaddr
= client
->lease
->address
;
863 case DHCP_STATE_INIT
:
864 case DHCP_STATE_SELECTING
:
865 case DHCP_STATE_REBOOTING
:
866 case DHCP_STATE_BOUND
:
867 case DHCP_STATE_STOPPED
:
871 if (client
->hostname
) {
872 if (dns_name_is_single_label(client
->hostname
))
873 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
874 SD_DHCP_OPTION_HOST_NAME
,
875 strlen(client
->hostname
), client
->hostname
);
877 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
883 if (client
->vendor_class_identifier
) {
884 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
885 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
886 strlen(client
->vendor_class_identifier
),
887 client
->vendor_class_identifier
);
892 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
893 SD_DHCP_OPTION_END
, 0, NULL
);
897 if (client
->state
== DHCP_STATE_RENEWING
) {
898 r
= dhcp_network_send_udp_socket(client
->fd
,
899 client
->lease
->server_address
,
902 sizeof(DHCPMessage
) + optoffset
);
904 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
909 switch (client
->state
) {
911 case DHCP_STATE_REQUESTING
:
912 log_dhcp_client(client
, "REQUEST (requesting)");
915 case DHCP_STATE_INIT_REBOOT
:
916 log_dhcp_client(client
, "REQUEST (init-reboot)");
919 case DHCP_STATE_RENEWING
:
920 log_dhcp_client(client
, "REQUEST (renewing)");
923 case DHCP_STATE_REBINDING
:
924 log_dhcp_client(client
, "REQUEST (rebinding)");
928 log_dhcp_client(client
, "REQUEST (invalid)");
935 static int client_start(sd_dhcp_client
*client
);
937 static int client_timeout_resend(
942 sd_dhcp_client
*client
= userdata
;
943 DHCP_CLIENT_DONT_DESTROY(client
);
944 usec_t next_timeout
= 0;
951 assert(client
->event
);
953 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
957 switch (client
->state
) {
959 case DHCP_STATE_RENEWING
:
961 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
965 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
969 case DHCP_STATE_REBINDING
:
971 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
975 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
978 case DHCP_STATE_REBOOTING
:
979 /* start over as we did not receive a timely ack or nak */
980 r
= client_initialize(client
);
984 r
= client_start(client
);
988 log_dhcp_client(client
, "REBOOTED");
992 case DHCP_STATE_INIT
:
993 case DHCP_STATE_INIT_REBOOT
:
994 case DHCP_STATE_SELECTING
:
995 case DHCP_STATE_REQUESTING
:
996 case DHCP_STATE_BOUND
:
998 if (client
->attempt
< 64)
999 client
->attempt
*= 2;
1001 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
1005 case DHCP_STATE_STOPPED
:
1010 next_timeout
+= (random_u32() & 0x1fffff);
1012 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1014 r
= sd_event_add_time(client
->event
,
1015 &client
->timeout_resend
,
1016 clock_boottime_or_monotonic(),
1017 next_timeout
, 10 * USEC_PER_MSEC
,
1018 client_timeout_resend
, client
);
1022 r
= sd_event_source_set_priority(client
->timeout_resend
,
1023 client
->event_priority
);
1027 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1031 switch (client
->state
) {
1032 case DHCP_STATE_INIT
:
1033 r
= client_send_discover(client
);
1035 client
->state
= DHCP_STATE_SELECTING
;
1036 client
->attempt
= 1;
1038 if (client
->attempt
>= 64)
1044 case DHCP_STATE_SELECTING
:
1045 r
= client_send_discover(client
);
1046 if (r
< 0 && client
->attempt
>= 64)
1051 case DHCP_STATE_INIT_REBOOT
:
1052 case DHCP_STATE_REQUESTING
:
1053 case DHCP_STATE_RENEWING
:
1054 case DHCP_STATE_REBINDING
:
1055 r
= client_send_request(client
);
1056 if (r
< 0 && client
->attempt
>= 64)
1059 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1060 client
->state
= DHCP_STATE_REBOOTING
;
1062 client
->request_sent
= time_now
;
1066 case DHCP_STATE_REBOOTING
:
1067 case DHCP_STATE_BOUND
:
1071 case DHCP_STATE_STOPPED
:
1079 client_stop(client
, r
);
1081 /* Errors were dealt with when stopping the client, don't spill
1082 errors into the event loop handler */
1086 static int client_initialize_io_events(
1087 sd_dhcp_client
*client
,
1088 sd_event_io_handler_t io_callback
) {
1093 assert(client
->event
);
1095 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1096 client
->fd
, EPOLLIN
, io_callback
,
1101 r
= sd_event_source_set_priority(client
->receive_message
,
1102 client
->event_priority
);
1106 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1112 client_stop(client
, r
);
1117 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1122 assert(client
->event
);
1124 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1126 if (client
->start_delay
) {
1127 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1128 usec
+= client
->start_delay
;
1131 r
= sd_event_add_time(client
->event
,
1132 &client
->timeout_resend
,
1133 clock_boottime_or_monotonic(),
1135 client_timeout_resend
, client
);
1139 r
= sd_event_source_set_priority(client
->timeout_resend
,
1140 client
->event_priority
);
1144 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1150 client_stop(client
, r
);
1156 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1157 client_initialize_io_events(client
, io_callback
);
1158 client_initialize_time_events(client
);
1163 static int client_start_delayed(sd_dhcp_client
*client
) {
1166 assert_return(client
, -EINVAL
);
1167 assert_return(client
->event
, -EINVAL
);
1168 assert_return(client
->ifindex
> 0, -EINVAL
);
1169 assert_return(client
->fd
< 0, -EBUSY
);
1170 assert_return(client
->xid
== 0, -EINVAL
);
1171 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1173 client
->xid
= random_u32();
1175 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1176 client
->xid
, client
->mac_addr
,
1177 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1179 client_stop(client
, r
);
1184 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1185 client
->start_time
= now(clock_boottime_or_monotonic());
1187 return client_initialize_events(client
, client_receive_message_raw
);
1190 static int client_start(sd_dhcp_client
*client
) {
1191 client
->start_delay
= 0;
1192 return client_start_delayed(client
);
1195 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1196 sd_dhcp_client
*client
= userdata
;
1197 DHCP_CLIENT_DONT_DESTROY(client
);
1199 log_dhcp_client(client
, "EXPIRED");
1201 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1203 /* lease was lost, start over if not freed or stopped in callback */
1204 if (client
->state
!= DHCP_STATE_STOPPED
) {
1205 client_initialize(client
);
1206 client_start(client
);
1212 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1213 sd_dhcp_client
*client
= userdata
;
1214 DHCP_CLIENT_DONT_DESTROY(client
);
1219 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1220 client
->fd
= asynchronous_close(client
->fd
);
1222 client
->state
= DHCP_STATE_REBINDING
;
1223 client
->attempt
= 1;
1225 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1226 client
->xid
, client
->mac_addr
,
1227 client
->mac_addr_len
, client
->arp_type
,
1230 client_stop(client
, r
);
1235 return client_initialize_events(client
, client_receive_message_raw
);
1238 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1239 sd_dhcp_client
*client
= userdata
;
1240 DHCP_CLIENT_DONT_DESTROY(client
);
1242 client
->state
= DHCP_STATE_RENEWING
;
1243 client
->attempt
= 1;
1245 return client_initialize_time_events(client
);
1248 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1249 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1252 r
= dhcp_lease_new(&lease
);
1256 if (client
->client_id_len
) {
1257 r
= dhcp_lease_set_client_id(lease
,
1258 (uint8_t *) &client
->client_id
,
1259 client
->client_id_len
);
1264 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1265 if (r
!= DHCP_OFFER
) {
1266 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1270 lease
->next_server
= offer
->siaddr
;
1271 lease
->address
= offer
->yiaddr
;
1273 if (lease
->address
== 0 ||
1274 lease
->server_address
== 0 ||
1275 lease
->lifetime
== 0) {
1276 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1280 if (!lease
->have_subnet_mask
) {
1281 r
= dhcp_lease_set_default_subnet_mask(lease
);
1283 log_dhcp_client(client
,
1284 "received lease lacks subnet mask, "
1285 "and a fallback one cannot be generated, ignoring");
1290 sd_dhcp_lease_unref(client
->lease
);
1291 client
->lease
= lease
;
1294 log_dhcp_client(client
, "OFFER");
1299 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1302 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1303 if (r
!= DHCP_FORCERENEW
)
1306 log_dhcp_client(client
, "FORCERENEW");
1311 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1312 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1313 _cleanup_free_
char *error_message
= NULL
;
1316 r
= dhcp_lease_new(&lease
);
1320 if (client
->client_id_len
) {
1321 r
= dhcp_lease_set_client_id(lease
,
1322 (uint8_t *) &client
->client_id
,
1323 client
->client_id_len
);
1328 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1329 if (r
== DHCP_NAK
) {
1330 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1331 return -EADDRNOTAVAIL
;
1334 if (r
!= DHCP_ACK
) {
1335 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1339 lease
->next_server
= ack
->siaddr
;
1341 lease
->address
= ack
->yiaddr
;
1343 if (lease
->address
== INADDR_ANY
||
1344 lease
->server_address
== INADDR_ANY
||
1345 lease
->lifetime
== 0) {
1346 log_dhcp_client(client
, "received lease lacks address, server "
1347 "address or lease lifetime, ignoring");
1351 if (lease
->subnet_mask
== INADDR_ANY
) {
1352 r
= dhcp_lease_set_default_subnet_mask(lease
);
1354 log_dhcp_client(client
,
1355 "received lease lacks subnet mask, "
1356 "and a fallback one cannot be generated, ignoring");
1361 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1362 if (client
->lease
) {
1363 if (client
->lease
->address
!= lease
->address
||
1364 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1365 client
->lease
->router
!= lease
->router
) {
1366 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1368 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1370 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1373 client
->lease
= lease
;
1376 log_dhcp_client(client
, "ACK");
1381 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1383 assert(client
->request_sent
);
1384 assert(lifetime
> 0);
1391 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1392 + (random_u32() & 0x1fffff);
1395 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1397 uint64_t lifetime_timeout
;
1398 uint64_t t2_timeout
;
1399 uint64_t t1_timeout
;
1400 char time_string
[FORMAT_TIMESPAN_MAX
];
1404 assert(client
->event
);
1405 assert(client
->lease
);
1406 assert(client
->lease
->lifetime
);
1408 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1409 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1410 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1412 /* don't set timers for infinite leases */
1413 if (client
->lease
->lifetime
== 0xffffffff)
1416 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1419 assert(client
->request_sent
<= time_now
);
1421 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1422 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1423 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1424 /* both T1 and T2 are given */
1425 if (client
->lease
->t1
< client
->lease
->t2
&&
1426 client
->lease
->t2
< client
->lease
->lifetime
) {
1427 /* they are both valid */
1428 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1429 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1432 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1433 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1434 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1435 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1437 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1438 /* only T2 is given, and it is valid */
1439 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1440 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1441 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1442 if (t2_timeout
<= t1_timeout
) {
1443 /* the computed T1 would be invalid, so discard T2 */
1444 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1445 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1447 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1448 /* only T1 is given, and it is valid */
1449 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1450 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1451 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1452 if (t2_timeout
<= t1_timeout
) {
1453 /* the computed T2 would be invalid, so discard T1 */
1454 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1455 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1458 /* fall back to the default timeouts */
1459 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1460 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1461 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1462 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1465 /* arm lifetime timeout */
1466 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1467 clock_boottime_or_monotonic(),
1468 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1469 client_timeout_expire
, client
);
1473 r
= sd_event_source_set_priority(client
->timeout_expire
,
1474 client
->event_priority
);
1478 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1482 log_dhcp_client(client
, "lease expires in %s",
1483 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1485 /* don't arm earlier timeouts if this has already expired */
1486 if (lifetime_timeout
<= time_now
)
1489 /* arm T2 timeout */
1490 r
= sd_event_add_time(client
->event
,
1491 &client
->timeout_t2
,
1492 clock_boottime_or_monotonic(),
1495 client_timeout_t2
, client
);
1499 r
= sd_event_source_set_priority(client
->timeout_t2
,
1500 client
->event_priority
);
1504 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1508 log_dhcp_client(client
, "T2 expires in %s",
1509 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1511 /* don't arm earlier timeout if this has already expired */
1512 if (t2_timeout
<= time_now
)
1515 /* arm T1 timeout */
1516 r
= sd_event_add_time(client
->event
,
1517 &client
->timeout_t1
,
1518 clock_boottime_or_monotonic(),
1519 t1_timeout
, 10 * USEC_PER_MSEC
,
1520 client_timeout_t1
, client
);
1524 r
= sd_event_source_set_priority(client
->timeout_t1
,
1525 client
->event_priority
);
1529 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1533 log_dhcp_client(client
, "T1 expires in %s",
1534 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1539 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1540 DHCP_CLIENT_DONT_DESTROY(client
);
1541 char time_string
[FORMAT_TIMESPAN_MAX
];
1542 int r
= 0, notify_event
= 0;
1545 assert(client
->event
);
1548 switch (client
->state
) {
1549 case DHCP_STATE_SELECTING
:
1551 r
= client_handle_offer(client
, message
, len
);
1554 client
->timeout_resend
=
1555 sd_event_source_unref(client
->timeout_resend
);
1557 client
->state
= DHCP_STATE_REQUESTING
;
1558 client
->attempt
= 1;
1560 r
= sd_event_add_time(client
->event
,
1561 &client
->timeout_resend
,
1562 clock_boottime_or_monotonic(),
1564 client_timeout_resend
, client
);
1568 r
= sd_event_source_set_priority(client
->timeout_resend
,
1569 client
->event_priority
);
1573 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1576 } else if (r
== -ENOMSG
)
1577 /* invalid message, let's ignore it */
1582 case DHCP_STATE_REBOOTING
:
1583 case DHCP_STATE_REQUESTING
:
1584 case DHCP_STATE_RENEWING
:
1585 case DHCP_STATE_REBINDING
:
1587 r
= client_handle_ack(client
, message
, len
);
1589 client
->start_delay
= 0;
1590 client
->timeout_resend
=
1591 sd_event_source_unref(client
->timeout_resend
);
1592 client
->receive_message
=
1593 sd_event_source_unref(client
->receive_message
);
1594 client
->fd
= asynchronous_close(client
->fd
);
1596 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1597 DHCP_STATE_REBOOTING
))
1598 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1599 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1602 client
->state
= DHCP_STATE_BOUND
;
1603 client
->attempt
= 1;
1605 client
->last_addr
= client
->lease
->address
;
1607 r
= client_set_lease_timeouts(client
);
1609 log_dhcp_client(client
, "could not set lease timeouts");
1613 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1615 log_dhcp_client(client
, "could not bind UDP socket");
1621 client_initialize_io_events(client
, client_receive_message_udp
);
1624 client_notify(client
, notify_event
);
1625 if (client
->state
== DHCP_STATE_STOPPED
)
1629 } else if (r
== -EADDRNOTAVAIL
) {
1630 /* got a NAK, let's restart the client */
1631 client
->timeout_resend
=
1632 sd_event_source_unref(client
->timeout_resend
);
1634 r
= client_initialize(client
);
1638 r
= client_start_delayed(client
);
1642 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1643 client
->start_delay
, USEC_PER_SEC
));
1645 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1646 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1649 } else if (r
== -ENOMSG
)
1650 /* invalid message, let's ignore it */
1655 case DHCP_STATE_BOUND
:
1656 r
= client_handle_forcerenew(client
, message
, len
);
1658 r
= client_timeout_t1(NULL
, 0, client
);
1661 } else if (r
== -ENOMSG
)
1662 /* invalid message, let's ignore it */
1667 case DHCP_STATE_INIT
:
1668 case DHCP_STATE_INIT_REBOOT
:
1672 case DHCP_STATE_STOPPED
:
1679 client_stop(client
, r
);
1684 static int client_receive_message_udp(
1690 sd_dhcp_client
*client
= userdata
;
1691 _cleanup_free_ DHCPMessage
*message
= NULL
;
1692 const struct ether_addr zero_mac
= {};
1693 const struct ether_addr
*expected_chaddr
= NULL
;
1694 uint8_t expected_hlen
= 0;
1695 ssize_t len
, buflen
;
1700 buflen
= next_datagram_size_fd(fd
);
1704 message
= malloc0(buflen
);
1708 len
= recv(fd
, message
, buflen
, 0);
1710 if (IN_SET(errno
, EAGAIN
, EINTR
))
1713 return log_dhcp_client_errno(client
, errno
,
1714 "Could not receive message from UDP socket: %m");
1716 if ((size_t) len
< sizeof(DHCPMessage
)) {
1717 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1721 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1722 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1726 if (message
->op
!= BOOTREPLY
) {
1727 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1731 if (message
->htype
!= client
->arp_type
) {
1732 log_dhcp_client(client
, "Packet type does not match client type");
1736 if (client
->arp_type
== ARPHRD_ETHER
) {
1737 expected_hlen
= ETH_ALEN
;
1738 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1740 /* Non-Ethernet links expect zero chaddr */
1742 expected_chaddr
= &zero_mac
;
1745 if (message
->hlen
!= expected_hlen
) {
1746 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1750 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1751 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1755 if (client
->state
!= DHCP_STATE_BOUND
&&
1756 be32toh(message
->xid
) != client
->xid
) {
1757 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1758 so ignore the xid in this case */
1759 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1760 be32toh(message
->xid
), client
->xid
);
1764 return client_handle_message(client
, message
, len
);
1767 static int client_receive_message_raw(
1773 sd_dhcp_client
*client
= userdata
;
1774 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1775 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1776 struct iovec iov
= {};
1777 struct msghdr msg
= {
1780 .msg_control
= cmsgbuf
,
1781 .msg_controllen
= sizeof(cmsgbuf
),
1783 struct cmsghdr
*cmsg
;
1784 bool checksum
= true;
1785 ssize_t buflen
, len
;
1791 buflen
= next_datagram_size_fd(fd
);
1795 packet
= malloc0(buflen
);
1799 iov
.iov_base
= packet
;
1800 iov
.iov_len
= buflen
;
1802 len
= recvmsg(fd
, &msg
, 0);
1804 if (IN_SET(errno
, EAGAIN
, EINTR
))
1807 return log_dhcp_client_errno(client
, errno
,
1808 "Could not receive message from raw socket: %m");
1809 } else if ((size_t)len
< sizeof(DHCPPacket
))
1812 CMSG_FOREACH(cmsg
, &msg
) {
1813 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1814 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1815 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1816 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1818 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1823 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1827 len
-= DHCP_IP_UDP_SIZE
;
1829 return client_handle_message(client
, &packet
->dhcp
, len
);
1832 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1835 assert_return(client
, -EINVAL
);
1837 r
= client_initialize(client
);
1841 /* RFC7844 section 3.3:
1842 SHOULD perform a complete four-way handshake, starting with a
1843 DHCPDISCOVER, to obtain a new address lease. If the client can
1844 ascertain that this is exactly the same network to which it was
1845 previously connected, and if the link-layer address did not change,
1846 the client MAY issue a DHCPREQUEST to try to reclaim the current
1848 if (client
->last_addr
&& !client
->anonymize
)
1849 client
->state
= DHCP_STATE_INIT_REBOOT
;
1851 r
= client_start(client
);
1853 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1858 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1859 DHCP_CLIENT_DONT_DESTROY(client
);
1861 assert_return(client
, -EINVAL
);
1863 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1864 client
->state
= DHCP_STATE_STOPPED
;
1869 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1872 assert_return(client
, -EINVAL
);
1873 assert_return(!client
->event
, -EBUSY
);
1876 client
->event
= sd_event_ref(event
);
1878 r
= sd_event_default(&client
->event
);
1883 client
->event_priority
= priority
;
1888 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1889 assert_return(client
, -EINVAL
);
1891 client
->event
= sd_event_unref(client
->event
);
1896 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1897 assert_return(client
, NULL
);
1899 return client
->event
;
1902 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1907 assert(client
->n_ref
>= 1);
1913 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1918 assert(client
->n_ref
>= 1);
1921 if (client
->n_ref
> 0)
1924 log_dhcp_client(client
, "FREE");
1926 client_initialize(client
);
1928 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1930 sd_dhcp_client_detach_event(client
);
1932 sd_dhcp_lease_unref(client
->lease
);
1934 free(client
->req_opts
);
1935 free(client
->hostname
);
1936 free(client
->vendor_class_identifier
);
1937 return mfree(client
);
1940 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1941 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1943 assert_return(ret
, -EINVAL
);
1945 client
= new0(sd_dhcp_client
, 1);
1950 client
->state
= DHCP_STATE_INIT
;
1951 client
->ifindex
= -1;
1953 client
->attempt
= 1;
1954 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1955 client
->port
= DHCP_PORT_CLIENT
;
1957 client
->anonymize
= !!anonymize
;
1958 /* NOTE: this could be moved to a function. */
1960 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1961 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1963 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1964 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1966 if (!client
->req_opts
)