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_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
536 return -EADDRNOTAVAIL
;
539 *ret
= client
->lease
;
544 static void client_notify(sd_dhcp_client
*client
, int event
) {
547 if (client
->callback
)
548 client
->callback(client
, event
, client
->userdata
);
551 static int client_initialize(sd_dhcp_client
*client
) {
552 assert_return(client
, -EINVAL
);
554 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
556 client
->fd
= asynchronous_close(client
->fd
);
558 (void) event_source_disable(client
->timeout_resend
);
559 (void) event_source_disable(client
->timeout_t1
);
560 (void) event_source_disable(client
->timeout_t2
);
561 (void) event_source_disable(client
->timeout_expire
);
565 client
->state
= DHCP_STATE_INIT
;
568 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
573 static void client_stop(sd_dhcp_client
*client
, int error
) {
577 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
578 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
579 log_dhcp_client(client
, "STOPPED");
581 log_dhcp_client(client
, "STOPPED: Unknown event");
583 client_notify(client
, error
);
585 client_initialize(client
);
588 static int client_message_init(
589 sd_dhcp_client
*client
,
593 size_t *_optoffset
) {
595 _cleanup_free_ DHCPPacket
*packet
= NULL
;
596 size_t optlen
, optoffset
, size
;
603 assert(client
->start_time
);
607 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
609 optlen
= DHCP_MIN_OPTIONS_SIZE
;
610 size
= sizeof(DHCPPacket
) + optlen
;
612 packet
= malloc0(size
);
616 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
617 client
->arp_type
, optlen
, &optoffset
);
621 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
622 refuse to issue an DHCP lease if 'secs' is set to zero */
623 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
626 assert(time_now
>= client
->start_time
);
628 /* seconds between sending first and last DISCOVER
629 * must always be strictly positive to deal with broken servers */
630 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
631 packet
->dhcp
.secs
= htobe16(secs
);
633 /* RFC2132 section 4.1
634 A client that cannot receive unicast IP datagrams until its protocol
635 software has been configured with an IP address SHOULD set the
636 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
637 DHCPREQUEST messages that client sends. The BROADCAST bit will
638 provide a hint to the DHCP server and BOOTP relay agent to broadcast
639 any messages to the client on the client's subnet.
641 Note: some interfaces needs this to be enabled, but some networks
642 needs this to be disabled as broadcasts are filteretd, so this
643 needs to be configurable */
644 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
645 packet
->dhcp
.flags
= htobe16(0x8000);
647 /* RFC2132 section 4.1.1:
648 The client MUST include its hardware address in the ’chaddr’ field, if
649 necessary for delivery of DHCP reply messages. Non-Ethernet
650 interfaces will leave 'chaddr' empty and use the client identifier
651 instead (eg, RFC 4390 section 2.1).
653 if (client
->arp_type
== ARPHRD_ETHER
)
654 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
656 /* If no client identifier exists, construct an RFC 4361-compliant one */
657 if (client
->client_id_len
== 0) {
660 client
->client_id
.type
= 255;
662 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
663 true, &client
->client_id
.ns
.iaid
);
667 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
671 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
674 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
675 Identifier option is not set */
676 if (client
->client_id_len
) {
677 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
678 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
679 client
->client_id_len
,
685 /* RFC2131 section 3.5:
686 in its initial DHCPDISCOVER or DHCPREQUEST message, a
687 client may provide the server with a list of specific
688 parameters the client is interested in. If the client
689 includes a list of parameters in a DHCPDISCOVER message,
690 it MUST include that list in any subsequent DHCPREQUEST
694 /* RFC7844 section 3:
695 MAY contain the Parameter Request List option. */
696 /* NOTE: in case that there would be an option to do not send
697 * any PRL at all, the size should be checked before sending */
698 if (client
->req_opts_size
> 0) {
699 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
700 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
701 client
->req_opts_size
, client
->req_opts
);
706 /* RFC2131 section 3.5:
707 The client SHOULD include the ’maximum DHCP message size’ option to
708 let the server know how large the server may make its DHCP messages.
710 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
711 than the defined default size unless the Maximum Message Size option
714 RFC3442 "Requirements to Avoid Sizing Constraints":
715 Because a full routing table can be quite large, the standard 576
716 octet maximum size for a DHCP message may be too short to contain
717 some legitimate Classless Static Route options. Because of this,
718 clients implementing the Classless Static Route option SHOULD send a
719 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
720 stack is capable of receiving larger IP datagrams. In this case, the
721 client SHOULD set the value of this option to at least the MTU of the
722 interface that the client is configuring. The client MAY set the
723 value of this option higher, up to the size of the largest UDP packet
724 it is prepared to accept. (Note that the value specified in the
725 Maximum DHCP Message Size option is the total maximum packet size,
726 including IP and UDP headers.)
728 /* RFC7844 section 3:
729 SHOULD NOT contain any other option. */
730 if (!client
->anonymize
) {
731 max_size
= htobe16(size
);
732 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
733 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
740 *_optoffset
= optoffset
;
741 *ret
= TAKE_PTR(packet
);
746 static int client_append_fqdn_option(
747 DHCPMessage
*message
,
752 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
755 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
756 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
757 buffer
[1] = 0; /* RCODE1 (deprecated) */
758 buffer
[2] = 0; /* RCODE2 (deprecated) */
760 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
762 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
763 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
768 static int dhcp_client_send_raw(
769 sd_dhcp_client
*client
,
773 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
774 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
776 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
780 static int client_send_discover(sd_dhcp_client
*client
) {
781 _cleanup_free_ DHCPPacket
*discover
= NULL
;
782 size_t optoffset
, optlen
;
786 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
788 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
789 &optlen
, &optoffset
);
793 /* the client may suggest values for the network address
794 and lease time in the DHCPDISCOVER message. The client may include
795 the ’requested IP address’ option to suggest that a particular IP
796 address be assigned, and may include the ’IP address lease time’
797 option to suggest the lease time it would like.
799 if (client
->last_addr
!= INADDR_ANY
) {
800 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
801 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
802 4, &client
->last_addr
);
807 if (client
->hostname
) {
808 /* According to RFC 4702 "clients that send the Client FQDN option in
809 their messages MUST NOT also send the Host Name option". Just send
810 one of the two depending on the hostname type.
812 if (dns_name_is_single_label(client
->hostname
)) {
813 /* it is unclear from RFC 2131 if client should send hostname in
814 DHCPDISCOVER but dhclient does and so we do as well
816 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
817 SD_DHCP_OPTION_HOST_NAME
,
818 strlen(client
->hostname
), client
->hostname
);
820 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
826 if (client
->vendor_class_identifier
) {
827 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
828 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
829 strlen(client
->vendor_class_identifier
),
830 client
->vendor_class_identifier
);
835 if (client
->user_class
) {
836 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
837 SD_DHCP_OPTION_USER_CLASS
,
838 strv_length(client
->user_class
),
844 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
845 SD_DHCP_OPTION_END
, 0, NULL
);
849 /* We currently ignore:
850 The client SHOULD wait a random time between one and ten seconds to
851 desynchronize the use of DHCP at startup.
853 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
857 log_dhcp_client(client
, "DISCOVER");
862 static int client_send_request(sd_dhcp_client
*client
) {
863 _cleanup_free_ DHCPPacket
*request
= NULL
;
864 size_t optoffset
, optlen
;
869 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
873 switch (client
->state
) {
874 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
875 SELECTING should be REQUESTING)
878 case DHCP_STATE_REQUESTING
:
879 /* Client inserts the address of the selected server in ’server
880 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
881 filled in with the yiaddr value from the chosen DHCPOFFER.
884 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
885 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
886 4, &client
->lease
->server_address
);
890 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
891 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
892 4, &client
->lease
->address
);
898 case DHCP_STATE_INIT_REBOOT
:
899 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
900 option MUST be filled in with client’s notion of its previously
901 assigned address. ’ciaddr’ MUST be zero.
903 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
904 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
905 4, &client
->last_addr
);
910 case DHCP_STATE_RENEWING
:
911 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
912 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
916 case DHCP_STATE_REBINDING
:
917 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
918 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
921 This message MUST be broadcast to the 0xffffffff IP broadcast address.
923 request
->dhcp
.ciaddr
= client
->lease
->address
;
927 case DHCP_STATE_INIT
:
928 case DHCP_STATE_SELECTING
:
929 case DHCP_STATE_REBOOTING
:
930 case DHCP_STATE_BOUND
:
931 case DHCP_STATE_STOPPED
:
935 if (client
->hostname
) {
936 if (dns_name_is_single_label(client
->hostname
))
937 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
938 SD_DHCP_OPTION_HOST_NAME
,
939 strlen(client
->hostname
), client
->hostname
);
941 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
947 if (client
->vendor_class_identifier
) {
948 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
949 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
950 strlen(client
->vendor_class_identifier
),
951 client
->vendor_class_identifier
);
956 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
957 SD_DHCP_OPTION_END
, 0, NULL
);
961 if (client
->state
== DHCP_STATE_RENEWING
) {
962 r
= dhcp_network_send_udp_socket(client
->fd
,
963 client
->lease
->server_address
,
966 sizeof(DHCPMessage
) + optoffset
);
968 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
973 switch (client
->state
) {
975 case DHCP_STATE_REQUESTING
:
976 log_dhcp_client(client
, "REQUEST (requesting)");
979 case DHCP_STATE_INIT_REBOOT
:
980 log_dhcp_client(client
, "REQUEST (init-reboot)");
983 case DHCP_STATE_RENEWING
:
984 log_dhcp_client(client
, "REQUEST (renewing)");
987 case DHCP_STATE_REBINDING
:
988 log_dhcp_client(client
, "REQUEST (rebinding)");
992 log_dhcp_client(client
, "REQUEST (invalid)");
999 static int client_start(sd_dhcp_client
*client
);
1001 static int client_timeout_resend(
1006 sd_dhcp_client
*client
= userdata
;
1007 DHCP_CLIENT_DONT_DESTROY(client
);
1008 usec_t next_timeout
= 0;
1015 assert(client
->event
);
1017 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1021 switch (client
->state
) {
1023 case DHCP_STATE_RENEWING
:
1025 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1029 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1033 case DHCP_STATE_REBINDING
:
1035 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1039 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1042 case DHCP_STATE_REBOOTING
:
1043 /* start over as we did not receive a timely ack or nak */
1044 r
= client_initialize(client
);
1048 r
= client_start(client
);
1052 log_dhcp_client(client
, "REBOOTED");
1056 case DHCP_STATE_INIT
:
1057 case DHCP_STATE_INIT_REBOOT
:
1058 case DHCP_STATE_SELECTING
:
1059 case DHCP_STATE_REQUESTING
:
1060 case DHCP_STATE_BOUND
:
1062 if (client
->attempt
< client
->max_attempts
)
1067 next_timeout
= time_now
+ ((UINT64_C(1) << MIN(client
->attempt
, (uint64_t) 6)) - 1) * USEC_PER_SEC
;
1071 case DHCP_STATE_STOPPED
:
1076 next_timeout
+= (random_u32() & 0x1fffff);
1078 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1079 clock_boottime_or_monotonic(),
1080 next_timeout
, 10 * USEC_PER_MSEC
,
1081 client_timeout_resend
, client
,
1082 client
->event_priority
, "dhcp4-resend-timer", true);
1086 switch (client
->state
) {
1087 case DHCP_STATE_INIT
:
1088 r
= client_send_discover(client
);
1090 client
->state
= DHCP_STATE_SELECTING
;
1091 client
->attempt
= 0;
1092 } else if (client
->attempt
>= client
->max_attempts
)
1097 case DHCP_STATE_SELECTING
:
1098 r
= client_send_discover(client
);
1099 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1104 case DHCP_STATE_INIT_REBOOT
:
1105 case DHCP_STATE_REQUESTING
:
1106 case DHCP_STATE_RENEWING
:
1107 case DHCP_STATE_REBINDING
:
1108 r
= client_send_request(client
);
1109 if (r
< 0 && client
->attempt
>= client
->max_attempts
)
1112 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1113 client
->state
= DHCP_STATE_REBOOTING
;
1115 client
->request_sent
= time_now
;
1119 case DHCP_STATE_REBOOTING
:
1120 case DHCP_STATE_BOUND
:
1124 case DHCP_STATE_STOPPED
:
1132 client_stop(client
, r
);
1134 /* Errors were dealt with when stopping the client, don't spill
1135 errors into the event loop handler */
1139 static int client_initialize_io_events(
1140 sd_dhcp_client
*client
,
1141 sd_event_io_handler_t io_callback
) {
1146 assert(client
->event
);
1148 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1149 client
->fd
, EPOLLIN
, io_callback
,
1154 r
= sd_event_source_set_priority(client
->receive_message
,
1155 client
->event_priority
);
1159 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1165 client_stop(client
, r
);
1170 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1175 assert(client
->event
);
1177 if (client
->start_delay
) {
1178 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1179 usec
+= client
->start_delay
;
1182 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1183 clock_boottime_or_monotonic(),
1185 client_timeout_resend
, client
,
1186 client
->event_priority
, "dhcp4-resend-timer", true);
1188 client_stop(client
, r
);
1194 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1195 client_initialize_io_events(client
, io_callback
);
1196 client_initialize_time_events(client
);
1201 static int client_start_delayed(sd_dhcp_client
*client
) {
1204 assert_return(client
, -EINVAL
);
1205 assert_return(client
->event
, -EINVAL
);
1206 assert_return(client
->ifindex
> 0, -EINVAL
);
1207 assert_return(client
->fd
< 0, -EBUSY
);
1208 assert_return(client
->xid
== 0, -EINVAL
);
1209 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1211 client
->xid
= random_u32();
1213 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1214 client
->xid
, client
->mac_addr
,
1215 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1217 client_stop(client
, r
);
1222 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1223 client
->start_time
= now(clock_boottime_or_monotonic());
1225 return client_initialize_events(client
, client_receive_message_raw
);
1228 static int client_start(sd_dhcp_client
*client
) {
1229 client
->start_delay
= 0;
1230 return client_start_delayed(client
);
1233 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1234 sd_dhcp_client
*client
= userdata
;
1235 DHCP_CLIENT_DONT_DESTROY(client
);
1237 log_dhcp_client(client
, "EXPIRED");
1239 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1241 /* lease was lost, start over if not freed or stopped in callback */
1242 if (client
->state
!= DHCP_STATE_STOPPED
) {
1243 client_initialize(client
);
1244 client_start(client
);
1250 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1251 sd_dhcp_client
*client
= userdata
;
1252 DHCP_CLIENT_DONT_DESTROY(client
);
1257 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1258 client
->fd
= asynchronous_close(client
->fd
);
1260 client
->state
= DHCP_STATE_REBINDING
;
1261 client
->attempt
= 0;
1263 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1264 client
->xid
, client
->mac_addr
,
1265 client
->mac_addr_len
, client
->arp_type
,
1268 client_stop(client
, r
);
1273 return client_initialize_events(client
, client_receive_message_raw
);
1276 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1277 sd_dhcp_client
*client
= userdata
;
1278 DHCP_CLIENT_DONT_DESTROY(client
);
1280 client
->state
= DHCP_STATE_RENEWING
;
1281 client
->attempt
= 0;
1283 return client_initialize_time_events(client
);
1286 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1287 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1290 r
= dhcp_lease_new(&lease
);
1294 if (client
->client_id_len
) {
1295 r
= dhcp_lease_set_client_id(lease
,
1296 (uint8_t *) &client
->client_id
,
1297 client
->client_id_len
);
1302 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1303 if (r
!= DHCP_OFFER
) {
1304 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1308 lease
->next_server
= offer
->siaddr
;
1309 lease
->address
= offer
->yiaddr
;
1311 if (lease
->address
== 0 ||
1312 lease
->server_address
== 0 ||
1313 lease
->lifetime
== 0) {
1314 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1318 if (!lease
->have_subnet_mask
) {
1319 r
= dhcp_lease_set_default_subnet_mask(lease
);
1321 log_dhcp_client(client
,
1322 "received lease lacks subnet mask, "
1323 "and a fallback one cannot be generated, ignoring");
1328 sd_dhcp_lease_unref(client
->lease
);
1329 client
->lease
= TAKE_PTR(lease
);
1331 log_dhcp_client(client
, "OFFER");
1336 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1339 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1340 if (r
!= DHCP_FORCERENEW
)
1343 log_dhcp_client(client
, "FORCERENEW");
1348 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1349 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1350 _cleanup_free_
char *error_message
= NULL
;
1353 r
= dhcp_lease_new(&lease
);
1357 if (client
->client_id_len
) {
1358 r
= dhcp_lease_set_client_id(lease
,
1359 (uint8_t *) &client
->client_id
,
1360 client
->client_id_len
);
1365 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1366 if (r
== DHCP_NAK
) {
1367 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1368 return -EADDRNOTAVAIL
;
1371 if (r
!= DHCP_ACK
) {
1372 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1376 lease
->next_server
= ack
->siaddr
;
1378 lease
->address
= ack
->yiaddr
;
1380 if (lease
->address
== INADDR_ANY
||
1381 lease
->server_address
== INADDR_ANY
||
1382 lease
->lifetime
== 0) {
1383 log_dhcp_client(client
, "received lease lacks address, server "
1384 "address or lease lifetime, ignoring");
1388 if (lease
->subnet_mask
== INADDR_ANY
) {
1389 r
= dhcp_lease_set_default_subnet_mask(lease
);
1391 log_dhcp_client(client
,
1392 "received lease lacks subnet mask, "
1393 "and a fallback one cannot be generated, ignoring");
1398 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1399 if (client
->lease
) {
1400 if (client
->lease
->address
!= lease
->address
||
1401 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1402 client
->lease
->router
!= lease
->router
) {
1403 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1405 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1407 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1410 client
->lease
= TAKE_PTR(lease
);
1412 log_dhcp_client(client
, "ACK");
1417 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1419 assert(client
->request_sent
);
1420 assert(lifetime
> 0);
1427 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1428 + (random_u32() & 0x1fffff);
1431 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1433 uint64_t lifetime_timeout
;
1434 uint64_t t2_timeout
;
1435 uint64_t t1_timeout
;
1436 char time_string
[FORMAT_TIMESPAN_MAX
];
1440 assert(client
->event
);
1441 assert(client
->lease
);
1442 assert(client
->lease
->lifetime
);
1444 /* don't set timers for infinite leases */
1445 if (client
->lease
->lifetime
== 0xffffffff) {
1446 (void) event_source_disable(client
->timeout_t1
);
1447 (void) event_source_disable(client
->timeout_t2
);
1448 (void) event_source_disable(client
->timeout_expire
);
1453 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1456 assert(client
->request_sent
<= time_now
);
1458 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1459 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1460 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1461 /* both T1 and T2 are given */
1462 if (client
->lease
->t1
< client
->lease
->t2
&&
1463 client
->lease
->t2
< client
->lease
->lifetime
) {
1464 /* they are both valid */
1465 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1466 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1469 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1470 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1471 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1472 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1474 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1475 /* only T2 is given, and it is valid */
1476 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1477 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1478 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1479 if (t2_timeout
<= t1_timeout
) {
1480 /* the computed T1 would be invalid, so discard T2 */
1481 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1482 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1484 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1485 /* only T1 is given, and it is valid */
1486 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1487 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1488 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1489 if (t2_timeout
<= t1_timeout
) {
1490 /* the computed T2 would be invalid, so discard T1 */
1491 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1492 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1495 /* fall back to the default timeouts */
1496 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1497 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1498 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1499 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1502 /* arm lifetime timeout */
1503 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1504 clock_boottime_or_monotonic(),
1505 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1506 client_timeout_expire
, client
,
1507 client
->event_priority
, "dhcp4-lifetime", true);
1511 log_dhcp_client(client
, "lease expires in %s",
1512 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1514 /* don't arm earlier timeouts if this has already expired */
1515 if (lifetime_timeout
<= time_now
)
1518 /* arm T2 timeout */
1519 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1520 clock_boottime_or_monotonic(),
1521 t2_timeout
, 10 * USEC_PER_MSEC
,
1522 client_timeout_t2
, client
,
1523 client
->event_priority
, "dhcp4-t2-timeout", true);
1527 log_dhcp_client(client
, "T2 expires in %s",
1528 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1530 /* don't arm earlier timeout if this has already expired */
1531 if (t2_timeout
<= time_now
)
1534 /* arm T1 timeout */
1535 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1536 clock_boottime_or_monotonic(),
1537 t1_timeout
, 10 * USEC_PER_MSEC
,
1538 client_timeout_t1
, client
,
1539 client
->event_priority
, "dhcp4-t1-timer", true);
1543 log_dhcp_client(client
, "T1 expires in %s",
1544 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1549 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1550 DHCP_CLIENT_DONT_DESTROY(client
);
1551 char time_string
[FORMAT_TIMESPAN_MAX
];
1552 int r
= 0, notify_event
= 0;
1555 assert(client
->event
);
1558 switch (client
->state
) {
1559 case DHCP_STATE_SELECTING
:
1561 r
= client_handle_offer(client
, message
, len
);
1564 client
->state
= DHCP_STATE_REQUESTING
;
1565 client
->attempt
= 0;
1567 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1568 clock_boottime_or_monotonic(),
1570 client_timeout_resend
, client
,
1571 client
->event_priority
, "dhcp4-resend-timer", true);
1574 } else if (r
== -ENOMSG
)
1575 /* invalid message, let's ignore it */
1580 case DHCP_STATE_REBOOTING
:
1581 case DHCP_STATE_REQUESTING
:
1582 case DHCP_STATE_RENEWING
:
1583 case DHCP_STATE_REBINDING
:
1585 r
= client_handle_ack(client
, message
, len
);
1587 client
->start_delay
= 0;
1588 (void) event_source_disable(client
->timeout_resend
);
1589 client
->receive_message
=
1590 sd_event_source_unref(client
->receive_message
);
1591 client
->fd
= asynchronous_close(client
->fd
);
1593 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1594 DHCP_STATE_REBOOTING
))
1595 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1596 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1599 client
->state
= DHCP_STATE_BOUND
;
1600 client
->attempt
= 0;
1602 client
->last_addr
= client
->lease
->address
;
1604 r
= client_set_lease_timeouts(client
);
1606 log_dhcp_client(client
, "could not set lease timeouts");
1610 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1612 log_dhcp_client(client
, "could not bind UDP socket");
1618 client_initialize_io_events(client
, client_receive_message_udp
);
1621 client_notify(client
, notify_event
);
1622 if (client
->state
== DHCP_STATE_STOPPED
)
1626 } else if (r
== -EADDRNOTAVAIL
) {
1627 /* got a NAK, let's restart the client */
1628 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1630 r
= client_initialize(client
);
1634 r
= client_start_delayed(client
);
1638 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1639 client
->start_delay
, USEC_PER_SEC
));
1641 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1642 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1645 } else if (r
== -ENOMSG
)
1646 /* invalid message, let's ignore it */
1651 case DHCP_STATE_BOUND
:
1652 r
= client_handle_forcerenew(client
, message
, len
);
1654 r
= client_timeout_t1(NULL
, 0, client
);
1657 } else if (r
== -ENOMSG
)
1658 /* invalid message, let's ignore it */
1663 case DHCP_STATE_INIT
:
1664 case DHCP_STATE_INIT_REBOOT
:
1668 case DHCP_STATE_STOPPED
:
1675 client_stop(client
, r
);
1680 static int client_receive_message_udp(
1686 sd_dhcp_client
*client
= userdata
;
1687 _cleanup_free_ DHCPMessage
*message
= NULL
;
1688 const uint8_t *expected_chaddr
= NULL
;
1689 uint8_t expected_hlen
= 0;
1690 ssize_t len
, buflen
;
1695 buflen
= next_datagram_size_fd(fd
);
1696 if (buflen
== -ENETDOWN
) {
1697 /* the link is down. Don't return an error or the I/O event
1698 source will be disconnected and we won't be able to receive
1699 packets again when the link comes back. */
1705 message
= malloc0(buflen
);
1709 len
= recv(fd
, message
, buflen
, 0);
1711 /* see comment above for why we shouldn't error out on ENETDOWN. */
1712 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1715 return log_dhcp_client_errno(client
, errno
,
1716 "Could not receive message from UDP socket: %m");
1718 if ((size_t) len
< sizeof(DHCPMessage
)) {
1719 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1723 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1724 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1728 if (message
->op
!= BOOTREPLY
) {
1729 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1733 if (message
->htype
!= client
->arp_type
) {
1734 log_dhcp_client(client
, "Packet type does not match client type");
1738 if (client
->arp_type
== ARPHRD_ETHER
) {
1739 expected_hlen
= ETH_ALEN
;
1740 expected_chaddr
= &client
->mac_addr
[0];
1743 if (message
->hlen
!= expected_hlen
) {
1744 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1748 if (expected_hlen
> 0 && memcmp(&message
->chaddr
[0], expected_chaddr
, expected_hlen
)) {
1749 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1753 if (client
->state
!= DHCP_STATE_BOUND
&&
1754 be32toh(message
->xid
) != client
->xid
) {
1755 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1756 so ignore the xid in this case */
1757 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1758 be32toh(message
->xid
), client
->xid
);
1762 return client_handle_message(client
, message
, len
);
1765 static int client_receive_message_raw(
1771 sd_dhcp_client
*client
= userdata
;
1772 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1773 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1774 struct iovec iov
= {};
1775 struct msghdr msg
= {
1778 .msg_control
= cmsgbuf
,
1779 .msg_controllen
= sizeof(cmsgbuf
),
1781 struct cmsghdr
*cmsg
;
1782 bool checksum
= true;
1783 ssize_t buflen
, len
;
1789 buflen
= next_datagram_size_fd(fd
);
1790 if (buflen
== -ENETDOWN
)
1795 packet
= malloc0(buflen
);
1799 iov
= IOVEC_MAKE(packet
, buflen
);
1801 len
= recvmsg(fd
, &msg
, 0);
1803 if (IN_SET(errno
, EAGAIN
, EINTR
, ENETDOWN
))
1806 return log_dhcp_client_errno(client
, errno
,
1807 "Could not receive message from raw socket: %m");
1808 } else if ((size_t)len
< sizeof(DHCPPacket
))
1811 CMSG_FOREACH(cmsg
, &msg
)
1812 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1813 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1814 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1815 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1817 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1821 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1825 len
-= DHCP_IP_UDP_SIZE
;
1827 return client_handle_message(client
, &packet
->dhcp
, len
);
1830 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1833 assert_return(client
, -EINVAL
);
1835 r
= client_initialize(client
);
1839 /* RFC7844 section 3.3:
1840 SHOULD perform a complete four-way handshake, starting with a
1841 DHCPDISCOVER, to obtain a new address lease. If the client can
1842 ascertain that this is exactly the same network to which it was
1843 previously connected, and if the link-layer address did not change,
1844 the client MAY issue a DHCPREQUEST to try to reclaim the current
1846 if (client
->last_addr
&& !client
->anonymize
)
1847 client
->state
= DHCP_STATE_INIT_REBOOT
;
1849 r
= client_start(client
);
1851 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1856 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1857 DHCP_CLIENT_DONT_DESTROY(client
);
1859 assert_return(client
, -EINVAL
);
1861 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1862 client
->state
= DHCP_STATE_STOPPED
;
1867 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1870 assert_return(client
, -EINVAL
);
1871 assert_return(!client
->event
, -EBUSY
);
1874 client
->event
= sd_event_ref(event
);
1876 r
= sd_event_default(&client
->event
);
1881 client
->event_priority
= priority
;
1886 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1887 assert_return(client
, -EINVAL
);
1889 client
->event
= sd_event_unref(client
->event
);
1894 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1895 assert_return(client
, NULL
);
1897 return client
->event
;
1900 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1903 log_dhcp_client(client
, "FREE");
1905 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1906 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1907 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1908 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1910 client_initialize(client
);
1912 sd_dhcp_client_detach_event(client
);
1914 sd_dhcp_lease_unref(client
->lease
);
1916 free(client
->req_opts
);
1917 free(client
->hostname
);
1918 free(client
->vendor_class_identifier
);
1919 client
->user_class
= strv_free(client
->user_class
);
1920 return mfree(client
);
1923 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1925 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1926 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1928 assert_return(ret
, -EINVAL
);
1930 client
= new(sd_dhcp_client
, 1);
1934 *client
= (sd_dhcp_client
) {
1936 .state
= DHCP_STATE_INIT
,
1939 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1940 .port
= DHCP_PORT_CLIENT
,
1941 .anonymize
= !!anonymize
,
1942 .max_attempts
= (uint64_t) -1,
1944 /* NOTE: this could be moved to a function. */
1946 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1947 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1949 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1950 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1952 if (!client
->req_opts
)
1955 *ret
= TAKE_PTR(client
);