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 struct ether_addr zero_mac
= {};
1680 const struct ether_addr
*expected_chaddr
= NULL
;
1681 uint8_t expected_hlen
= 0;
1682 ssize_t len
, buflen
;
1687 buflen
= next_datagram_size_fd(fd
);
1691 message
= malloc0(buflen
);
1695 len
= recv(fd
, message
, buflen
, 0);
1697 if (IN_SET(errno
, EAGAIN
, EINTR
))
1700 return log_dhcp_client_errno(client
, errno
,
1701 "Could not receive message from UDP socket: %m");
1703 if ((size_t) len
< sizeof(DHCPMessage
)) {
1704 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1708 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1709 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1713 if (message
->op
!= BOOTREPLY
) {
1714 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1718 if (message
->htype
!= client
->arp_type
) {
1719 log_dhcp_client(client
, "Packet type does not match client type");
1723 if (client
->arp_type
== ARPHRD_ETHER
) {
1724 expected_hlen
= ETH_ALEN
;
1725 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1727 /* Non-Ethernet links expect zero chaddr */
1729 expected_chaddr
= &zero_mac
;
1732 if (message
->hlen
!= expected_hlen
) {
1733 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1737 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1738 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1742 if (client
->state
!= DHCP_STATE_BOUND
&&
1743 be32toh(message
->xid
) != client
->xid
) {
1744 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1745 so ignore the xid in this case */
1746 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1747 be32toh(message
->xid
), client
->xid
);
1751 return client_handle_message(client
, message
, len
);
1754 static int client_receive_message_raw(
1760 sd_dhcp_client
*client
= userdata
;
1761 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1762 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1763 struct iovec iov
= {};
1764 struct msghdr msg
= {
1767 .msg_control
= cmsgbuf
,
1768 .msg_controllen
= sizeof(cmsgbuf
),
1770 struct cmsghdr
*cmsg
;
1771 bool checksum
= true;
1772 ssize_t buflen
, len
;
1778 buflen
= next_datagram_size_fd(fd
);
1782 packet
= malloc0(buflen
);
1786 iov
= IOVEC_MAKE(packet
, buflen
);
1788 len
= recvmsg(fd
, &msg
, 0);
1790 if (IN_SET(errno
, EAGAIN
, EINTR
))
1793 return log_dhcp_client_errno(client
, errno
,
1794 "Could not receive message from raw socket: %m");
1795 } else if ((size_t)len
< sizeof(DHCPPacket
))
1798 CMSG_FOREACH(cmsg
, &msg
)
1799 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1800 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1801 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1802 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1804 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1808 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1812 len
-= DHCP_IP_UDP_SIZE
;
1814 return client_handle_message(client
, &packet
->dhcp
, len
);
1817 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1820 assert_return(client
, -EINVAL
);
1822 r
= client_initialize(client
);
1826 /* RFC7844 section 3.3:
1827 SHOULD perform a complete four-way handshake, starting with a
1828 DHCPDISCOVER, to obtain a new address lease. If the client can
1829 ascertain that this is exactly the same network to which it was
1830 previously connected, and if the link-layer address did not change,
1831 the client MAY issue a DHCPREQUEST to try to reclaim the current
1833 if (client
->last_addr
&& !client
->anonymize
)
1834 client
->state
= DHCP_STATE_INIT_REBOOT
;
1836 r
= client_start(client
);
1838 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1843 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1844 DHCP_CLIENT_DONT_DESTROY(client
);
1846 assert_return(client
, -EINVAL
);
1848 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1849 client
->state
= DHCP_STATE_STOPPED
;
1854 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1857 assert_return(client
, -EINVAL
);
1858 assert_return(!client
->event
, -EBUSY
);
1861 client
->event
= sd_event_ref(event
);
1863 r
= sd_event_default(&client
->event
);
1868 client
->event_priority
= priority
;
1873 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1874 assert_return(client
, -EINVAL
);
1876 client
->event
= sd_event_unref(client
->event
);
1881 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1882 assert_return(client
, NULL
);
1884 return client
->event
;
1887 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1890 log_dhcp_client(client
, "FREE");
1892 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1893 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1894 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1895 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1897 client_initialize(client
);
1899 sd_dhcp_client_detach_event(client
);
1901 sd_dhcp_lease_unref(client
->lease
);
1903 free(client
->req_opts
);
1904 free(client
->hostname
);
1905 free(client
->vendor_class_identifier
);
1906 client
->user_class
= strv_free(client
->user_class
);
1907 return mfree(client
);
1910 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1912 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1913 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1915 assert_return(ret
, -EINVAL
);
1917 client
= new(sd_dhcp_client
, 1);
1921 *client
= (sd_dhcp_client
) {
1923 .state
= DHCP_STATE_INIT
,
1927 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1928 .port
= DHCP_PORT_CLIENT
,
1929 .anonymize
= !!anonymize
,
1931 /* NOTE: this could be moved to a function. */
1933 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1934 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1936 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1937 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1939 if (!client
->req_opts
)
1942 *ret
= TAKE_PTR(client
);