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 "memory-util.h"
28 #include "random-util.h"
29 #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
;
92 uint64_t max_attempts
;
94 sd_event_source
*timeout_t1
;
95 sd_event_source
*timeout_t2
;
96 sd_event_source
*timeout_expire
;
97 sd_dhcp_client_callback_t callback
;
103 static const uint8_t default_req_opts
[] = {
104 SD_DHCP_OPTION_SUBNET_MASK
,
105 SD_DHCP_OPTION_ROUTER
,
106 SD_DHCP_OPTION_HOST_NAME
,
107 SD_DHCP_OPTION_DOMAIN_NAME
,
108 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
111 /* RFC7844 section 3:
112 MAY contain the Parameter Request List option.
114 The client intending to protect its privacy SHOULD only request a
115 minimal number of options in the PRL and SHOULD also randomly shuffle
116 the ordering of option codes in the PRL. If this random ordering
117 cannot be implemented, the client MAY order the option codes in the
118 PRL by option code number (lowest to highest).
120 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
121 static const uint8_t default_req_opts_anonymize
[] = {
122 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
123 SD_DHCP_OPTION_ROUTER
, /* 3 */
124 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
125 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
126 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
127 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
128 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
129 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
130 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
131 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
132 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
133 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
134 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
137 static int client_receive_message_raw(
142 static int client_receive_message_udp(
147 static void client_stop(sd_dhcp_client
*client
, int error
);
149 int sd_dhcp_client_set_callback(
150 sd_dhcp_client
*client
,
151 sd_dhcp_client_callback_t cb
,
154 assert_return(client
, -EINVAL
);
156 client
->callback
= cb
;
157 client
->userdata
= userdata
;
162 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
163 assert_return(client
, -EINVAL
);
165 client
->request_broadcast
= !!broadcast
;
170 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
173 assert_return(client
, -EINVAL
);
174 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
178 case SD_DHCP_OPTION_PAD
:
179 case SD_DHCP_OPTION_OVERLOAD
:
180 case SD_DHCP_OPTION_MESSAGE_TYPE
:
181 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
182 case SD_DHCP_OPTION_END
:
189 for (i
= 0; i
< client
->req_opts_size
; i
++)
190 if (client
->req_opts
[i
] == option
)
193 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
194 client
->req_opts_size
+ 1))
197 client
->req_opts
[client
->req_opts_size
++] = option
;
202 int sd_dhcp_client_set_request_address(
203 sd_dhcp_client
*client
,
204 const struct in_addr
*last_addr
) {
206 assert_return(client
, -EINVAL
);
207 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
210 client
->last_addr
= last_addr
->s_addr
;
212 client
->last_addr
= INADDR_ANY
;
217 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
219 assert_return(client
, -EINVAL
);
220 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
221 assert_return(ifindex
> 0, -EINVAL
);
223 client
->ifindex
= ifindex
;
227 int sd_dhcp_client_set_mac(
228 sd_dhcp_client
*client
,
233 DHCP_CLIENT_DONT_DESTROY(client
);
234 bool need_restart
= false;
236 assert_return(client
, -EINVAL
);
237 assert_return(addr
, -EINVAL
);
238 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
239 assert_return(arp_type
> 0, -EINVAL
);
241 if (arp_type
== ARPHRD_ETHER
)
242 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
243 else if (arp_type
== ARPHRD_INFINIBAND
)
244 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
248 if (client
->mac_addr_len
== addr_len
&&
249 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
252 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
253 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
255 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
258 memcpy(&client
->mac_addr
, addr
, addr_len
);
259 client
->mac_addr_len
= addr_len
;
260 client
->arp_type
= arp_type
;
262 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
263 sd_dhcp_client_start(client
);
268 int sd_dhcp_client_get_client_id(
269 sd_dhcp_client
*client
,
271 const uint8_t **data
,
274 assert_return(client
, -EINVAL
);
275 assert_return(type
, -EINVAL
);
276 assert_return(data
, -EINVAL
);
277 assert_return(data_len
, -EINVAL
);
282 if (client
->client_id_len
) {
283 *type
= client
->client_id
.type
;
284 *data
= client
->client_id
.raw
.data
;
285 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
291 int sd_dhcp_client_set_client_id(
292 sd_dhcp_client
*client
,
297 DHCP_CLIENT_DONT_DESTROY(client
);
298 bool need_restart
= false;
300 assert_return(client
, -EINVAL
);
301 assert_return(data
, -EINVAL
);
302 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
304 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
305 client
->client_id
.type
== type
&&
306 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
309 /* For hardware types, log debug message about unexpected data length.
311 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
312 * last last 8 bytes of the address are stable and suitable to put into
313 * the client-id. The caller is advised to account for that. */
314 if ((type
== ARPHRD_ETHER
&& data_len
!= ETH_ALEN
) ||
315 (type
== ARPHRD_INFINIBAND
&& data_len
!= 8))
316 log_dhcp_client(client
, "Changing client ID to hardware type %u with "
317 "unexpected address length %zu",
320 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
321 log_dhcp_client(client
, "Changing client ID on running DHCP "
322 "client, restarting");
324 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
327 client
->client_id
.type
= type
;
328 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
329 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
331 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
332 sd_dhcp_client_start(client
);
338 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
339 * without further modification. Otherwise, if duid_type is supported, DUID
340 * is set based on that type. Otherwise, an error is returned.
342 static int dhcp_client_set_iaid_duid_internal(
343 sd_dhcp_client
*client
,
352 DHCP_CLIENT_DONT_DESTROY(client
);
356 assert_return(client
, -EINVAL
);
357 assert_return(duid_len
== 0 || duid
, -EINVAL
);
360 r
= dhcp_validate_duid_len(duid_type
, duid_len
, true);
365 zero(client
->client_id
);
366 client
->client_id
.type
= 255;
370 client
->client_id
.ns
.iaid
= htobe32(iaid
);
372 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
373 client
->mac_addr_len
,
375 &client
->client_id
.ns
.iaid
);
382 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
383 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
384 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
388 if (client
->mac_addr_len
== 0)
391 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
396 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
401 if (client
->mac_addr_len
== 0)
404 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
409 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
417 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
418 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
420 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
421 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
422 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
423 sd_dhcp_client_start(client
);
429 int sd_dhcp_client_set_iaid_duid(
430 sd_dhcp_client
*client
,
436 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
439 int sd_dhcp_client_set_iaid_duid_llt(
440 sd_dhcp_client
*client
,
444 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
447 int sd_dhcp_client_set_duid(
448 sd_dhcp_client
*client
,
452 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
455 int sd_dhcp_client_set_duid_llt(
456 sd_dhcp_client
*client
,
458 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
461 int sd_dhcp_client_set_hostname(
462 sd_dhcp_client
*client
,
463 const char *hostname
) {
465 assert_return(client
, -EINVAL
);
467 /* Make sure hostnames qualify as DNS and as Linux hostnames */
469 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
472 return free_and_strdup(&client
->hostname
, hostname
);
475 int sd_dhcp_client_set_vendor_class_identifier(
476 sd_dhcp_client
*client
,
479 assert_return(client
, -EINVAL
);
481 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
484 int sd_dhcp_client_set_user_class(
485 sd_dhcp_client
*client
,
486 const char* const* user_class
) {
488 _cleanup_strv_free_
char **s
= NULL
;
491 STRV_FOREACH(p
, (char **) user_class
)
492 if (strlen(*p
) > 255)
493 return -ENAMETOOLONG
;
495 s
= strv_copy((char **) user_class
);
499 client
->user_class
= TAKE_PTR(s
);
504 int sd_dhcp_client_set_client_port(
505 sd_dhcp_client
*client
,
508 assert_return(client
, -EINVAL
);
515 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
516 assert_return(client
, -EINVAL
);
517 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
524 int sd_dhcp_client_set_max_attempts(sd_dhcp_client
*client
, uint64_t max_attempts
) {
525 assert_return(client
, -EINVAL
);
527 client
->max_attempts
= max_attempts
;
532 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
533 assert_return(client
, -EINVAL
);
535 if (!IN_SET(client
->state
, DHCP_STATE_SELECTING
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
536 return -EADDRNOTAVAIL
;
539 *ret
= client
->lease
;
544 static int client_notify(sd_dhcp_client
*client
, int event
) {
547 if (client
->callback
)
548 return client
->callback(client
, event
, client
->userdata
);
553 static int client_initialize(sd_dhcp_client
*client
) {
554 assert_return(client
, -EINVAL
);
556 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
558 client
->fd
= asynchronous_close(client
->fd
);
560 (void) event_source_disable(client
->timeout_resend
);
561 (void) event_source_disable(client
->timeout_t1
);
562 (void) event_source_disable(client
->timeout_t2
);
563 (void) event_source_disable(client
->timeout_expire
);
567 client
->state
= DHCP_STATE_INIT
;
570 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
575 static void client_stop(sd_dhcp_client
*client
, int error
) {
579 log_dhcp_client_errno(client
, error
, "STOPPED: %m");
580 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
581 log_dhcp_client(client
, "STOPPED");
583 log_dhcp_client(client
, "STOPPED: Unknown event");
585 client_notify(client
, error
);
587 client_initialize(client
);
590 static int client_message_init(
591 sd_dhcp_client
*client
,
595 size_t *_optoffset
) {
597 _cleanup_free_ DHCPPacket
*packet
= NULL
;
598 size_t optlen
, optoffset
, size
;
605 assert(client
->start_time
);
609 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
, DHCP_RELEASE
));
611 optlen
= DHCP_MIN_OPTIONS_SIZE
;
612 size
= sizeof(DHCPPacket
) + optlen
;
614 packet
= malloc0(size
);
618 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
619 client
->arp_type
, optlen
, &optoffset
);
623 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
624 refuse to issue an DHCP lease if 'secs' is set to zero */
625 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
628 assert(time_now
>= client
->start_time
);
630 /* seconds between sending first and last DISCOVER
631 * must always be strictly positive to deal with broken servers */
632 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
633 packet
->dhcp
.secs
= htobe16(secs
);
635 /* RFC2132 section 4.1
636 A client that cannot receive unicast IP datagrams until its protocol
637 software has been configured with an IP address SHOULD set the
638 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
639 DHCPREQUEST messages that client sends. The BROADCAST bit will
640 provide a hint to the DHCP server and BOOTP relay agent to broadcast
641 any messages to the client on the client's subnet.
643 Note: some interfaces needs this to be enabled, but some networks
644 needs this to be disabled as broadcasts are filteretd, so this
645 needs to be configurable */
646 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
647 packet
->dhcp
.flags
= htobe16(0x8000);
649 /* RFC2132 section 4.1.1:
650 The client MUST include its hardware address in the ’chaddr’ field, if
651 necessary for delivery of DHCP reply messages. Non-Ethernet
652 interfaces will leave 'chaddr' empty and use the client identifier
653 instead (eg, RFC 4390 section 2.1).
655 if (client
->arp_type
== ARPHRD_ETHER
)
656 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
658 /* If no client identifier exists, construct an RFC 4361-compliant one */
659 if (client
->client_id_len
== 0) {
662 client
->client_id
.type
= 255;
664 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
665 true, &client
->client_id
.ns
.iaid
);
669 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
673 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
676 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
677 Identifier option is not set */
678 if (client
->client_id_len
) {
679 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
680 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
681 client
->client_id_len
,
687 /* RFC2131 section 3.5:
688 in its initial DHCPDISCOVER or DHCPREQUEST message, a
689 client may provide the server with a list of specific
690 parameters the client is interested in. If the client
691 includes a list of parameters in a DHCPDISCOVER message,
692 it MUST include that list in any subsequent DHCPREQUEST
696 /* RFC7844 section 3:
697 MAY contain the Parameter Request List option. */
698 /* NOTE: in case that there would be an option to do not send
699 * any PRL at all, the size should be checked before sending */
700 if (client
->req_opts_size
> 0 && type
!= DHCP_RELEASE
) {
701 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
702 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
703 client
->req_opts_size
, client
->req_opts
);
708 /* RFC2131 section 3.5:
709 The client SHOULD include the ’maximum DHCP message size’ option to
710 let the server know how large the server may make its DHCP messages.
712 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
713 than the defined default size unless the Maximum Message Size option
716 RFC3442 "Requirements to Avoid Sizing Constraints":
717 Because a full routing table can be quite large, the standard 576
718 octet maximum size for a DHCP message may be too short to contain
719 some legitimate Classless Static Route options. Because of this,
720 clients implementing the Classless Static Route option SHOULD send a
721 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
722 stack is capable of receiving larger IP datagrams. In this case, the
723 client SHOULD set the value of this option to at least the MTU of the
724 interface that the client is configuring. The client MAY set the
725 value of this option higher, up to the size of the largest UDP packet
726 it is prepared to accept. (Note that the value specified in the
727 Maximum DHCP Message Size option is the total maximum packet size,
728 including IP and UDP headers.)
730 /* RFC7844 section 3:
731 SHOULD NOT contain any other option. */
732 if (!client
->anonymize
&& type
!= DHCP_RELEASE
) {
733 max_size
= htobe16(size
);
734 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
735 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
742 *_optoffset
= optoffset
;
743 *ret
= TAKE_PTR(packet
);
748 static int client_append_fqdn_option(
749 DHCPMessage
*message
,
754 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
757 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
758 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
759 buffer
[1] = 0; /* RCODE1 (deprecated) */
760 buffer
[2] = 0; /* RCODE2 (deprecated) */
762 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
764 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
765 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
770 static int dhcp_client_send_raw(
771 sd_dhcp_client
*client
,
775 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
776 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
778 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
782 static int client_send_discover(sd_dhcp_client
*client
) {
783 _cleanup_free_ DHCPPacket
*discover
= NULL
;
784 size_t optoffset
, optlen
;
788 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
790 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
791 &optlen
, &optoffset
);
795 /* the client may suggest values for the network address
796 and lease time in the DHCPDISCOVER message. The client may include
797 the ’requested IP address’ option to suggest that a particular IP
798 address be assigned, and may include the ’IP address lease time’
799 option to suggest the lease time it would like.
801 if (client
->last_addr
!= INADDR_ANY
) {
802 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
803 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
804 4, &client
->last_addr
);
809 if (client
->hostname
) {
810 /* According to RFC 4702 "clients that send the Client FQDN option in
811 their messages MUST NOT also send the Host Name option". Just send
812 one of the two depending on the hostname type.
814 if (dns_name_is_single_label(client
->hostname
)) {
815 /* it is unclear from RFC 2131 if client should send hostname in
816 DHCPDISCOVER but dhclient does and so we do as well
818 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
819 SD_DHCP_OPTION_HOST_NAME
,
820 strlen(client
->hostname
), client
->hostname
);
822 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
828 if (client
->vendor_class_identifier
) {
829 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
830 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
831 strlen(client
->vendor_class_identifier
),
832 client
->vendor_class_identifier
);
837 if (client
->user_class
) {
838 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
839 SD_DHCP_OPTION_USER_CLASS
,
840 strv_length(client
->user_class
),
846 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
847 SD_DHCP_OPTION_END
, 0, NULL
);
851 /* We currently ignore:
852 The client SHOULD wait a random time between one and ten seconds to
853 desynchronize the use of DHCP at startup.
855 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
859 log_dhcp_client(client
, "DISCOVER");
864 static int client_send_release(sd_dhcp_client
*client
) {
865 _cleanup_free_ DHCPPacket
*release
= NULL
;
866 size_t optoffset
, optlen
;
870 assert(!IN_SET(client
->state
, DHCP_STATE_STOPPED
));
872 r
= client_message_init(client
, &release
, DHCP_RELEASE
,
873 &optlen
, &optoffset
);
877 /* Fill up release IP and MAC */
878 release
->dhcp
.ciaddr
= client
->lease
->address
;
879 memcpy(&release
->dhcp
.chaddr
, &client
->mac_addr
, client
->mac_addr_len
);
881 r
= dhcp_option_append(&release
->dhcp
, optlen
, &optoffset
, 0,
882 SD_DHCP_OPTION_END
, 0, NULL
);
886 r
= dhcp_network_send_udp_socket(client
->fd
,
887 client
->lease
->server_address
,
890 sizeof(DHCPMessage
) + optoffset
);
894 log_dhcp_client(client
, "RELEASE");
899 static int client_send_request(sd_dhcp_client
*client
) {
900 _cleanup_free_ DHCPPacket
*request
= NULL
;
901 size_t optoffset
, optlen
;
906 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
910 switch (client
->state
) {
911 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
912 SELECTING should be REQUESTING)
915 case DHCP_STATE_REQUESTING
:
916 /* Client inserts the address of the selected server in ’server
917 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
918 filled in with the yiaddr value from the chosen DHCPOFFER.
921 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
922 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
923 4, &client
->lease
->server_address
);
927 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
928 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
929 4, &client
->lease
->address
);
935 case DHCP_STATE_INIT_REBOOT
:
936 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
937 option MUST be filled in with client’s notion of its previously
938 assigned address. ’ciaddr’ MUST be zero.
940 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
941 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
942 4, &client
->last_addr
);
947 case DHCP_STATE_RENEWING
:
948 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
949 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
953 case DHCP_STATE_REBINDING
:
954 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
955 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
958 This message MUST be broadcast to the 0xffffffff IP broadcast address.
960 request
->dhcp
.ciaddr
= client
->lease
->address
;
964 case DHCP_STATE_INIT
:
965 case DHCP_STATE_SELECTING
:
966 case DHCP_STATE_REBOOTING
:
967 case DHCP_STATE_BOUND
:
968 case DHCP_STATE_STOPPED
:
972 if (client
->hostname
) {
973 if (dns_name_is_single_label(client
->hostname
))
974 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
975 SD_DHCP_OPTION_HOST_NAME
,
976 strlen(client
->hostname
), client
->hostname
);
978 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
984 if (client
->vendor_class_identifier
) {
985 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
986 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
987 strlen(client
->vendor_class_identifier
),
988 client
->vendor_class_identifier
);
993 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
994 SD_DHCP_OPTION_END
, 0, NULL
);
998 if (client
->state
== DHCP_STATE_RENEWING
)
999 r
= dhcp_network_send_udp_socket(client
->fd
,
1000 client
->lease
->server_address
,
1003 sizeof(DHCPMessage
) + optoffset
);
1005 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
1009 switch (client
->state
) {
1011 case DHCP_STATE_REQUESTING
:
1012 log_dhcp_client(client
, "REQUEST (requesting)");
1015 case DHCP_STATE_INIT_REBOOT
:
1016 log_dhcp_client(client
, "REQUEST (init-reboot)");
1019 case DHCP_STATE_RENEWING
:
1020 log_dhcp_client(client
, "REQUEST (renewing)");
1023 case DHCP_STATE_REBINDING
:
1024 log_dhcp_client(client
, "REQUEST (rebinding)");
1028 log_dhcp_client(client
, "REQUEST (invalid)");
1035 static int client_start(sd_dhcp_client
*client
);
1037 static int client_timeout_resend(
1042 sd_dhcp_client
*client
= userdata
;
1043 DHCP_CLIENT_DONT_DESTROY(client
);
1044 usec_t next_timeout
= 0;
1051 assert(client
->event
);
1053 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1057 switch (client
->state
) {
1059 case DHCP_STATE_RENEWING
:
1061 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1065 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1069 case DHCP_STATE_REBINDING
:
1071 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1075 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1078 case DHCP_STATE_REBOOTING
:
1079 /* start over as we did not receive a timely ack or nak */
1080 r
= client_initialize(client
);
1084 r
= client_start(client
);
1088 log_dhcp_client(client
, "REBOOTED");
1092 case DHCP_STATE_INIT
:
1093 case DHCP_STATE_INIT_REBOOT
:
1094 case DHCP_STATE_SELECTING
:
1095 case DHCP_STATE_REQUESTING
:
1096 case DHCP_STATE_BOUND
:
1098 if (client
->attempt
< client
->max_attempts
)
1103 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1107 case DHCP_STATE_STOPPED
:
1112 next_timeout
+= (random_u32() & 0x1fffff);
1114 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1115 clock_boottime_or_monotonic(),
1116 next_timeout
, 10 * USEC_PER_MSEC
,
1117 client_timeout_resend
, client
,
1118 client
->event_priority
, "dhcp4-resend-timer", true);
1122 switch (client
->state
) {
1123 case DHCP_STATE_INIT
:
1124 r
= client_send_discover(client
);
1126 client
->state
= DHCP_STATE_SELECTING
;
1127 client
->attempt
= 0;
1128 } else if (client
->attempt
>= client
->max_attempts
)
1133 case DHCP_STATE_SELECTING
:
1134 r
= client_send_discover(client
);
1135 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1140 case DHCP_STATE_INIT_REBOOT
:
1141 case DHCP_STATE_REQUESTING
:
1142 case DHCP_STATE_RENEWING
:
1143 case DHCP_STATE_REBINDING
:
1144 r
= client_send_request(client
);
1145 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1148 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1149 client
->state
= DHCP_STATE_REBOOTING
;
1151 client
->request_sent
= time_now
;
1155 case DHCP_STATE_REBOOTING
:
1156 case DHCP_STATE_BOUND
:
1160 case DHCP_STATE_STOPPED
:
1168 client_stop(client
, r
);
1170 /* Errors were dealt with when stopping the client, don't spill
1171 errors into the event loop handler */
1175 static int client_initialize_io_events(
1176 sd_dhcp_client
*client
,
1177 sd_event_io_handler_t io_callback
) {
1182 assert(client
->event
);
1184 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1185 client
->fd
, EPOLLIN
, io_callback
,
1190 r
= sd_event_source_set_priority(client
->receive_message
,
1191 client
->event_priority
);
1195 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1201 client_stop(client
, r
);
1206 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1211 assert(client
->event
);
1213 if (client
->start_delay
> 0) {
1214 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1215 usec
+= client
->start_delay
;
1218 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1219 clock_boottime_or_monotonic(),
1221 client_timeout_resend
, client
,
1222 client
->event_priority
, "dhcp4-resend-timer", true);
1224 client_stop(client
, r
);
1230 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1231 client_initialize_io_events(client
, io_callback
);
1232 client_initialize_time_events(client
);
1237 static int client_start_delayed(sd_dhcp_client
*client
) {
1240 assert_return(client
, -EINVAL
);
1241 assert_return(client
->event
, -EINVAL
);
1242 assert_return(client
->ifindex
> 0, -EINVAL
);
1243 assert_return(client
->fd
< 0, -EBUSY
);
1244 assert_return(client
->xid
== 0, -EINVAL
);
1245 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1247 client
->xid
= random_u32();
1249 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1250 client
->xid
, client
->mac_addr
,
1251 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1253 client_stop(client
, r
);
1258 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1259 client
->start_time
= now(clock_boottime_or_monotonic());
1261 return client_initialize_events(client
, client_receive_message_raw
);
1264 static int client_start(sd_dhcp_client
*client
) {
1265 client
->start_delay
= 0;
1266 return client_start_delayed(client
);
1269 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1270 sd_dhcp_client
*client
= userdata
;
1271 DHCP_CLIENT_DONT_DESTROY(client
);
1273 log_dhcp_client(client
, "EXPIRED");
1275 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1277 /* lease was lost, start over if not freed or stopped in callback */
1278 if (client
->state
!= DHCP_STATE_STOPPED
) {
1279 client_initialize(client
);
1280 client_start(client
);
1286 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1287 sd_dhcp_client
*client
= userdata
;
1288 DHCP_CLIENT_DONT_DESTROY(client
);
1293 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1294 client
->fd
= asynchronous_close(client
->fd
);
1296 client
->state
= DHCP_STATE_REBINDING
;
1297 client
->attempt
= 0;
1299 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1300 client
->xid
, client
->mac_addr
,
1301 client
->mac_addr_len
, client
->arp_type
,
1304 client_stop(client
, r
);
1309 return client_initialize_events(client
, client_receive_message_raw
);
1312 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1313 sd_dhcp_client
*client
= userdata
;
1314 DHCP_CLIENT_DONT_DESTROY(client
);
1316 client
->state
= DHCP_STATE_RENEWING
;
1317 client
->attempt
= 0;
1319 return client_initialize_time_events(client
);
1322 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1323 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1326 r
= dhcp_lease_new(&lease
);
1330 if (client
->client_id_len
) {
1331 r
= dhcp_lease_set_client_id(lease
,
1332 (uint8_t *) &client
->client_id
,
1333 client
->client_id_len
);
1338 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1339 if (r
!= DHCP_OFFER
) {
1340 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1344 lease
->next_server
= offer
->siaddr
;
1345 lease
->address
= offer
->yiaddr
;
1347 if (lease
->address
== 0 ||
1348 lease
->server_address
== 0 ||
1349 lease
->lifetime
== 0) {
1350 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1354 if (!lease
->have_subnet_mask
) {
1355 r
= dhcp_lease_set_default_subnet_mask(lease
);
1357 log_dhcp_client(client
,
1358 "received lease lacks subnet mask, "
1359 "and a fallback one cannot be generated, ignoring");
1364 sd_dhcp_lease_unref(client
->lease
);
1365 client
->lease
= TAKE_PTR(lease
);
1367 if (client_notify(client
, SD_DHCP_CLIENT_EVENT_SELECTING
) < 0)
1370 log_dhcp_client(client
, "OFFER");
1375 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1378 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1379 if (r
!= DHCP_FORCERENEW
)
1382 log_dhcp_client(client
, "FORCERENEW");
1387 static bool lease_equal(const sd_dhcp_lease
*a
, const sd_dhcp_lease
*b
) {
1388 if (a
->address
!= b
->address
)
1391 if (a
->subnet_mask
!= b
->subnet_mask
)
1394 if (a
->router_size
!= b
->router_size
)
1397 for (size_t i
= 0; i
< a
->router_size
; i
++)
1398 if (a
->router
[i
].s_addr
!= b
->router
[i
].s_addr
)
1404 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1405 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1406 _cleanup_free_
char *error_message
= NULL
;
1409 r
= dhcp_lease_new(&lease
);
1413 if (client
->client_id_len
) {
1414 r
= dhcp_lease_set_client_id(lease
,
1415 (uint8_t *) &client
->client_id
,
1416 client
->client_id_len
);
1421 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1422 if (r
== DHCP_NAK
) {
1423 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1424 return -EADDRNOTAVAIL
;
1427 if (r
!= DHCP_ACK
) {
1428 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1432 lease
->next_server
= ack
->siaddr
;
1434 lease
->address
= ack
->yiaddr
;
1436 if (lease
->address
== INADDR_ANY
||
1437 lease
->server_address
== INADDR_ANY
||
1438 lease
->lifetime
== 0) {
1439 log_dhcp_client(client
, "received lease lacks address, server "
1440 "address or lease lifetime, ignoring");
1444 if (lease
->subnet_mask
== INADDR_ANY
) {
1445 r
= dhcp_lease_set_default_subnet_mask(lease
);
1447 log_dhcp_client(client
,
1448 "received lease lacks subnet mask, "
1449 "and a fallback one cannot be generated, ignoring");
1454 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1455 if (client
->lease
) {
1456 if (lease_equal(client
->lease
, lease
))
1457 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1459 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1461 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1464 client
->lease
= TAKE_PTR(lease
);
1466 log_dhcp_client(client
, "ACK");
1471 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1473 assert(client
->request_sent
);
1474 assert(lifetime
> 0);
1481 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1482 + (random_u32() & 0x1fffff);
1485 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1487 uint64_t lifetime_timeout
;
1488 uint64_t t2_timeout
;
1489 uint64_t t1_timeout
;
1490 char time_string
[FORMAT_TIMESPAN_MAX
];
1494 assert(client
->event
);
1495 assert(client
->lease
);
1496 assert(client
->lease
->lifetime
);
1498 /* don't set timers for infinite leases */
1499 if (client
->lease
->lifetime
== 0xffffffff) {
1500 (void) event_source_disable(client
->timeout_t1
);
1501 (void) event_source_disable(client
->timeout_t2
);
1502 (void) event_source_disable(client
->timeout_expire
);
1507 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1510 assert(client
->request_sent
<= time_now
);
1512 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1513 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1514 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1515 /* both T1 and T2 are given */
1516 if (client
->lease
->t1
< client
->lease
->t2
&&
1517 client
->lease
->t2
< client
->lease
->lifetime
) {
1518 /* they are both valid */
1519 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1520 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1523 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1524 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1525 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1526 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1528 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1529 /* only T2 is given, and it is valid */
1530 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1531 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1532 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1533 if (t2_timeout
<= t1_timeout
) {
1534 /* the computed T1 would be invalid, so discard T2 */
1535 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1536 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1538 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1539 /* only T1 is given, and it is valid */
1540 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1541 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1542 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1543 if (t2_timeout
<= t1_timeout
) {
1544 /* the computed T2 would be invalid, so discard T1 */
1545 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1546 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1549 /* fall back to the default timeouts */
1550 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1551 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1552 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1553 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1556 /* arm lifetime timeout */
1557 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1558 clock_boottime_or_monotonic(),
1559 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1560 client_timeout_expire
, client
,
1561 client
->event_priority
, "dhcp4-lifetime", true);
1565 log_dhcp_client(client
, "lease expires in %s",
1566 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1568 /* don't arm earlier timeouts if this has already expired */
1569 if (lifetime_timeout
<= time_now
)
1572 /* arm T2 timeout */
1573 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1574 clock_boottime_or_monotonic(),
1575 t2_timeout
, 10 * USEC_PER_MSEC
,
1576 client_timeout_t2
, client
,
1577 client
->event_priority
, "dhcp4-t2-timeout", true);
1581 log_dhcp_client(client
, "T2 expires in %s",
1582 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1584 /* don't arm earlier timeout if this has already expired */
1585 if (t2_timeout
<= time_now
)
1588 /* arm T1 timeout */
1589 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1590 clock_boottime_or_monotonic(),
1591 t1_timeout
, 10 * USEC_PER_MSEC
,
1592 client_timeout_t1
, client
,
1593 client
->event_priority
, "dhcp4-t1-timer", true);
1597 log_dhcp_client(client
, "T1 expires in %s",
1598 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1603 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1604 DHCP_CLIENT_DONT_DESTROY(client
);
1605 char time_string
[FORMAT_TIMESPAN_MAX
];
1606 int r
= 0, notify_event
= 0;
1609 assert(client
->event
);
1612 switch (client
->state
) {
1613 case DHCP_STATE_SELECTING
:
1615 r
= client_handle_offer(client
, message
, len
);
1618 client
->state
= DHCP_STATE_REQUESTING
;
1619 client
->attempt
= 0;
1621 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1622 clock_boottime_or_monotonic(),
1624 client_timeout_resend
, client
,
1625 client
->event_priority
, "dhcp4-resend-timer", true);
1628 } else if (r
== -ENOMSG
)
1629 /* invalid message, let's ignore it */
1634 case DHCP_STATE_REBOOTING
:
1635 case DHCP_STATE_REQUESTING
:
1636 case DHCP_STATE_RENEWING
:
1637 case DHCP_STATE_REBINDING
:
1639 r
= client_handle_ack(client
, message
, len
);
1641 client
->start_delay
= 0;
1642 (void) event_source_disable(client
->timeout_resend
);
1643 client
->receive_message
=
1644 sd_event_source_unref(client
->receive_message
);
1645 client
->fd
= asynchronous_close(client
->fd
);
1647 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1648 DHCP_STATE_REBOOTING
))
1649 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1650 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1653 client
->state
= DHCP_STATE_BOUND
;
1654 client
->attempt
= 0;
1656 client
->last_addr
= client
->lease
->address
;
1658 r
= client_set_lease_timeouts(client
);
1660 log_dhcp_client(client
, "could not set lease timeouts");
1664 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1666 log_dhcp_client(client
, "could not bind UDP socket");
1672 client_initialize_io_events(client
, client_receive_message_udp
);
1675 client_notify(client
, notify_event
);
1676 if (client
->state
== DHCP_STATE_STOPPED
)
1680 } else if (r
== -EADDRNOTAVAIL
) {
1681 /* got a NAK, let's restart the client */
1682 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1684 r
= client_initialize(client
);
1688 r
= client_start_delayed(client
);
1692 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1693 client
->start_delay
, USEC_PER_SEC
));
1695 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1696 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1699 } else if (r
== -ENOMSG
)
1700 /* invalid message, let's ignore it */
1705 case DHCP_STATE_BOUND
:
1706 r
= client_handle_forcerenew(client
, message
, len
);
1708 r
= client_timeout_t1(NULL
, 0, client
);
1711 } else if (r
== -ENOMSG
)
1712 /* invalid message, let's ignore it */
1717 case DHCP_STATE_INIT
:
1718 case DHCP_STATE_INIT_REBOOT
:
1722 case DHCP_STATE_STOPPED
:
1729 client_stop(client
, r
);
1734 static int client_receive_message_udp(
1740 sd_dhcp_client
*client
= userdata
;
1741 _cleanup_free_ DHCPMessage
*message
= NULL
;
1742 const uint8_t *expected_chaddr
= NULL
;
1743 uint8_t expected_hlen
= 0;
1744 ssize_t len
, buflen
;
1749 buflen
= next_datagram_size_fd(fd
);
1750 if (buflen
== -ENETDOWN
) {
1751 /* the link is down. Don't return an error or the I/O event
1752 source will be disconnected and we won't be able to receive
1753 packets again when the link comes back. */
1759 message
= malloc0(buflen
);
1763 len
= recv(fd
, message
, buflen
, 0);
1765 /* see comment above for why we shouldn't error out on ENETDOWN. */
1766 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1769 return log_dhcp_client_errno(client
, errno
,
1770 "Could not receive message from UDP socket: %m");
1772 if ((size_t) len
< sizeof(DHCPMessage
)) {
1773 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1777 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1778 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1782 if (message
->op
!= BOOTREPLY
) {
1783 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1787 if (message
->htype
!= client
->arp_type
) {
1788 log_dhcp_client(client
, "Packet type does not match client type");
1792 if (client
->arp_type
== ARPHRD_ETHER
) {
1793 expected_hlen
= ETH_ALEN
;
1794 expected_chaddr
= &client
->mac_addr
[0];
1797 if (message
->hlen
!= expected_hlen
) {
1798 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1802 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1803 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1807 if (client
->state
!= DHCP_STATE_BOUND
&&
1808 be32toh(message
->xid
) != client
->xid
) {
1809 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1810 so ignore the xid in this case */
1811 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1812 be32toh(message
->xid
), client
->xid
);
1816 return client_handle_message(client
, message
, len
);
1819 static int client_receive_message_raw(
1825 sd_dhcp_client
*client
= userdata
;
1826 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1827 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1828 struct iovec iov
= {};
1829 struct msghdr msg
= {
1832 .msg_control
= cmsgbuf
,
1833 .msg_controllen
= sizeof(cmsgbuf
),
1835 struct cmsghdr
*cmsg
;
1836 bool checksum
= true;
1837 ssize_t buflen
, len
;
1843 buflen
= next_datagram_size_fd(fd
);
1844 if (buflen
== -ENETDOWN
)
1849 packet
= malloc0(buflen
);
1853 iov
= IOVEC_MAKE(packet
, buflen
);
1855 len
= recvmsg(fd
, &msg
, 0);
1857 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1860 return log_dhcp_client_errno(client
, errno
,
1861 "Could not receive message from raw socket: %m");
1862 } else if ((size_t)len
< sizeof(DHCPPacket
))
1865 CMSG_FOREACH(cmsg
, &msg
)
1866 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1867 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1868 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1869 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1871 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1875 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1879 len
-= DHCP_IP_UDP_SIZE
;
1881 return client_handle_message(client
, &packet
->dhcp
, len
);
1884 int sd_dhcp_client_send_renew(sd_dhcp_client
*client
) {
1885 assert_return(client
, -EINVAL
);
1886 assert_return(client
->fd
>= 0, -EINVAL
);
1888 client
->start_delay
= 0;
1889 client
->attempt
= 1;
1890 client
->state
= DHCP_STATE_RENEWING
;
1892 return client_initialize_time_events(client
);
1895 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1898 assert_return(client
, -EINVAL
);
1900 r
= client_initialize(client
);
1904 /* RFC7844 section 3.3:
1905 SHOULD perform a complete four-way handshake, starting with a
1906 DHCPDISCOVER, to obtain a new address lease. If the client can
1907 ascertain that this is exactly the same network to which it was
1908 previously connected, and if the link-layer address did not change,
1909 the client MAY issue a DHCPREQUEST to try to reclaim the current
1911 if (client
->last_addr
&& !client
->anonymize
)
1912 client
->state
= DHCP_STATE_INIT_REBOOT
;
1914 r
= client_start(client
);
1916 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1921 int sd_dhcp_client_send_release(sd_dhcp_client
*client
) {
1922 assert_return(client
, -EINVAL
);
1924 client_send_release(client
);
1929 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1930 DHCP_CLIENT_DONT_DESTROY(client
);
1932 assert_return(client
, -EINVAL
);
1934 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1935 client
->state
= DHCP_STATE_STOPPED
;
1940 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1943 assert_return(client
, -EINVAL
);
1944 assert_return(!client
->event
, -EBUSY
);
1947 client
->event
= sd_event_ref(event
);
1949 r
= sd_event_default(&client
->event
);
1954 client
->event_priority
= priority
;
1959 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1960 assert_return(client
, -EINVAL
);
1962 client
->event
= sd_event_unref(client
->event
);
1967 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1968 assert_return(client
, NULL
);
1970 return client
->event
;
1973 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1976 log_dhcp_client(client
, "FREE");
1978 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1979 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1980 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1981 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1983 client_initialize(client
);
1985 sd_dhcp_client_detach_event(client
);
1987 sd_dhcp_lease_unref(client
->lease
);
1989 free(client
->req_opts
);
1990 free(client
->hostname
);
1991 free(client
->vendor_class_identifier
);
1992 client
->user_class
= strv_free(client
->user_class
);
1993 return mfree(client
);
1996 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1998 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1999 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
2001 assert_return(ret
, -EINVAL
);
2003 client
= new(sd_dhcp_client
, 1);
2007 *client
= (sd_dhcp_client
) {
2009 .state
= DHCP_STATE_INIT
,
2012 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
2013 .port
= DHCP_PORT_CLIENT
,
2014 .anonymize
= !!anonymize
,
2015 .max_attempts
= (uint64_t) -1,
2017 /* NOTE: this could be moved to a function. */
2019 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
2020 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
2022 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
2023 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
2025 if (!client
->req_opts
)
2028 *ret
= TAKE_PTR(client
);