1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
7 #include <net/ethernet.h>
8 #include <net/if_arp.h>
12 #include <sys/ioctl.h>
13 #include <linux/if_infiniband.h>
15 #include "sd-dhcp-client.h"
17 #include "alloc-util.h"
19 #include "dhcp-identifier.h"
20 #include "dhcp-internal.h"
21 #include "dhcp-lease-internal.h"
22 #include "dhcp-protocol.h"
23 #include "dns-domain.h"
24 #include "event-util.h"
25 #include "hostname-util.h"
27 #include "random-util.h"
28 #include "string-util.h"
32 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
33 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
35 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
36 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
38 struct sd_dhcp_client
{
44 sd_event_source
*timeout_resend
;
48 union sockaddr_union link
;
49 sd_event_source
*receive_message
;
50 bool request_broadcast
;
52 size_t req_opts_allocated
;
56 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
63 /* 0: Generic (non-LL) (RFC 2132) */
64 uint8_t data
[MAX_CLIENT_ID_LEN
];
67 /* 1: Ethernet Link-Layer (RFC 2132) */
68 uint8_t haddr
[ETH_ALEN
];
71 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
75 /* 255: Node-specific (RFC 4361) */
80 uint8_t data
[MAX_CLIENT_ID_LEN
];
86 char *vendor_class_identifier
;
93 sd_event_source
*timeout_t1
;
94 sd_event_source
*timeout_t2
;
95 sd_event_source
*timeout_expire
;
96 sd_dhcp_client_callback_t callback
;
102 static const uint8_t default_req_opts
[] = {
103 SD_DHCP_OPTION_SUBNET_MASK
,
104 SD_DHCP_OPTION_ROUTER
,
105 SD_DHCP_OPTION_HOST_NAME
,
106 SD_DHCP_OPTION_DOMAIN_NAME
,
107 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
110 /* RFC7844 section 3:
111 MAY contain the Parameter Request List option.
113 The client intending to protect its privacy SHOULD only request a
114 minimal number of options in the PRL and SHOULD also randomly shuffle
115 the ordering of option codes in the PRL. If this random ordering
116 cannot be implemented, the client MAY order the option codes in the
117 PRL by option code number (lowest to highest).
119 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
120 static const uint8_t default_req_opts_anonymize
[] = {
121 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
122 SD_DHCP_OPTION_ROUTER
, /* 3 */
123 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
124 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
125 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
126 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
127 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
128 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
129 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
130 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
131 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
132 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
133 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
136 static int client_receive_message_raw(
141 static int client_receive_message_udp(
146 static void client_stop(sd_dhcp_client
*client
, int error
);
148 int sd_dhcp_client_set_callback(
149 sd_dhcp_client
*client
,
150 sd_dhcp_client_callback_t cb
,
153 assert_return(client
, -EINVAL
);
155 client
->callback
= cb
;
156 client
->userdata
= userdata
;
161 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
162 assert_return(client
, -EINVAL
);
164 client
->request_broadcast
= !!broadcast
;
169 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
172 assert_return(client
, -EINVAL
);
173 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
177 case SD_DHCP_OPTION_PAD
:
178 case SD_DHCP_OPTION_OVERLOAD
:
179 case SD_DHCP_OPTION_MESSAGE_TYPE
:
180 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
181 case SD_DHCP_OPTION_END
:
188 for (i
= 0; i
< client
->req_opts_size
; i
++)
189 if (client
->req_opts
[i
] == option
)
192 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
193 client
->req_opts_size
+ 1))
196 client
->req_opts
[client
->req_opts_size
++] = option
;
201 int sd_dhcp_client_set_request_address(
202 sd_dhcp_client
*client
,
203 const struct in_addr
*last_addr
) {
205 assert_return(client
, -EINVAL
);
206 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
209 client
->last_addr
= last_addr
->s_addr
;
211 client
->last_addr
= INADDR_ANY
;
216 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
218 assert_return(client
, -EINVAL
);
219 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
220 assert_return(ifindex
> 0, -EINVAL
);
222 client
->ifindex
= ifindex
;
226 int sd_dhcp_client_set_mac(
227 sd_dhcp_client
*client
,
232 DHCP_CLIENT_DONT_DESTROY(client
);
233 bool need_restart
= false;
235 assert_return(client
, -EINVAL
);
236 assert_return(addr
, -EINVAL
);
237 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
238 assert_return(arp_type
> 0, -EINVAL
);
240 if (arp_type
== ARPHRD_ETHER
)
241 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
242 else if (arp_type
== ARPHRD_INFINIBAND
)
243 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
247 if (client
->mac_addr_len
== addr_len
&&
248 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
251 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
252 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
254 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
257 memcpy(&client
->mac_addr
, addr
, addr_len
);
258 client
->mac_addr_len
= addr_len
;
259 client
->arp_type
= arp_type
;
261 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
262 sd_dhcp_client_start(client
);
267 int sd_dhcp_client_get_client_id(
268 sd_dhcp_client
*client
,
270 const uint8_t **data
,
273 assert_return(client
, -EINVAL
);
274 assert_return(type
, -EINVAL
);
275 assert_return(data
, -EINVAL
);
276 assert_return(data_len
, -EINVAL
);
281 if (client
->client_id_len
) {
282 *type
= client
->client_id
.type
;
283 *data
= client
->client_id
.raw
.data
;
284 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
290 int sd_dhcp_client_set_client_id(
291 sd_dhcp_client
*client
,
296 DHCP_CLIENT_DONT_DESTROY(client
);
297 bool need_restart
= false;
299 assert_return(client
, -EINVAL
);
300 assert_return(data
, -EINVAL
);
301 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
306 if (data_len
!= ETH_ALEN
)
310 case ARPHRD_INFINIBAND
:
311 if (data_len
!= INFINIBAND_ALEN
)
319 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
320 client
->client_id
.type
== type
&&
321 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
324 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
325 log_dhcp_client(client
, "Changing client ID on running DHCP "
326 "client, restarting");
328 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
331 client
->client_id
.type
= type
;
332 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
333 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
335 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
336 sd_dhcp_client_start(client
);
342 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
343 * without further modification. Otherwise, if duid_type is supported, DUID
344 * is set based on that type. Otherwise, an error is returned.
346 static int dhcp_client_set_iaid_duid_internal(
347 sd_dhcp_client
*client
,
356 DHCP_CLIENT_DONT_DESTROY(client
);
360 assert_return(client
, -EINVAL
);
361 assert_return(duid_len
== 0 || duid
!= NULL
, -EINVAL
);
364 r
= dhcp_validate_duid_len(duid_type
, duid_len
);
369 zero(client
->client_id
);
370 client
->client_id
.type
= 255;
374 client
->client_id
.ns
.iaid
= htobe32(iaid
);
376 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
377 client
->mac_addr_len
,
379 &client
->client_id
.ns
.iaid
);
386 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
387 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
388 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
392 if (client
->mac_addr_len
== 0)
395 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
400 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
405 if (client
->mac_addr_len
== 0)
408 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
413 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
421 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
422 (iaid_append
? sizeof(client
->client_id
.ns
.iaid
) : 0);
424 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
425 log_dhcp_client(client
, "Configured %sDUID, restarting.", iaid_append
? "IAID+" : "");
426 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
427 sd_dhcp_client_start(client
);
433 int sd_dhcp_client_set_iaid_duid(
434 sd_dhcp_client
*client
,
440 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, duid_type
, duid
, duid_len
, 0);
443 int sd_dhcp_client_set_iaid_duid_llt(
444 sd_dhcp_client
*client
,
448 return dhcp_client_set_iaid_duid_internal(client
, true, iaid_set
, iaid
, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
451 int sd_dhcp_client_set_duid(
452 sd_dhcp_client
*client
,
456 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, duid_type
, duid
, duid_len
, 0);
459 int sd_dhcp_client_set_duid_llt(
460 sd_dhcp_client
*client
,
462 return dhcp_client_set_iaid_duid_internal(client
, false, false, 0, DUID_TYPE_LLT
, NULL
, 0, llt_time
);
465 int sd_dhcp_client_set_hostname(
466 sd_dhcp_client
*client
,
467 const char *hostname
) {
469 assert_return(client
, -EINVAL
);
471 /* Make sure hostnames qualify as DNS and as Linux hostnames */
473 !(hostname_is_valid(hostname
, false) && dns_name_is_valid(hostname
) > 0))
476 return free_and_strdup(&client
->hostname
, hostname
);
479 int sd_dhcp_client_set_vendor_class_identifier(
480 sd_dhcp_client
*client
,
483 assert_return(client
, -EINVAL
);
485 return free_and_strdup(&client
->vendor_class_identifier
, vci
);
488 int sd_dhcp_client_set_user_class(
489 sd_dhcp_client
*client
,
490 const char* const* user_class
) {
492 _cleanup_strv_free_
char **s
= NULL
;
495 STRV_FOREACH(p
, (char **) user_class
)
496 if (strlen(*p
) > 255)
497 return -ENAMETOOLONG
;
499 s
= strv_copy((char **) user_class
);
503 client
->user_class
= TAKE_PTR(s
);
508 int sd_dhcp_client_set_client_port(
509 sd_dhcp_client
*client
,
512 assert_return(client
, -EINVAL
);
519 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
520 assert_return(client
, -EINVAL
);
521 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
528 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
529 assert_return(client
, -EINVAL
);
531 if (!IN_SET(client
->state
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
532 return -EADDRNOTAVAIL
;
535 *ret
= client
->lease
;
540 static void client_notify(sd_dhcp_client
*client
, int event
) {
543 if (client
->callback
)
544 client
->callback(client
, event
, client
->userdata
);
547 static int client_initialize(sd_dhcp_client
*client
) {
548 assert_return(client
, -EINVAL
);
550 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
552 client
->fd
= asynchronous_close(client
->fd
);
554 (void) event_source_disable(client
->timeout_resend
);
555 (void) event_source_disable(client
->timeout_t1
);
556 (void) event_source_disable(client
->timeout_t2
);
557 (void) event_source_disable(client
->timeout_expire
);
561 client
->state
= DHCP_STATE_INIT
;
564 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
569 static void client_stop(sd_dhcp_client
*client
, int error
) {
573 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
574 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
575 log_dhcp_client(client
, "STOPPED");
577 log_dhcp_client(client
, "STOPPED: Unknown event");
579 client_notify(client
, error
);
581 client_initialize(client
);
584 static int client_message_init(
585 sd_dhcp_client
*client
,
589 size_t *_optoffset
) {
591 _cleanup_free_ DHCPPacket
*packet
= NULL
;
592 size_t optlen
, optoffset
, size
;
599 assert(client
->start_time
);
603 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
605 optlen
= DHCP_MIN_OPTIONS_SIZE
;
606 size
= sizeof(DHCPPacket
) + optlen
;
608 packet
= malloc0(size
);
612 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
613 client
->arp_type
, optlen
, &optoffset
);
617 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
618 refuse to issue an DHCP lease if 'secs' is set to zero */
619 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
622 assert(time_now
>= client
->start_time
);
624 /* seconds between sending first and last DISCOVER
625 * must always be strictly positive to deal with broken servers */
626 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
627 packet
->dhcp
.secs
= htobe16(secs
);
629 /* RFC2132 section 4.1
630 A client that cannot receive unicast IP datagrams until its protocol
631 software has been configured with an IP address SHOULD set the
632 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
633 DHCPREQUEST messages that client sends. The BROADCAST bit will
634 provide a hint to the DHCP server and BOOTP relay agent to broadcast
635 any messages to the client on the client's subnet.
637 Note: some interfaces needs this to be enabled, but some networks
638 needs this to be disabled as broadcasts are filteretd, so this
639 needs to be configurable */
640 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
641 packet
->dhcp
.flags
= htobe16(0x8000);
643 /* RFC2132 section 4.1.1:
644 The client MUST include its hardware address in the ’chaddr’ field, if
645 necessary for delivery of DHCP reply messages. Non-Ethernet
646 interfaces will leave 'chaddr' empty and use the client identifier
647 instead (eg, RFC 4390 section 2.1).
649 if (client
->arp_type
== ARPHRD_ETHER
)
650 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
652 /* If no client identifier exists, construct an RFC 4361-compliant one */
653 if (client
->client_id_len
== 0) {
656 client
->client_id
.type
= 255;
658 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
659 true, &client
->client_id
.ns
.iaid
);
663 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
667 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
670 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
671 Identifier option is not set */
672 if (client
->client_id_len
) {
673 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
674 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
675 client
->client_id_len
,
681 /* RFC2131 section 3.5:
682 in its initial DHCPDISCOVER or DHCPREQUEST message, a
683 client may provide the server with a list of specific
684 parameters the client is interested in. If the client
685 includes a list of parameters in a DHCPDISCOVER message,
686 it MUST include that list in any subsequent DHCPREQUEST
690 /* RFC7844 section 3:
691 MAY contain the Parameter Request List option. */
692 /* NOTE: in case that there would be an option to do not send
693 * any PRL at all, the size should be checked before sending */
694 if (client
->req_opts_size
> 0) {
695 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
696 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
697 client
->req_opts_size
, client
->req_opts
);
702 /* RFC2131 section 3.5:
703 The client SHOULD include the ’maximum DHCP message size’ option to
704 let the server know how large the server may make its DHCP messages.
706 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
707 than the defined default size unless the Maximum Message Size option
710 RFC3442 "Requirements to Avoid Sizing Constraints":
711 Because a full routing table can be quite large, the standard 576
712 octet maximum size for a DHCP message may be too short to contain
713 some legitimate Classless Static Route options. Because of this,
714 clients implementing the Classless Static Route option SHOULD send a
715 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
716 stack is capable of receiving larger IP datagrams. In this case, the
717 client SHOULD set the value of this option to at least the MTU of the
718 interface that the client is configuring. The client MAY set the
719 value of this option higher, up to the size of the largest UDP packet
720 it is prepared to accept. (Note that the value specified in the
721 Maximum DHCP Message Size option is the total maximum packet size,
722 including IP and UDP headers.)
724 /* RFC7844 section 3:
725 SHOULD NOT contain any other option. */
726 if (!client
->anonymize
) {
727 max_size
= htobe16(size
);
728 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
729 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
736 *_optoffset
= optoffset
;
737 *ret
= TAKE_PTR(packet
);
742 static int client_append_fqdn_option(
743 DHCPMessage
*message
,
748 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
751 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
752 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
753 buffer
[1] = 0; /* RCODE1 (deprecated) */
754 buffer
[2] = 0; /* RCODE2 (deprecated) */
756 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
758 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
759 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
764 static int dhcp_client_send_raw(
765 sd_dhcp_client
*client
,
769 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
770 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
772 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
776 static int client_send_discover(sd_dhcp_client
*client
) {
777 _cleanup_free_ DHCPPacket
*discover
= NULL
;
778 size_t optoffset
, optlen
;
782 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
784 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
785 &optlen
, &optoffset
);
789 /* the client may suggest values for the network address
790 and lease time in the DHCPDISCOVER message. The client may include
791 the ’requested IP address’ option to suggest that a particular IP
792 address be assigned, and may include the ’IP address lease time’
793 option to suggest the lease time it would like.
795 if (client
->last_addr
!= INADDR_ANY
) {
796 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
797 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
798 4, &client
->last_addr
);
803 if (client
->hostname
) {
804 /* According to RFC 4702 "clients that send the Client FQDN option in
805 their messages MUST NOT also send the Host Name option". Just send
806 one of the two depending on the hostname type.
808 if (dns_name_is_single_label(client
->hostname
)) {
809 /* it is unclear from RFC 2131 if client should send hostname in
810 DHCPDISCOVER but dhclient does and so we do as well
812 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
813 SD_DHCP_OPTION_HOST_NAME
,
814 strlen(client
->hostname
), client
->hostname
);
816 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
822 if (client
->vendor_class_identifier
) {
823 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
824 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
825 strlen(client
->vendor_class_identifier
),
826 client
->vendor_class_identifier
);
831 if (client
->user_class
) {
832 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
833 SD_DHCP_OPTION_USER_CLASS
,
834 strv_length(client
->user_class
),
840 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
841 SD_DHCP_OPTION_END
, 0, NULL
);
845 /* We currently ignore:
846 The client SHOULD wait a random time between one and ten seconds to
847 desynchronize the use of DHCP at startup.
849 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
853 log_dhcp_client(client
, "DISCOVER");
858 static int client_send_request(sd_dhcp_client
*client
) {
859 _cleanup_free_ DHCPPacket
*request
= NULL
;
860 size_t optoffset
, optlen
;
865 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
869 switch (client
->state
) {
870 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
871 SELECTING should be REQUESTING)
874 case DHCP_STATE_REQUESTING
:
875 /* Client inserts the address of the selected server in ’server
876 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
877 filled in with the yiaddr value from the chosen DHCPOFFER.
880 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
881 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
882 4, &client
->lease
->server_address
);
886 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
887 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
888 4, &client
->lease
->address
);
894 case DHCP_STATE_INIT_REBOOT
:
895 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
896 option MUST be filled in with client’s notion of its previously
897 assigned address. ’ciaddr’ MUST be zero.
899 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
900 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
901 4, &client
->last_addr
);
906 case DHCP_STATE_RENEWING
:
907 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
908 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
912 case DHCP_STATE_REBINDING
:
913 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
914 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
917 This message MUST be broadcast to the 0xffffffff IP broadcast address.
919 request
->dhcp
.ciaddr
= client
->lease
->address
;
923 case DHCP_STATE_INIT
:
924 case DHCP_STATE_SELECTING
:
925 case DHCP_STATE_REBOOTING
:
926 case DHCP_STATE_BOUND
:
927 case DHCP_STATE_STOPPED
:
931 if (client
->hostname
) {
932 if (dns_name_is_single_label(client
->hostname
))
933 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
934 SD_DHCP_OPTION_HOST_NAME
,
935 strlen(client
->hostname
), client
->hostname
);
937 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
943 if (client
->vendor_class_identifier
) {
944 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
945 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
946 strlen(client
->vendor_class_identifier
),
947 client
->vendor_class_identifier
);
952 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
953 SD_DHCP_OPTION_END
, 0, NULL
);
957 if (client
->state
== DHCP_STATE_RENEWING
) {
958 r
= dhcp_network_send_udp_socket(client
->fd
,
959 client
->lease
->server_address
,
962 sizeof(DHCPMessage
) + optoffset
);
964 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
969 switch (client
->state
) {
971 case DHCP_STATE_REQUESTING
:
972 log_dhcp_client(client
, "REQUEST (requesting)");
975 case DHCP_STATE_INIT_REBOOT
:
976 log_dhcp_client(client
, "REQUEST (init-reboot)");
979 case DHCP_STATE_RENEWING
:
980 log_dhcp_client(client
, "REQUEST (renewing)");
983 case DHCP_STATE_REBINDING
:
984 log_dhcp_client(client
, "REQUEST (rebinding)");
988 log_dhcp_client(client
, "REQUEST (invalid)");
995 static int client_start(sd_dhcp_client
*client
);
997 static int client_timeout_resend(
1002 sd_dhcp_client
*client
= userdata
;
1003 DHCP_CLIENT_DONT_DESTROY(client
);
1004 usec_t next_timeout
= 0;
1011 assert(client
->event
);
1013 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1017 switch (client
->state
) {
1019 case DHCP_STATE_RENEWING
:
1021 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1025 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1029 case DHCP_STATE_REBINDING
:
1031 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1035 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1038 case DHCP_STATE_REBOOTING
:
1039 /* start over as we did not receive a timely ack or nak */
1040 r
= client_initialize(client
);
1044 r
= client_start(client
);
1048 log_dhcp_client(client
, "REBOOTED");
1052 case DHCP_STATE_INIT
:
1053 case DHCP_STATE_INIT_REBOOT
:
1054 case DHCP_STATE_SELECTING
:
1055 case DHCP_STATE_REQUESTING
:
1056 case DHCP_STATE_BOUND
:
1058 if (client
->attempt
< 64)
1059 client
->attempt
*= 2;
1061 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
1065 case DHCP_STATE_STOPPED
:
1070 next_timeout
+= (random_u32() & 0x1fffff);
1072 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1073 clock_boottime_or_monotonic(),
1074 next_timeout
, 10 * USEC_PER_MSEC
,
1075 client_timeout_resend
, client
,
1076 client
->event_priority
, "dhcp4-resend-timer", true);
1080 switch (client
->state
) {
1081 case DHCP_STATE_INIT
:
1082 r
= client_send_discover(client
);
1084 client
->state
= DHCP_STATE_SELECTING
;
1085 client
->attempt
= 1;
1087 if (client
->attempt
>= 64)
1093 case DHCP_STATE_SELECTING
:
1094 r
= client_send_discover(client
);
1095 if (r
< 0 && client
->attempt
>= 64)
1100 case DHCP_STATE_INIT_REBOOT
:
1101 case DHCP_STATE_REQUESTING
:
1102 case DHCP_STATE_RENEWING
:
1103 case DHCP_STATE_REBINDING
:
1104 r
= client_send_request(client
);
1105 if (r
< 0 && client
->attempt
>= 64)
1108 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1109 client
->state
= DHCP_STATE_REBOOTING
;
1111 client
->request_sent
= time_now
;
1115 case DHCP_STATE_REBOOTING
:
1116 case DHCP_STATE_BOUND
:
1120 case DHCP_STATE_STOPPED
:
1128 client_stop(client
, r
);
1130 /* Errors were dealt with when stopping the client, don't spill
1131 errors into the event loop handler */
1135 static int client_initialize_io_events(
1136 sd_dhcp_client
*client
,
1137 sd_event_io_handler_t io_callback
) {
1142 assert(client
->event
);
1144 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1145 client
->fd
, EPOLLIN
, io_callback
,
1150 r
= sd_event_source_set_priority(client
->receive_message
,
1151 client
->event_priority
);
1155 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1161 client_stop(client
, r
);
1166 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1171 assert(client
->event
);
1173 if (client
->start_delay
) {
1174 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1175 usec
+= client
->start_delay
;
1178 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1179 clock_boottime_or_monotonic(),
1181 client_timeout_resend
, client
,
1182 client
->event_priority
, "dhcp4-resend-timer", true);
1184 client_stop(client
, r
);
1190 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1191 client_initialize_io_events(client
, io_callback
);
1192 client_initialize_time_events(client
);
1197 static int client_start_delayed(sd_dhcp_client
*client
) {
1200 assert_return(client
, -EINVAL
);
1201 assert_return(client
->event
, -EINVAL
);
1202 assert_return(client
->ifindex
> 0, -EINVAL
);
1203 assert_return(client
->fd
< 0, -EBUSY
);
1204 assert_return(client
->xid
== 0, -EINVAL
);
1205 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1207 client
->xid
= random_u32();
1209 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1210 client
->xid
, client
->mac_addr
,
1211 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1213 client_stop(client
, r
);
1218 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1219 client
->start_time
= now(clock_boottime_or_monotonic());
1221 return client_initialize_events(client
, client_receive_message_raw
);
1224 static int client_start(sd_dhcp_client
*client
) {
1225 client
->start_delay
= 0;
1226 return client_start_delayed(client
);
1229 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1230 sd_dhcp_client
*client
= userdata
;
1231 DHCP_CLIENT_DONT_DESTROY(client
);
1233 log_dhcp_client(client
, "EXPIRED");
1235 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1237 /* lease was lost, start over if not freed or stopped in callback */
1238 if (client
->state
!= DHCP_STATE_STOPPED
) {
1239 client_initialize(client
);
1240 client_start(client
);
1246 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1247 sd_dhcp_client
*client
= userdata
;
1248 DHCP_CLIENT_DONT_DESTROY(client
);
1253 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1254 client
->fd
= asynchronous_close(client
->fd
);
1256 client
->state
= DHCP_STATE_REBINDING
;
1257 client
->attempt
= 1;
1259 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1260 client
->xid
, client
->mac_addr
,
1261 client
->mac_addr_len
, client
->arp_type
,
1264 client_stop(client
, r
);
1269 return client_initialize_events(client
, client_receive_message_raw
);
1272 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1273 sd_dhcp_client
*client
= userdata
;
1274 DHCP_CLIENT_DONT_DESTROY(client
);
1276 client
->state
= DHCP_STATE_RENEWING
;
1277 client
->attempt
= 1;
1279 return client_initialize_time_events(client
);
1282 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1283 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1286 r
= dhcp_lease_new(&lease
);
1290 if (client
->client_id_len
) {
1291 r
= dhcp_lease_set_client_id(lease
,
1292 (uint8_t *) &client
->client_id
,
1293 client
->client_id_len
);
1298 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1299 if (r
!= DHCP_OFFER
) {
1300 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1304 lease
->next_server
= offer
->siaddr
;
1305 lease
->address
= offer
->yiaddr
;
1307 if (lease
->address
== 0 ||
1308 lease
->server_address
== 0 ||
1309 lease
->lifetime
== 0) {
1310 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1314 if (!lease
->have_subnet_mask
) {
1315 r
= dhcp_lease_set_default_subnet_mask(lease
);
1317 log_dhcp_client(client
,
1318 "received lease lacks subnet mask, "
1319 "and a fallback one cannot be generated, ignoring");
1324 sd_dhcp_lease_unref(client
->lease
);
1325 client
->lease
= TAKE_PTR(lease
);
1327 log_dhcp_client(client
, "OFFER");
1332 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1335 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1336 if (r
!= DHCP_FORCERENEW
)
1339 log_dhcp_client(client
, "FORCERENEW");
1344 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1345 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1346 _cleanup_free_
char *error_message
= NULL
;
1349 r
= dhcp_lease_new(&lease
);
1353 if (client
->client_id_len
) {
1354 r
= dhcp_lease_set_client_id(lease
,
1355 (uint8_t *) &client
->client_id
,
1356 client
->client_id_len
);
1361 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1362 if (r
== DHCP_NAK
) {
1363 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1364 return -EADDRNOTAVAIL
;
1367 if (r
!= DHCP_ACK
) {
1368 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1372 lease
->next_server
= ack
->siaddr
;
1374 lease
->address
= ack
->yiaddr
;
1376 if (lease
->address
== INADDR_ANY
||
1377 lease
->server_address
== INADDR_ANY
||
1378 lease
->lifetime
== 0) {
1379 log_dhcp_client(client
, "received lease lacks address, server "
1380 "address or lease lifetime, ignoring");
1384 if (lease
->subnet_mask
== INADDR_ANY
) {
1385 r
= dhcp_lease_set_default_subnet_mask(lease
);
1387 log_dhcp_client(client
,
1388 "received lease lacks subnet mask, "
1389 "and a fallback one cannot be generated, ignoring");
1394 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1395 if (client
->lease
) {
1396 if (client
->lease
->address
!= lease
->address
||
1397 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1398 client
->lease
->router
!= lease
->router
) {
1399 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1401 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1403 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1406 client
->lease
= TAKE_PTR(lease
);
1408 log_dhcp_client(client
, "ACK");
1413 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1415 assert(client
->request_sent
);
1416 assert(lifetime
> 0);
1423 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1424 + (random_u32() & 0x1fffff);
1427 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1429 uint64_t lifetime_timeout
;
1430 uint64_t t2_timeout
;
1431 uint64_t t1_timeout
;
1432 char time_string
[FORMAT_TIMESPAN_MAX
];
1436 assert(client
->event
);
1437 assert(client
->lease
);
1438 assert(client
->lease
->lifetime
);
1440 /* don't set timers for infinite leases */
1441 if (client
->lease
->lifetime
== 0xffffffff) {
1442 (void) event_source_disable(client
->timeout_t1
);
1443 (void) event_source_disable(client
->timeout_t2
);
1444 (void) event_source_disable(client
->timeout_expire
);
1449 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1452 assert(client
->request_sent
<= time_now
);
1454 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1455 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1456 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1457 /* both T1 and T2 are given */
1458 if (client
->lease
->t1
< client
->lease
->t2
&&
1459 client
->lease
->t2
< client
->lease
->lifetime
) {
1460 /* they are both valid */
1461 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1462 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1465 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1466 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1467 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1468 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1470 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1471 /* only T2 is given, and it is valid */
1472 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1473 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1474 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1475 if (t2_timeout
<= t1_timeout
) {
1476 /* the computed T1 would be invalid, so discard T2 */
1477 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1478 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1480 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1481 /* only T1 is given, and it is valid */
1482 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1483 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1484 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1485 if (t2_timeout
<= t1_timeout
) {
1486 /* the computed T2 would be invalid, so discard T1 */
1487 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1488 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1491 /* fall back to the default timeouts */
1492 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1493 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1494 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1495 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1498 /* arm lifetime timeout */
1499 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1500 clock_boottime_or_monotonic(),
1501 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1502 client_timeout_expire
, client
,
1503 client
->event_priority
, "dhcp4-lifetime", true);
1507 log_dhcp_client(client
, "lease expires in %s",
1508 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1510 /* don't arm earlier timeouts if this has already expired */
1511 if (lifetime_timeout
<= time_now
)
1514 /* arm T2 timeout */
1515 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1516 clock_boottime_or_monotonic(),
1517 t2_timeout
, 10 * USEC_PER_MSEC
,
1518 client_timeout_t2
, client
,
1519 client
->event_priority
, "dhcp4-t2-timeout", true);
1523 log_dhcp_client(client
, "T2 expires in %s",
1524 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1526 /* don't arm earlier timeout if this has already expired */
1527 if (t2_timeout
<= time_now
)
1530 /* arm T1 timeout */
1531 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1532 clock_boottime_or_monotonic(),
1533 t1_timeout
, 10 * USEC_PER_MSEC
,
1534 client_timeout_t1
, client
,
1535 client
->event_priority
, "dhcp4-t1-timer", true);
1539 log_dhcp_client(client
, "T1 expires in %s",
1540 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1545 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1546 DHCP_CLIENT_DONT_DESTROY(client
);
1547 char time_string
[FORMAT_TIMESPAN_MAX
];
1548 int r
= 0, notify_event
= 0;
1551 assert(client
->event
);
1554 switch (client
->state
) {
1555 case DHCP_STATE_SELECTING
:
1557 r
= client_handle_offer(client
, message
, len
);
1560 client
->state
= DHCP_STATE_REQUESTING
;
1561 client
->attempt
= 1;
1563 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1564 clock_boottime_or_monotonic(),
1566 client_timeout_resend
, client
,
1567 client
->event_priority
, "dhcp4-resend-timer", true);
1570 } else if (r
== -ENOMSG
)
1571 /* invalid message, let's ignore it */
1576 case DHCP_STATE_REBOOTING
:
1577 case DHCP_STATE_REQUESTING
:
1578 case DHCP_STATE_RENEWING
:
1579 case DHCP_STATE_REBINDING
:
1581 r
= client_handle_ack(client
, message
, len
);
1583 client
->start_delay
= 0;
1584 (void) event_source_disable(client
->timeout_resend
);
1585 client
->receive_message
=
1586 sd_event_source_unref(client
->receive_message
);
1587 client
->fd
= asynchronous_close(client
->fd
);
1589 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1590 DHCP_STATE_REBOOTING
))
1591 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1592 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1595 client
->state
= DHCP_STATE_BOUND
;
1596 client
->attempt
= 1;
1598 client
->last_addr
= client
->lease
->address
;
1600 r
= client_set_lease_timeouts(client
);
1602 log_dhcp_client(client
, "could not set lease timeouts");
1606 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1608 log_dhcp_client(client
, "could not bind UDP socket");
1614 client_initialize_io_events(client
, client_receive_message_udp
);
1617 client_notify(client
, notify_event
);
1618 if (client
->state
== DHCP_STATE_STOPPED
)
1622 } else if (r
== -EADDRNOTAVAIL
) {
1623 /* got a NAK, let's restart the client */
1624 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1626 r
= client_initialize(client
);
1630 r
= client_start_delayed(client
);
1634 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1635 client
->start_delay
, USEC_PER_SEC
));
1637 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1638 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1641 } else if (r
== -ENOMSG
)
1642 /* invalid message, let's ignore it */
1647 case DHCP_STATE_BOUND
:
1648 r
= client_handle_forcerenew(client
, message
, len
);
1650 r
= client_timeout_t1(NULL
, 0, client
);
1653 } else if (r
== -ENOMSG
)
1654 /* invalid message, let's ignore it */
1659 case DHCP_STATE_INIT
:
1660 case DHCP_STATE_INIT_REBOOT
:
1664 case DHCP_STATE_STOPPED
:
1671 client_stop(client
, r
);
1676 static int client_receive_message_udp(
1682 sd_dhcp_client
*client
= userdata
;
1683 _cleanup_free_ DHCPMessage
*message
= NULL
;
1684 const struct ether_addr zero_mac
= {};
1685 const struct ether_addr
*expected_chaddr
= NULL
;
1686 uint8_t expected_hlen
= 0;
1687 ssize_t len
, buflen
;
1692 buflen
= next_datagram_size_fd(fd
);
1696 message
= malloc0(buflen
);
1700 len
= recv(fd
, message
, buflen
, 0);
1702 if (IN_SET(errno
, EAGAIN
, EINTR
))
1705 return log_dhcp_client_errno(client
, errno
,
1706 "Could not receive message from UDP socket: %m");
1708 if ((size_t) len
< sizeof(DHCPMessage
)) {
1709 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1713 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1714 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1718 if (message
->op
!= BOOTREPLY
) {
1719 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1723 if (message
->htype
!= client
->arp_type
) {
1724 log_dhcp_client(client
, "Packet type does not match client type");
1728 if (client
->arp_type
== ARPHRD_ETHER
) {
1729 expected_hlen
= ETH_ALEN
;
1730 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1732 /* Non-Ethernet links expect zero chaddr */
1734 expected_chaddr
= &zero_mac
;
1737 if (message
->hlen
!= expected_hlen
) {
1738 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1742 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1743 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1747 if (client
->state
!= DHCP_STATE_BOUND
&&
1748 be32toh(message
->xid
) != client
->xid
) {
1749 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1750 so ignore the xid in this case */
1751 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1752 be32toh(message
->xid
), client
->xid
);
1756 return client_handle_message(client
, message
, len
);
1759 static int client_receive_message_raw(
1765 sd_dhcp_client
*client
= userdata
;
1766 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1767 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1768 struct iovec iov
= {};
1769 struct msghdr msg
= {
1772 .msg_control
= cmsgbuf
,
1773 .msg_controllen
= sizeof(cmsgbuf
),
1775 struct cmsghdr
*cmsg
;
1776 bool checksum
= true;
1777 ssize_t buflen
, len
;
1783 buflen
= next_datagram_size_fd(fd
);
1787 packet
= malloc0(buflen
);
1791 iov
= IOVEC_MAKE(packet
, buflen
);
1793 len
= recvmsg(fd
, &msg
, 0);
1795 if (IN_SET(errno
, EAGAIN
, EINTR
))
1798 return log_dhcp_client_errno(client
, errno
,
1799 "Could not receive message from raw socket: %m");
1800 } else if ((size_t)len
< sizeof(DHCPPacket
))
1803 CMSG_FOREACH(cmsg
, &msg
) {
1804 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1805 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1806 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1807 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1809 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1814 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1818 len
-= DHCP_IP_UDP_SIZE
;
1820 return client_handle_message(client
, &packet
->dhcp
, len
);
1823 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1826 assert_return(client
, -EINVAL
);
1828 r
= client_initialize(client
);
1832 /* RFC7844 section 3.3:
1833 SHOULD perform a complete four-way handshake, starting with a
1834 DHCPDISCOVER, to obtain a new address lease. If the client can
1835 ascertain that this is exactly the same network to which it was
1836 previously connected, and if the link-layer address did not change,
1837 the client MAY issue a DHCPREQUEST to try to reclaim the current
1839 if (client
->last_addr
&& !client
->anonymize
)
1840 client
->state
= DHCP_STATE_INIT_REBOOT
;
1842 r
= client_start(client
);
1844 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1849 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1850 DHCP_CLIENT_DONT_DESTROY(client
);
1852 assert_return(client
, -EINVAL
);
1854 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1855 client
->state
= DHCP_STATE_STOPPED
;
1860 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1863 assert_return(client
, -EINVAL
);
1864 assert_return(!client
->event
, -EBUSY
);
1867 client
->event
= sd_event_ref(event
);
1869 r
= sd_event_default(&client
->event
);
1874 client
->event_priority
= priority
;
1879 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1880 assert_return(client
, -EINVAL
);
1882 client
->event
= sd_event_unref(client
->event
);
1887 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1888 assert_return(client
, NULL
);
1890 return client
->event
;
1893 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1896 log_dhcp_client(client
, "FREE");
1898 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1899 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1900 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1901 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1903 client_initialize(client
);
1905 sd_dhcp_client_detach_event(client
);
1907 sd_dhcp_lease_unref(client
->lease
);
1909 free(client
->req_opts
);
1910 free(client
->hostname
);
1911 free(client
->vendor_class_identifier
);
1912 client
->user_class
= strv_free(client
->user_class
);
1913 return mfree(client
);
1916 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1918 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1919 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1921 assert_return(ret
, -EINVAL
);
1923 client
= new(sd_dhcp_client
, 1);
1927 *client
= (sd_dhcp_client
) {
1929 .state
= DHCP_STATE_INIT
,
1933 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1934 .port
= DHCP_PORT_CLIENT
,
1935 .anonymize
= !!anonymize
,
1937 /* NOTE: this could be moved to a function. */
1939 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1940 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1942 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1943 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1945 if (!client
->req_opts
)
1948 *ret
= TAKE_PTR(client
);