1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
7 #include <net/ethernet.h>
8 #include <net/if_arp.h>
12 #include <sys/ioctl.h>
13 #include <linux/if_infiniband.h>
15 #include "sd-dhcp-client.h"
17 #include "alloc-util.h"
19 #include "dhcp-identifier.h"
20 #include "dhcp-internal.h"
21 #include "dhcp-lease-internal.h"
22 #include "dhcp-protocol.h"
23 #include "dns-domain.h"
24 #include "event-util.h"
25 #include "hostname-util.h"
27 #include "random-util.h"
28 #include "string-util.h"
32 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
33 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
35 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
36 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
38 struct sd_dhcp_client
{
44 sd_event_source
*timeout_resend
;
48 union sockaddr_union link
;
49 sd_event_source
*receive_message
;
50 bool request_broadcast
;
52 size_t req_opts_allocated
;
56 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
63 /* 0: Generic (non-LL) (RFC 2132) */
64 uint8_t data
[MAX_CLIENT_ID_LEN
];
67 /* 1: Ethernet Link-Layer (RFC 2132) */
68 uint8_t haddr
[ETH_ALEN
];
71 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
75 /* 255: Node-specific (RFC 4361) */
80 uint8_t data
[MAX_CLIENT_ID_LEN
];
86 char *vendor_class_identifier
;
93 sd_event_source
*timeout_t1
;
94 sd_event_source
*timeout_t2
;
95 sd_event_source
*timeout_expire
;
96 sd_dhcp_client_callback_t callback
;
102 static const uint8_t default_req_opts
[] = {
103 SD_DHCP_OPTION_SUBNET_MASK
,
104 SD_DHCP_OPTION_ROUTER
,
105 SD_DHCP_OPTION_HOST_NAME
,
106 SD_DHCP_OPTION_DOMAIN_NAME
,
107 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
110 /* RFC7844 section 3:
111 MAY contain the Parameter Request List option.
113 The client intending to protect its privacy SHOULD only request a
114 minimal number of options in the PRL and SHOULD also randomly shuffle
115 the ordering of option codes in the PRL. If this random ordering
116 cannot be implemented, the client MAY order the option codes in the
117 PRL by option code number (lowest to highest).
119 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
120 static const uint8_t default_req_opts_anonymize
[] = {
121 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
122 SD_DHCP_OPTION_ROUTER
, /* 3 */
123 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
124 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
125 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
126 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
127 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
128 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
129 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
130 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
131 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
132 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
133 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
136 static int client_receive_message_raw(
141 static int client_receive_message_udp(
146 static void client_stop(sd_dhcp_client
*client
, int error
);
148 int sd_dhcp_client_set_callback(
149 sd_dhcp_client
*client
,
150 sd_dhcp_client_callback_t cb
,
153 assert_return(client
, -EINVAL
);
155 client
->callback
= cb
;
156 client
->userdata
= userdata
;
161 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
162 assert_return(client
, -EINVAL
);
164 client
->request_broadcast
= !!broadcast
;
169 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
172 assert_return(client
, -EINVAL
);
173 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
177 case SD_DHCP_OPTION_PAD
:
178 case SD_DHCP_OPTION_OVERLOAD
:
179 case SD_DHCP_OPTION_MESSAGE_TYPE
:
180 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
181 case SD_DHCP_OPTION_END
:
188 for (i
= 0; i
< client
->req_opts_size
; i
++)
189 if (client
->req_opts
[i
] == option
)
192 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
193 client
->req_opts_size
+ 1))
196 client
->req_opts
[client
->req_opts_size
++] = option
;
201 int sd_dhcp_client_set_request_address(
202 sd_dhcp_client
*client
,
203 const struct in_addr
*last_addr
) {
205 assert_return(client
, -EINVAL
);
206 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
209 client
->last_addr
= last_addr
->s_addr
;
211 client
->last_addr
= INADDR_ANY
;
216 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
218 assert_return(client
, -EINVAL
);
219 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
220 assert_return(ifindex
> 0, -EINVAL
);
222 client
->ifindex
= ifindex
;
226 int sd_dhcp_client_set_mac(
227 sd_dhcp_client
*client
,
232 DHCP_CLIENT_DONT_DESTROY(client
);
233 bool need_restart
= false;
235 assert_return(client
, -EINVAL
);
236 assert_return(addr
, -EINVAL
);
237 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
238 assert_return(arp_type
> 0, -EINVAL
);
240 if (arp_type
== ARPHRD_ETHER
)
241 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
242 else if (arp_type
== ARPHRD_INFINIBAND
)
243 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
247 if (client
->mac_addr_len
== addr_len
&&
248 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
251 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
252 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
254 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
257 memcpy(&client
->mac_addr
, addr
, addr_len
);
258 client
->mac_addr_len
= addr_len
;
259 client
->arp_type
= arp_type
;
261 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
262 sd_dhcp_client_start(client
);
267 int sd_dhcp_client_get_client_id(
268 sd_dhcp_client
*client
,
270 const uint8_t **data
,
273 assert_return(client
, -EINVAL
);
274 assert_return(type
, -EINVAL
);
275 assert_return(data
, -EINVAL
);
276 assert_return(data_len
, -EINVAL
);
281 if (client
->client_id_len
) {
282 *type
= client
->client_id
.type
;
283 *data
= client
->client_id
.raw
.data
;
284 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
290 int sd_dhcp_client_set_client_id(
291 sd_dhcp_client
*client
,
296 DHCP_CLIENT_DONT_DESTROY(client
);
297 bool need_restart
= false;
299 assert_return(client
, -EINVAL
);
300 assert_return(data
, -EINVAL
);
301 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
303 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
304 client
->client_id
.type
== type
&&
305 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
308 /* For hardware types, log debug message about unexpected data length.
310 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
311 * last last 8 bytes of the address are stable and suitable to put into
312 * the client-id. The caller is advised to account for that. */
313 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
314 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
315 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
316 "unexpected address length %zu",
319 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
320 log_dhcp_client(client
, "Changing client ID on running DHCP "
321 "client, restarting");
323 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
326 client
->client_id
.type
= type
;
327 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
328 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
330 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
331 sd_dhcp_client_start(client
);
337 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
338 * without further modification. Otherwise, if duid_type is supported, DUID
339 * is set based on that type. Otherwise, an error is returned.
341 static int dhcp_client_set_iaid_duid_internal(
342 sd_dhcp_client
*client
,
351 DHCP_CLIENT_DONT_DESTROY(client
);
355 assert_return(client
, -EINVAL
);
356 assert_return(duid_len
== 0 || duid
, -EINVAL
);
359 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
364 zero(client
->client_id
);
365 client
->client_id
.type
= 255;
369 client
->client_id
.ns
.iaid
= htobe32(iaid
);
371 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
372 client
->mac_addr_len
,
374 &client
->client_id
.ns
.iaid
);
381 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
382 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
383 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
387 if (client
->mac_addr_len
== 0)
390 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
395 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
400 if (client
->mac_addr_len
== 0)
403 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
408 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
416 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
417 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
419 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
420 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
421 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
422 sd_dhcp_client_start(client
);
428 int sd_dhcp_client_set_iaid_duid(
429 sd_dhcp_client
*client
,
435 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
438 int sd_dhcp_client_set_iaid_duid_llt(
439 sd_dhcp_client
*client
,
443 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
446 int sd_dhcp_client_set_duid(
447 sd_dhcp_client
*client
,
451 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
454 int sd_dhcp_client_set_duid_llt(
455 sd_dhcp_client
*client
,
457 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
460 int sd_dhcp_client_set_hostname(
461 sd_dhcp_client
*client
,
462 const char *hostname
) {
464 assert_return(client
, -EINVAL
);
466 /* Make sure hostnames qualify as DNS and as Linux hostnames */
468 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
471 return free_and_strdup(&client
->hostname
, hostname
);
474 int sd_dhcp_client_set_vendor_class_identifier(
475 sd_dhcp_client
*client
,
478 assert_return(client
, -EINVAL
);
480 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
483 int sd_dhcp_client_set_user_class(
484 sd_dhcp_client
*client
,
485 const char* const* user_class
) {
487 _cleanup_strv_free_
char **s
= NULL
;
490 STRV_FOREACH(p
, (char **) user_class
)
491 if (strlen(*p
) > 255)
492 return -ENAMETOOLONG
;
494 s
= strv_copy((char **) user_class
);
498 client
->user_class
= TAKE_PTR(s
);
503 int sd_dhcp_client_set_client_port(
504 sd_dhcp_client
*client
,
507 assert_return(client
, -EINVAL
);
514 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
515 assert_return(client
, -EINVAL
);
516 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
523 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
524 assert_return(client
, -EINVAL
);
526 if (!IN_SET(client
->state
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
527 return -EADDRNOTAVAIL
;
530 *ret
= client
->lease
;
535 static void client_notify(sd_dhcp_client
*client
, int event
) {
538 if (client
->callback
)
539 client
->callback(client
, event
, client
->userdata
);
542 static int client_initialize(sd_dhcp_client
*client
) {
543 assert_return(client
, -EINVAL
);
545 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
547 client
->fd
= asynchronous_close(client
->fd
);
549 (void) event_source_disable(client
->timeout_resend
);
550 (void) event_source_disable(client
->timeout_t1
);
551 (void) event_source_disable(client
->timeout_t2
);
552 (void) event_source_disable(client
->timeout_expire
);
556 client
->state
= DHCP_STATE_INIT
;
559 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
564 static void client_stop(sd_dhcp_client
*client
, int error
) {
568 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
569 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
570 log_dhcp_client(client
, "STOPPED");
572 log_dhcp_client(client
, "STOPPED: Unknown event");
574 client_notify(client
, error
);
576 client_initialize(client
);
579 static int client_message_init(
580 sd_dhcp_client
*client
,
584 size_t *_optoffset
) {
586 _cleanup_free_ DHCPPacket
*packet
= NULL
;
587 size_t optlen
, optoffset
, size
;
594 assert(client
->start_time
);
598 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
600 optlen
= DHCP_MIN_OPTIONS_SIZE
;
601 size
= sizeof(DHCPPacket
) + optlen
;
603 packet
= malloc0(size
);
607 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
608 client
->arp_type
, optlen
, &optoffset
);
612 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
613 refuse to issue an DHCP lease if 'secs' is set to zero */
614 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
617 assert(time_now
>= client
->start_time
);
619 /* seconds between sending first and last DISCOVER
620 * must always be strictly positive to deal with broken servers */
621 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
622 packet
->dhcp
.secs
= htobe16(secs
);
624 /* RFC2132 section 4.1
625 A client that cannot receive unicast IP datagrams until its protocol
626 software has been configured with an IP address SHOULD set the
627 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
628 DHCPREQUEST messages that client sends. The BROADCAST bit will
629 provide a hint to the DHCP server and BOOTP relay agent to broadcast
630 any messages to the client on the client's subnet.
632 Note: some interfaces needs this to be enabled, but some networks
633 needs this to be disabled as broadcasts are filteretd, so this
634 needs to be configurable */
635 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
636 packet
->dhcp
.flags
= htobe16(0x8000);
638 /* RFC2132 section 4.1.1:
639 The client MUST include its hardware address in the ’chaddr’ field, if
640 necessary for delivery of DHCP reply messages. Non-Ethernet
641 interfaces will leave 'chaddr' empty and use the client identifier
642 instead (eg, RFC 4390 section 2.1).
644 if (client
->arp_type
== ARPHRD_ETHER
)
645 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
647 /* If no client identifier exists, construct an RFC 4361-compliant one */
648 if (client
->client_id_len
== 0) {
651 client
->client_id
.type
= 255;
653 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
654 true, &client
->client_id
.ns
.iaid
);
658 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
662 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
665 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
666 Identifier option is not set */
667 if (client
->client_id_len
) {
668 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
669 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
670 client
->client_id_len
,
676 /* RFC2131 section 3.5:
677 in its initial DHCPDISCOVER or DHCPREQUEST message, a
678 client may provide the server with a list of specific
679 parameters the client is interested in. If the client
680 includes a list of parameters in a DHCPDISCOVER message,
681 it MUST include that list in any subsequent DHCPREQUEST
685 /* RFC7844 section 3:
686 MAY contain the Parameter Request List option. */
687 /* NOTE: in case that there would be an option to do not send
688 * any PRL at all, the size should be checked before sending */
689 if (client
->req_opts_size
> 0) {
690 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
691 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
692 client
->req_opts_size
, client
->req_opts
);
697 /* RFC2131 section 3.5:
698 The client SHOULD include the ’maximum DHCP message size’ option to
699 let the server know how large the server may make its DHCP messages.
701 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
702 than the defined default size unless the Maximum Message Size option
705 RFC3442 "Requirements to Avoid Sizing Constraints":
706 Because a full routing table can be quite large, the standard 576
707 octet maximum size for a DHCP message may be too short to contain
708 some legitimate Classless Static Route options. Because of this,
709 clients implementing the Classless Static Route option SHOULD send a
710 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
711 stack is capable of receiving larger IP datagrams. In this case, the
712 client SHOULD set the value of this option to at least the MTU of the
713 interface that the client is configuring. The client MAY set the
714 value of this option higher, up to the size of the largest UDP packet
715 it is prepared to accept. (Note that the value specified in the
716 Maximum DHCP Message Size option is the total maximum packet size,
717 including IP and UDP headers.)
719 /* RFC7844 section 3:
720 SHOULD NOT contain any other option. */
721 if (!client
->anonymize
) {
722 max_size
= htobe16(size
);
723 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
724 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
731 *_optoffset
= optoffset
;
732 *ret
= TAKE_PTR(packet
);
737 static int client_append_fqdn_option(
738 DHCPMessage
*message
,
743 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
746 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
747 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
748 buffer
[1] = 0; /* RCODE1 (deprecated) */
749 buffer
[2] = 0; /* RCODE2 (deprecated) */
751 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
753 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
754 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
759 static int dhcp_client_send_raw(
760 sd_dhcp_client
*client
,
764 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
765 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
767 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
771 static int client_send_discover(sd_dhcp_client
*client
) {
772 _cleanup_free_ DHCPPacket
*discover
= NULL
;
773 size_t optoffset
, optlen
;
777 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
779 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
780 &optlen
, &optoffset
);
784 /* the client may suggest values for the network address
785 and lease time in the DHCPDISCOVER message. The client may include
786 the ’requested IP address’ option to suggest that a particular IP
787 address be assigned, and may include the ’IP address lease time’
788 option to suggest the lease time it would like.
790 if (client
->last_addr
!= INADDR_ANY
) {
791 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
792 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
793 4, &client
->last_addr
);
798 if (client
->hostname
) {
799 /* According to RFC 4702 "clients that send the Client FQDN option in
800 their messages MUST NOT also send the Host Name option". Just send
801 one of the two depending on the hostname type.
803 if (dns_name_is_single_label(client
->hostname
)) {
804 /* it is unclear from RFC 2131 if client should send hostname in
805 DHCPDISCOVER but dhclient does and so we do as well
807 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
808 SD_DHCP_OPTION_HOST_NAME
,
809 strlen(client
->hostname
), client
->hostname
);
811 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
817 if (client
->vendor_class_identifier
) {
818 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
819 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
820 strlen(client
->vendor_class_identifier
),
821 client
->vendor_class_identifier
);
826 if (client
->user_class
) {
827 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
828 SD_DHCP_OPTION_USER_CLASS
,
829 strv_length(client
->user_class
),
835 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
836 SD_DHCP_OPTION_END
, 0, NULL
);
840 /* We currently ignore:
841 The client SHOULD wait a random time between one and ten seconds to
842 desynchronize the use of DHCP at startup.
844 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
848 log_dhcp_client(client
, "DISCOVER");
853 static int client_send_request(sd_dhcp_client
*client
) {
854 _cleanup_free_ DHCPPacket
*request
= NULL
;
855 size_t optoffset
, optlen
;
860 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
864 switch (client
->state
) {
865 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
866 SELECTING should be REQUESTING)
869 case DHCP_STATE_REQUESTING
:
870 /* Client inserts the address of the selected server in ’server
871 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
872 filled in with the yiaddr value from the chosen DHCPOFFER.
875 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
876 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
877 4, &client
->lease
->server_address
);
881 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
882 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
883 4, &client
->lease
->address
);
889 case DHCP_STATE_INIT_REBOOT
:
890 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
891 option MUST be filled in with client’s notion of its previously
892 assigned address. ’ciaddr’ MUST be zero.
894 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
895 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
896 4, &client
->last_addr
);
901 case DHCP_STATE_RENEWING
:
902 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
903 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
907 case DHCP_STATE_REBINDING
:
908 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
909 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
912 This message MUST be broadcast to the 0xffffffff IP broadcast address.
914 request
->dhcp
.ciaddr
= client
->lease
->address
;
918 case DHCP_STATE_INIT
:
919 case DHCP_STATE_SELECTING
:
920 case DHCP_STATE_REBOOTING
:
921 case DHCP_STATE_BOUND
:
922 case DHCP_STATE_STOPPED
:
926 if (client
->hostname
) {
927 if (dns_name_is_single_label(client
->hostname
))
928 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
929 SD_DHCP_OPTION_HOST_NAME
,
930 strlen(client
->hostname
), client
->hostname
);
932 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
938 if (client
->vendor_class_identifier
) {
939 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
940 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
941 strlen(client
->vendor_class_identifier
),
942 client
->vendor_class_identifier
);
947 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
948 SD_DHCP_OPTION_END
, 0, NULL
);
952 if (client
->state
== DHCP_STATE_RENEWING
) {
953 r
= dhcp_network_send_udp_socket(client
->fd
,
954 client
->lease
->server_address
,
957 sizeof(DHCPMessage
) + optoffset
);
959 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
964 switch (client
->state
) {
966 case DHCP_STATE_REQUESTING
:
967 log_dhcp_client(client
, "REQUEST (requesting)");
970 case DHCP_STATE_INIT_REBOOT
:
971 log_dhcp_client(client
, "REQUEST (init-reboot)");
974 case DHCP_STATE_RENEWING
:
975 log_dhcp_client(client
, "REQUEST (renewing)");
978 case DHCP_STATE_REBINDING
:
979 log_dhcp_client(client
, "REQUEST (rebinding)");
983 log_dhcp_client(client
, "REQUEST (invalid)");
990 static int client_start(sd_dhcp_client
*client
);
992 static int client_timeout_resend(
997 sd_dhcp_client
*client
= userdata
;
998 DHCP_CLIENT_DONT_DESTROY(client
);
999 usec_t next_timeout
= 0;
1006 assert(client
->event
);
1008 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1012 switch (client
->state
) {
1014 case DHCP_STATE_RENEWING
:
1016 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1020 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1024 case DHCP_STATE_REBINDING
:
1026 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1030 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1033 case DHCP_STATE_REBOOTING
:
1034 /* start over as we did not receive a timely ack or nak */
1035 r
= client_initialize(client
);
1039 r
= client_start(client
);
1043 log_dhcp_client(client
, "REBOOTED");
1047 case DHCP_STATE_INIT
:
1048 case DHCP_STATE_INIT_REBOOT
:
1049 case DHCP_STATE_SELECTING
:
1050 case DHCP_STATE_REQUESTING
:
1051 case DHCP_STATE_BOUND
:
1053 if (client
->attempt
< 64)
1054 client
->attempt
*= 2;
1056 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
1060 case DHCP_STATE_STOPPED
:
1065 next_timeout
+= (random_u32() & 0x1fffff);
1067 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1068 clock_boottime_or_monotonic(),
1069 next_timeout
, 10 * USEC_PER_MSEC
,
1070 client_timeout_resend
, client
,
1071 client
->event_priority
, "dhcp4-resend-timer", true);
1075 switch (client
->state
) {
1076 case DHCP_STATE_INIT
:
1077 r
= client_send_discover(client
);
1079 client
->state
= DHCP_STATE_SELECTING
;
1080 client
->attempt
= 1;
1082 if (client
->attempt
>= 64)
1088 case DHCP_STATE_SELECTING
:
1089 r
= client_send_discover(client
);
1090 if (r
< 0 && client
->attempt
>= 64)
1095 case DHCP_STATE_INIT_REBOOT
:
1096 case DHCP_STATE_REQUESTING
:
1097 case DHCP_STATE_RENEWING
:
1098 case DHCP_STATE_REBINDING
:
1099 r
= client_send_request(client
);
1100 if (r
< 0 && client
->attempt
>= 64)
1103 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1104 client
->state
= DHCP_STATE_REBOOTING
;
1106 client
->request_sent
= time_now
;
1110 case DHCP_STATE_REBOOTING
:
1111 case DHCP_STATE_BOUND
:
1115 case DHCP_STATE_STOPPED
:
1123 client_stop(client
, r
);
1125 /* Errors were dealt with when stopping the client, don't spill
1126 errors into the event loop handler */
1130 static int client_initialize_io_events(
1131 sd_dhcp_client
*client
,
1132 sd_event_io_handler_t io_callback
) {
1137 assert(client
->event
);
1139 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1140 client
->fd
, EPOLLIN
, io_callback
,
1145 r
= sd_event_source_set_priority(client
->receive_message
,
1146 client
->event_priority
);
1150 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1156 client_stop(client
, r
);
1161 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1166 assert(client
->event
);
1168 if (client
->start_delay
) {
1169 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1170 usec
+= client
->start_delay
;
1173 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1174 clock_boottime_or_monotonic(),
1176 client_timeout_resend
, client
,
1177 client
->event_priority
, "dhcp4-resend-timer", true);
1179 client_stop(client
, r
);
1185 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1186 client_initialize_io_events(client
, io_callback
);
1187 client_initialize_time_events(client
);
1192 static int client_start_delayed(sd_dhcp_client
*client
) {
1195 assert_return(client
, -EINVAL
);
1196 assert_return(client
->event
, -EINVAL
);
1197 assert_return(client
->ifindex
> 0, -EINVAL
);
1198 assert_return(client
->fd
< 0, -EBUSY
);
1199 assert_return(client
->xid
== 0, -EINVAL
);
1200 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1202 client
->xid
= random_u32();
1204 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1205 client
->xid
, client
->mac_addr
,
1206 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1208 client_stop(client
, r
);
1213 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1214 client
->start_time
= now(clock_boottime_or_monotonic());
1216 return client_initialize_events(client
, client_receive_message_raw
);
1219 static int client_start(sd_dhcp_client
*client
) {
1220 client
->start_delay
= 0;
1221 return client_start_delayed(client
);
1224 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1225 sd_dhcp_client
*client
= userdata
;
1226 DHCP_CLIENT_DONT_DESTROY(client
);
1228 log_dhcp_client(client
, "EXPIRED");
1230 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1232 /* lease was lost, start over if not freed or stopped in callback */
1233 if (client
->state
!= DHCP_STATE_STOPPED
) {
1234 client_initialize(client
);
1235 client_start(client
);
1241 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1242 sd_dhcp_client
*client
= userdata
;
1243 DHCP_CLIENT_DONT_DESTROY(client
);
1248 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1249 client
->fd
= asynchronous_close(client
->fd
);
1251 client
->state
= DHCP_STATE_REBINDING
;
1252 client
->attempt
= 1;
1254 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1255 client
->xid
, client
->mac_addr
,
1256 client
->mac_addr_len
, client
->arp_type
,
1259 client_stop(client
, r
);
1264 return client_initialize_events(client
, client_receive_message_raw
);
1267 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1268 sd_dhcp_client
*client
= userdata
;
1269 DHCP_CLIENT_DONT_DESTROY(client
);
1271 client
->state
= DHCP_STATE_RENEWING
;
1272 client
->attempt
= 1;
1274 return client_initialize_time_events(client
);
1277 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1278 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1281 r
= dhcp_lease_new(&lease
);
1285 if (client
->client_id_len
) {
1286 r
= dhcp_lease_set_client_id(lease
,
1287 (uint8_t *) &client
->client_id
,
1288 client
->client_id_len
);
1293 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1294 if (r
!= DHCP_OFFER
) {
1295 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1299 lease
->next_server
= offer
->siaddr
;
1300 lease
->address
= offer
->yiaddr
;
1302 if (lease
->address
== 0 ||
1303 lease
->server_address
== 0 ||
1304 lease
->lifetime
== 0) {
1305 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1309 if (!lease
->have_subnet_mask
) {
1310 r
= dhcp_lease_set_default_subnet_mask(lease
);
1312 log_dhcp_client(client
,
1313 "received lease lacks subnet mask, "
1314 "and a fallback one cannot be generated, ignoring");
1319 sd_dhcp_lease_unref(client
->lease
);
1320 client
->lease
= TAKE_PTR(lease
);
1322 log_dhcp_client(client
, "OFFER");
1327 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1330 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1331 if (r
!= DHCP_FORCERENEW
)
1334 log_dhcp_client(client
, "FORCERENEW");
1339 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1340 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1341 _cleanup_free_
char *error_message
= NULL
;
1344 r
= dhcp_lease_new(&lease
);
1348 if (client
->client_id_len
) {
1349 r
= dhcp_lease_set_client_id(lease
,
1350 (uint8_t *) &client
->client_id
,
1351 client
->client_id_len
);
1356 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1357 if (r
== DHCP_NAK
) {
1358 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1359 return -EADDRNOTAVAIL
;
1362 if (r
!= DHCP_ACK
) {
1363 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1367 lease
->next_server
= ack
->siaddr
;
1369 lease
->address
= ack
->yiaddr
;
1371 if (lease
->address
== INADDR_ANY
||
1372 lease
->server_address
== INADDR_ANY
||
1373 lease
->lifetime
== 0) {
1374 log_dhcp_client(client
, "received lease lacks address, server "
1375 "address or lease lifetime, ignoring");
1379 if (lease
->subnet_mask
== INADDR_ANY
) {
1380 r
= dhcp_lease_set_default_subnet_mask(lease
);
1382 log_dhcp_client(client
,
1383 "received lease lacks subnet mask, "
1384 "and a fallback one cannot be generated, ignoring");
1389 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1390 if (client
->lease
) {
1391 if (client
->lease
->address
!= lease
->address
||
1392 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1393 client
->lease
->router
!= lease
->router
) {
1394 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1396 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1398 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1401 client
->lease
= TAKE_PTR(lease
);
1403 log_dhcp_client(client
, "ACK");
1408 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1410 assert(client
->request_sent
);
1411 assert(lifetime
> 0);
1418 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1419 + (random_u32() & 0x1fffff);
1422 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1424 uint64_t lifetime_timeout
;
1425 uint64_t t2_timeout
;
1426 uint64_t t1_timeout
;
1427 char time_string
[FORMAT_TIMESPAN_MAX
];
1431 assert(client
->event
);
1432 assert(client
->lease
);
1433 assert(client
->lease
->lifetime
);
1435 /* don't set timers for infinite leases */
1436 if (client
->lease
->lifetime
== 0xffffffff) {
1437 (void) event_source_disable(client
->timeout_t1
);
1438 (void) event_source_disable(client
->timeout_t2
);
1439 (void) event_source_disable(client
->timeout_expire
);
1444 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1447 assert(client
->request_sent
<= time_now
);
1449 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1450 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1451 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1452 /* both T1 and T2 are given */
1453 if (client
->lease
->t1
< client
->lease
->t2
&&
1454 client
->lease
->t2
< client
->lease
->lifetime
) {
1455 /* they are both valid */
1456 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1457 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1460 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1461 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1462 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1463 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1465 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1466 /* only T2 is given, and it is valid */
1467 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1468 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1469 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1470 if (t2_timeout
<= t1_timeout
) {
1471 /* the computed T1 would be invalid, so discard T2 */
1472 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1473 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1475 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1476 /* only T1 is given, and it is valid */
1477 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1478 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1479 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1480 if (t2_timeout
<= t1_timeout
) {
1481 /* the computed T2 would be invalid, so discard T1 */
1482 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1483 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1486 /* fall back to the default timeouts */
1487 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1488 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1489 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1490 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1493 /* arm lifetime timeout */
1494 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1495 clock_boottime_or_monotonic(),
1496 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1497 client_timeout_expire
, client
,
1498 client
->event_priority
, "dhcp4-lifetime", true);
1502 log_dhcp_client(client
, "lease expires in %s",
1503 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1505 /* don't arm earlier timeouts if this has already expired */
1506 if (lifetime_timeout
<= time_now
)
1509 /* arm T2 timeout */
1510 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1511 clock_boottime_or_monotonic(),
1512 t2_timeout
, 10 * USEC_PER_MSEC
,
1513 client_timeout_t2
, client
,
1514 client
->event_priority
, "dhcp4-t2-timeout", true);
1518 log_dhcp_client(client
, "T2 expires in %s",
1519 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1521 /* don't arm earlier timeout if this has already expired */
1522 if (t2_timeout
<= time_now
)
1525 /* arm T1 timeout */
1526 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1527 clock_boottime_or_monotonic(),
1528 t1_timeout
, 10 * USEC_PER_MSEC
,
1529 client_timeout_t1
, client
,
1530 client
->event_priority
, "dhcp4-t1-timer", true);
1534 log_dhcp_client(client
, "T1 expires in %s",
1535 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1540 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1541 DHCP_CLIENT_DONT_DESTROY(client
);
1542 char time_string
[FORMAT_TIMESPAN_MAX
];
1543 int r
= 0, notify_event
= 0;
1546 assert(client
->event
);
1549 switch (client
->state
) {
1550 case DHCP_STATE_SELECTING
:
1552 r
= client_handle_offer(client
, message
, len
);
1555 client
->state
= DHCP_STATE_REQUESTING
;
1556 client
->attempt
= 1;
1558 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1559 clock_boottime_or_monotonic(),
1561 client_timeout_resend
, client
,
1562 client
->event_priority
, "dhcp4-resend-timer", true);
1565 } else if (r
== -ENOMSG
)
1566 /* invalid message, let's ignore it */
1571 case DHCP_STATE_REBOOTING
:
1572 case DHCP_STATE_REQUESTING
:
1573 case DHCP_STATE_RENEWING
:
1574 case DHCP_STATE_REBINDING
:
1576 r
= client_handle_ack(client
, message
, len
);
1578 client
->start_delay
= 0;
1579 (void) event_source_disable(client
->timeout_resend
);
1580 client
->receive_message
=
1581 sd_event_source_unref(client
->receive_message
);
1582 client
->fd
= asynchronous_close(client
->fd
);
1584 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1585 DHCP_STATE_REBOOTING
))
1586 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1587 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1590 client
->state
= DHCP_STATE_BOUND
;
1591 client
->attempt
= 1;
1593 client
->last_addr
= client
->lease
->address
;
1595 r
= client_set_lease_timeouts(client
);
1597 log_dhcp_client(client
, "could not set lease timeouts");
1601 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1603 log_dhcp_client(client
, "could not bind UDP socket");
1609 client_initialize_io_events(client
, client_receive_message_udp
);
1612 client_notify(client
, notify_event
);
1613 if (client
->state
== DHCP_STATE_STOPPED
)
1617 } else if (r
== -EADDRNOTAVAIL
) {
1618 /* got a NAK, let's restart the client */
1619 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1621 r
= client_initialize(client
);
1625 r
= client_start_delayed(client
);
1629 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1630 client
->start_delay
, USEC_PER_SEC
));
1632 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1633 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1636 } else if (r
== -ENOMSG
)
1637 /* invalid message, let's ignore it */
1642 case DHCP_STATE_BOUND
:
1643 r
= client_handle_forcerenew(client
, message
, len
);
1645 r
= client_timeout_t1(NULL
, 0, client
);
1648 } else if (r
== -ENOMSG
)
1649 /* invalid message, let's ignore it */
1654 case DHCP_STATE_INIT
:
1655 case DHCP_STATE_INIT_REBOOT
:
1659 case DHCP_STATE_STOPPED
:
1666 client_stop(client
, r
);
1671 static int client_receive_message_udp(
1677 sd_dhcp_client
*client
= userdata
;
1678 _cleanup_free_ DHCPMessage
*message
= NULL
;
1679 const uint8_t *expected_chaddr
= NULL
;
1680 uint8_t expected_hlen
= 0;
1681 ssize_t len
, buflen
;
1686 buflen
= next_datagram_size_fd(fd
);
1687 if (buflen
== -ENETDOWN
) {
1688 /* the link is down. Don't return an error or the I/O event
1689 source will be disconnected and we won't be able to receive
1690 packets again when the link comes back. */
1696 message
= malloc0(buflen
);
1700 len
= recv(fd
, message
, buflen
, 0);
1702 /* see comment above for why we shouldn't error out on ENETDOWN. */
1703 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1706 return log_dhcp_client_errno(client
, errno
,
1707 "Could not receive message from UDP socket: %m");
1709 if ((size_t) len
< sizeof(DHCPMessage
)) {
1710 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1714 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1715 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1719 if (message
->op
!= BOOTREPLY
) {
1720 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1724 if (message
->htype
!= client
->arp_type
) {
1725 log_dhcp_client(client
, "Packet type does not match client type");
1729 if (client
->arp_type
== ARPHRD_ETHER
) {
1730 expected_hlen
= ETH_ALEN
;
1731 expected_chaddr
= &client
->mac_addr
[0];
1734 if (message
->hlen
!= expected_hlen
) {
1735 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1739 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1740 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1744 if (client
->state
!= DHCP_STATE_BOUND
&&
1745 be32toh(message
->xid
) != client
->xid
) {
1746 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1747 so ignore the xid in this case */
1748 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1749 be32toh(message
->xid
), client
->xid
);
1753 return client_handle_message(client
, message
, len
);
1756 static int client_receive_message_raw(
1762 sd_dhcp_client
*client
= userdata
;
1763 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1764 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1765 struct iovec iov
= {};
1766 struct msghdr msg
= {
1769 .msg_control
= cmsgbuf
,
1770 .msg_controllen
= sizeof(cmsgbuf
),
1772 struct cmsghdr
*cmsg
;
1773 bool checksum
= true;
1774 ssize_t buflen
, len
;
1780 buflen
= next_datagram_size_fd(fd
);
1781 if (buflen
== -ENETDOWN
)
1786 packet
= malloc0(buflen
);
1790 iov
= IOVEC_MAKE(packet
, buflen
);
1792 len
= recvmsg(fd
, &msg
, 0);
1794 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1797 return log_dhcp_client_errno(client
, errno
,
1798 "Could not receive message from raw socket: %m");
1799 } else if ((size_t)len
< sizeof(DHCPPacket
))
1802 CMSG_FOREACH(cmsg
, &msg
)
1803 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1804 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1805 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1806 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1808 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1812 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1816 len
-= DHCP_IP_UDP_SIZE
;
1818 return client_handle_message(client
, &packet
->dhcp
, len
);
1821 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1824 assert_return(client
, -EINVAL
);
1826 r
= client_initialize(client
);
1830 /* RFC7844 section 3.3:
1831 SHOULD perform a complete four-way handshake, starting with a
1832 DHCPDISCOVER, to obtain a new address lease. If the client can
1833 ascertain that this is exactly the same network to which it was
1834 previously connected, and if the link-layer address did not change,
1835 the client MAY issue a DHCPREQUEST to try to reclaim the current
1837 if (client
->last_addr
&& !client
->anonymize
)
1838 client
->state
= DHCP_STATE_INIT_REBOOT
;
1840 r
= client_start(client
);
1842 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1847 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1848 DHCP_CLIENT_DONT_DESTROY(client
);
1850 assert_return(client
, -EINVAL
);
1852 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1853 client
->state
= DHCP_STATE_STOPPED
;
1858 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1861 assert_return(client
, -EINVAL
);
1862 assert_return(!client
->event
, -EBUSY
);
1865 client
->event
= sd_event_ref(event
);
1867 r
= sd_event_default(&client
->event
);
1872 client
->event_priority
= priority
;
1877 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1878 assert_return(client
, -EINVAL
);
1880 client
->event
= sd_event_unref(client
->event
);
1885 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1886 assert_return(client
, NULL
);
1888 return client
->event
;
1891 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1894 log_dhcp_client(client
, "FREE");
1896 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1897 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1898 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1899 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1901 client_initialize(client
);
1903 sd_dhcp_client_detach_event(client
);
1905 sd_dhcp_lease_unref(client
->lease
);
1907 free(client
->req_opts
);
1908 free(client
->hostname
);
1909 free(client
->vendor_class_identifier
);
1910 client
->user_class
= strv_free(client
->user_class
);
1911 return mfree(client
);
1914 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1916 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1917 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1919 assert_return(ret
, -EINVAL
);
1921 client
= new(sd_dhcp_client
, 1);
1925 *client
= (sd_dhcp_client
) {
1927 .state
= DHCP_STATE_INIT
,
1931 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1932 .port
= DHCP_PORT_CLIENT
,
1933 .anonymize
= !!anonymize
,
1935 /* NOTE: this could be moved to a function. */
1937 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1938 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1940 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1941 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1943 if (!client
->req_opts
)
1946 *ret
= TAKE_PTR(client
);