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"
26 #include "random-util.h"
27 #include "string-util.h"
31 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
32 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
34 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
35 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
37 struct sd_dhcp_client
{
43 sd_event_source
*timeout_resend
;
47 union sockaddr_union link
;
48 sd_event_source
*receive_message
;
49 bool request_broadcast
;
51 size_t req_opts_allocated
;
55 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
62 /* 0: Generic (non-LL) (RFC 2132) */
63 uint8_t data
[MAX_CLIENT_ID_LEN
];
66 /* 1: Ethernet Link-Layer (RFC 2132) */
67 uint8_t haddr
[ETH_ALEN
];
70 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
74 /* 255: Node-specific (RFC 4361) */
79 uint8_t data
[MAX_CLIENT_ID_LEN
];
85 char *vendor_class_identifier
;
92 sd_event_source
*timeout_t1
;
93 sd_event_source
*timeout_t2
;
94 sd_event_source
*timeout_expire
;
95 sd_dhcp_client_callback_t callback
;
101 static const uint8_t default_req_opts
[] = {
102 SD_DHCP_OPTION_SUBNET_MASK
,
103 SD_DHCP_OPTION_ROUTER
,
104 SD_DHCP_OPTION_HOST_NAME
,
105 SD_DHCP_OPTION_DOMAIN_NAME
,
106 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
109 /* RFC7844 section 3:
110 MAY contain the Parameter Request List option.
112 The client intending to protect its privacy SHOULD only request a
113 minimal number of options in the PRL and SHOULD also randomly shuffle
114 the ordering of option codes in the PRL. If this random ordering
115 cannot be implemented, the client MAY order the option codes in the
116 PRL by option code number (lowest to highest).
118 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
119 static const uint8_t default_req_opts_anonymize
[] = {
120 SD_DHCP_OPTION_SUBNET_MASK
, /* 1 */
121 SD_DHCP_OPTION_ROUTER
, /* 3 */
122 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
, /* 6 */
123 SD_DHCP_OPTION_DOMAIN_NAME
, /* 15 */
124 SD_DHCP_OPTION_ROUTER_DISCOVER
, /* 31 */
125 SD_DHCP_OPTION_STATIC_ROUTE
, /* 33 */
126 SD_DHCP_OPTION_VENDOR_SPECIFIC
, /* 43 */
127 SD_DHCP_OPTION_NETBIOS_NAMESERVER
, /* 44 */
128 SD_DHCP_OPTION_NETBIOS_NODETYPE
, /* 46 */
129 SD_DHCP_OPTION_NETBIOS_SCOPE
, /* 47 */
130 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
, /* 121 */
131 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE
, /* 249 */
132 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY
, /* 252 */
135 static int client_receive_message_raw(
140 static int client_receive_message_udp(
145 static void client_stop(sd_dhcp_client
*client
, int error
);
147 int sd_dhcp_client_set_callback(
148 sd_dhcp_client
*client
,
149 sd_dhcp_client_callback_t cb
,
152 assert_return(client
, -EINVAL
);
154 client
->callback
= cb
;
155 client
->userdata
= userdata
;
160 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
161 assert_return(client
, -EINVAL
);
163 client
->request_broadcast
= !!broadcast
;
168 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
171 assert_return(client
, -EINVAL
);
172 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
176 case SD_DHCP_OPTION_PAD
:
177 case SD_DHCP_OPTION_OVERLOAD
:
178 case SD_DHCP_OPTION_MESSAGE_TYPE
:
179 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
180 case SD_DHCP_OPTION_END
:
187 for (i
= 0; i
< client
->req_opts_size
; i
++)
188 if (client
->req_opts
[i
] == option
)
191 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
192 client
->req_opts_size
+ 1))
195 client
->req_opts
[client
->req_opts_size
++] = option
;
200 int sd_dhcp_client_set_request_address(
201 sd_dhcp_client
*client
,
202 const struct in_addr
*last_addr
) {
204 assert_return(client
, -EINVAL
);
205 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
208 client
->last_addr
= last_addr
->s_addr
;
210 client
->last_addr
= INADDR_ANY
;
215 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
217 assert_return(client
, -EINVAL
);
218 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
219 assert_return(ifindex
> 0, -EINVAL
);
221 client
->ifindex
= ifindex
;
225 int sd_dhcp_client_set_mac(
226 sd_dhcp_client
*client
,
231 DHCP_CLIENT_DONT_DESTROY(client
);
232 bool need_restart
= false;
234 assert_return(client
, -EINVAL
);
235 assert_return(addr
, -EINVAL
);
236 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
237 assert_return(arp_type
> 0, -EINVAL
);
239 if (arp_type
== ARPHRD_ETHER
)
240 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
241 else if (arp_type
== ARPHRD_INFINIBAND
)
242 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
246 if (client
->mac_addr_len
== addr_len
&&
247 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
250 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
251 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
253 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
256 memcpy(&client
->mac_addr
, addr
, addr_len
);
257 client
->mac_addr_len
= addr_len
;
258 client
->arp_type
= arp_type
;
260 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
261 sd_dhcp_client_start(client
);
266 int sd_dhcp_client_get_client_id(
267 sd_dhcp_client
*client
,
269 const uint8_t **data
,
272 assert_return(client
, -EINVAL
);
273 assert_return(type
, -EINVAL
);
274 assert_return(data
, -EINVAL
);
275 assert_return(data_len
, -EINVAL
);
280 if (client
->client_id_len
) {
281 *type
= client
->client_id
.type
;
282 *data
= client
->client_id
.raw
.data
;
283 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
289 int sd_dhcp_client_set_client_id(
290 sd_dhcp_client
*client
,
295 DHCP_CLIENT_DONT_DESTROY(client
);
296 bool need_restart
= false;
298 assert_return(client
, -EINVAL
);
299 assert_return(data
, -EINVAL
);
300 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
305 if (data_len
!= ETH_ALEN
)
309 case ARPHRD_INFINIBAND
:
310 if (data_len
!= INFINIBAND_ALEN
)
318 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
319 client
->client_id
.type
== type
&&
320 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
323 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
324 log_dhcp_client(client
, "Changing client ID on running DHCP "
325 "client, restarting");
327 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
330 client
->client_id
.type
= type
;
331 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
332 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
334 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
335 sd_dhcp_client_start(client
);
341 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
342 * without further modification. Otherwise, if duid_type is supported, DUID
343 * is set based on that type. Otherwise, an error is returned.
345 static int dhcp_client_set_iaid_duid_internal(
346 sd_dhcp_client
*client
,
354 DHCP_CLIENT_DONT_DESTROY(client
);
358 assert_return(client
, -EINVAL
);
359 assert_return(duid_len
== 0 || duid
!= NULL
, -EINVAL
);
362 r
= dhcp_validate_duid_len(duid_type
, duid_len
);
367 zero(client
->client_id
);
368 client
->client_id
.type
= 255;
371 /* If IAID is not configured, generate it. */
373 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
374 client
->mac_addr_len
,
376 &client
->client_id
.ns
.iaid
);
380 client
->client_id
.ns
.iaid
= htobe32(iaid
);
384 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
385 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
386 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
390 if (client
->mac_addr_len
== 0)
393 r
= dhcp_identifier_set_duid_llt(&client
->client_id
.ns
.duid
, llt_time
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
398 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
403 if (client
->mac_addr_len
== 0)
406 r
= dhcp_identifier_set_duid_ll(&client
->client_id
.ns
.duid
, client
->mac_addr
, client
->mac_addr_len
, client
->arp_type
, &len
);
411 r
= dhcp_identifier_set_duid_uuid(&client
->client_id
.ns
.duid
, &len
);
419 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
420 (append_iaid
? sizeof(client
->client_id
.ns
.iaid
) : 0);
422 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
423 log_dhcp_client(client
, "Configured %sDUID, restarting.", append_iaid
? "IAID+" : "");
424 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
425 sd_dhcp_client_start(client
);
431 int sd_dhcp_client_set_iaid_duid(
432 sd_dhcp_client
*client
,
437 return dhcp_client_set_iaid_duid_internal(client
, iaid
, true, duid_type
, duid
, duid_len
, 0);
440 int sd_dhcp_client_set_iaid_duid_llt(
441 sd_dhcp_client
*client
,
444 return dhcp_client_set_iaid_duid_internal(client
, iaid
, true, 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
, 0, false, 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
, 0, false, 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_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
525 assert_return(client
, -EINVAL
);
527 if (!IN_SET(client
->state
, DHCP_STATE_BOUND
, DHCP_STATE_RENEWING
, DHCP_STATE_REBINDING
))
528 return -EADDRNOTAVAIL
;
531 *ret
= client
->lease
;
536 static void client_notify(sd_dhcp_client
*client
, int event
) {
539 if (client
->callback
)
540 client
->callback(client
, event
, client
->userdata
);
543 static int client_initialize(sd_dhcp_client
*client
) {
544 assert_return(client
, -EINVAL
);
546 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
548 client
->fd
= asynchronous_close(client
->fd
);
550 (void) event_source_disable(client
->timeout_resend
);
551 (void) event_source_disable(client
->timeout_t1
);
552 (void) event_source_disable(client
->timeout_t2
);
553 (void) event_source_disable(client
->timeout_expire
);
557 client
->state
= DHCP_STATE_INIT
;
560 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
565 static void client_stop(sd_dhcp_client
*client
, int error
) {
569 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
570 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
571 log_dhcp_client(client
, "STOPPED");
573 log_dhcp_client(client
, "STOPPED: Unknown event");
575 client_notify(client
, error
);
577 client_initialize(client
);
580 static int client_message_init(
581 sd_dhcp_client
*client
,
585 size_t *_optoffset
) {
587 _cleanup_free_ DHCPPacket
*packet
= NULL
;
588 size_t optlen
, optoffset
, size
;
595 assert(client
->start_time
);
599 assert(IN_SET(type
, DHCP_DISCOVER
, DHCP_REQUEST
));
601 optlen
= DHCP_MIN_OPTIONS_SIZE
;
602 size
= sizeof(DHCPPacket
) + optlen
;
604 packet
= malloc0(size
);
608 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
609 client
->arp_type
, optlen
, &optoffset
);
613 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
614 refuse to issue an DHCP lease if 'secs' is set to zero */
615 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
618 assert(time_now
>= client
->start_time
);
620 /* seconds between sending first and last DISCOVER
621 * must always be strictly positive to deal with broken servers */
622 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
623 packet
->dhcp
.secs
= htobe16(secs
);
625 /* RFC2132 section 4.1
626 A client that cannot receive unicast IP datagrams until its protocol
627 software has been configured with an IP address SHOULD set the
628 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
629 DHCPREQUEST messages that client sends. The BROADCAST bit will
630 provide a hint to the DHCP server and BOOTP relay agent to broadcast
631 any messages to the client on the client's subnet.
633 Note: some interfaces needs this to be enabled, but some networks
634 needs this to be disabled as broadcasts are filteretd, so this
635 needs to be configurable */
636 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
637 packet
->dhcp
.flags
= htobe16(0x8000);
639 /* RFC2132 section 4.1.1:
640 The client MUST include its hardware address in the ’chaddr’ field, if
641 necessary for delivery of DHCP reply messages. Non-Ethernet
642 interfaces will leave 'chaddr' empty and use the client identifier
643 instead (eg, RFC 4390 section 2.1).
645 if (client
->arp_type
== ARPHRD_ETHER
)
646 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
648 /* If no client identifier exists, construct an RFC 4361-compliant one */
649 if (client
->client_id_len
== 0) {
652 client
->client_id
.type
= 255;
654 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
,
655 true, &client
->client_id
.ns
.iaid
);
659 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
663 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
666 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
667 Identifier option is not set */
668 if (client
->client_id_len
) {
669 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
670 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
671 client
->client_id_len
,
677 /* RFC2131 section 3.5:
678 in its initial DHCPDISCOVER or DHCPREQUEST message, a
679 client may provide the server with a list of specific
680 parameters the client is interested in. If the client
681 includes a list of parameters in a DHCPDISCOVER message,
682 it MUST include that list in any subsequent DHCPREQUEST
686 /* RFC7844 section 3:
687 MAY contain the Parameter Request List option. */
688 /* NOTE: in case that there would be an option to do not send
689 * any PRL at all, the size should be checked before sending */
690 if (client
->req_opts_size
> 0) {
691 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
692 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
693 client
->req_opts_size
, client
->req_opts
);
698 /* RFC2131 section 3.5:
699 The client SHOULD include the ’maximum DHCP message size’ option to
700 let the server know how large the server may make its DHCP messages.
702 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
703 than the defined default size unless the Maximum Message Size option
706 RFC3442 "Requirements to Avoid Sizing Constraints":
707 Because a full routing table can be quite large, the standard 576
708 octet maximum size for a DHCP message may be too short to contain
709 some legitimate Classless Static Route options. Because of this,
710 clients implementing the Classless Static Route option SHOULD send a
711 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
712 stack is capable of receiving larger IP datagrams. In this case, the
713 client SHOULD set the value of this option to at least the MTU of the
714 interface that the client is configuring. The client MAY set the
715 value of this option higher, up to the size of the largest UDP packet
716 it is prepared to accept. (Note that the value specified in the
717 Maximum DHCP Message Size option is the total maximum packet size,
718 including IP and UDP headers.)
720 /* RFC7844 section 3:
721 SHOULD NOT contain any other option. */
722 if (!client
->anonymize
) {
723 max_size
= htobe16(size
);
724 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
725 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
732 *_optoffset
= optoffset
;
733 *ret
= TAKE_PTR(packet
);
738 static int client_append_fqdn_option(
739 DHCPMessage
*message
,
744 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
747 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
748 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
749 buffer
[1] = 0; /* RCODE1 (deprecated) */
750 buffer
[2] = 0; /* RCODE2 (deprecated) */
752 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
754 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
755 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
760 static int dhcp_client_send_raw(
761 sd_dhcp_client
*client
,
765 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, client
->port
,
766 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
768 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
772 static int client_send_discover(sd_dhcp_client
*client
) {
773 _cleanup_free_ DHCPPacket
*discover
= NULL
;
774 size_t optoffset
, optlen
;
778 assert(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_SELECTING
));
780 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
781 &optlen
, &optoffset
);
785 /* the client may suggest values for the network address
786 and lease time in the DHCPDISCOVER message. The client may include
787 the ’requested IP address’ option to suggest that a particular IP
788 address be assigned, and may include the ’IP address lease time’
789 option to suggest the lease time it would like.
791 if (client
->last_addr
!= INADDR_ANY
) {
792 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
793 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
794 4, &client
->last_addr
);
799 if (client
->hostname
) {
800 /* According to RFC 4702 "clients that send the Client FQDN option in
801 their messages MUST NOT also send the Host Name option". Just send
802 one of the two depending on the hostname type.
804 if (dns_name_is_single_label(client
->hostname
)) {
805 /* it is unclear from RFC 2131 if client should send hostname in
806 DHCPDISCOVER but dhclient does and so we do as well
808 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
809 SD_DHCP_OPTION_HOST_NAME
,
810 strlen(client
->hostname
), client
->hostname
);
812 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
818 if (client
->vendor_class_identifier
) {
819 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
820 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
821 strlen(client
->vendor_class_identifier
),
822 client
->vendor_class_identifier
);
827 if (client
->user_class
) {
828 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
829 SD_DHCP_OPTION_USER_CLASS
,
830 strv_length(client
->user_class
),
836 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
837 SD_DHCP_OPTION_END
, 0, NULL
);
841 /* We currently ignore:
842 The client SHOULD wait a random time between one and ten seconds to
843 desynchronize the use of DHCP at startup.
845 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
849 log_dhcp_client(client
, "DISCOVER");
854 static int client_send_request(sd_dhcp_client
*client
) {
855 _cleanup_free_ DHCPPacket
*request
= NULL
;
856 size_t optoffset
, optlen
;
861 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
865 switch (client
->state
) {
866 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
867 SELECTING should be REQUESTING)
870 case DHCP_STATE_REQUESTING
:
871 /* Client inserts the address of the selected server in ’server
872 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
873 filled in with the yiaddr value from the chosen DHCPOFFER.
876 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
877 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
878 4, &client
->lease
->server_address
);
882 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
883 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
884 4, &client
->lease
->address
);
890 case DHCP_STATE_INIT_REBOOT
:
891 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
892 option MUST be filled in with client’s notion of its previously
893 assigned address. ’ciaddr’ MUST be zero.
895 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
896 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
897 4, &client
->last_addr
);
902 case DHCP_STATE_RENEWING
:
903 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
904 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
908 case DHCP_STATE_REBINDING
:
909 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
910 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
913 This message MUST be broadcast to the 0xffffffff IP broadcast address.
915 request
->dhcp
.ciaddr
= client
->lease
->address
;
919 case DHCP_STATE_INIT
:
920 case DHCP_STATE_SELECTING
:
921 case DHCP_STATE_REBOOTING
:
922 case DHCP_STATE_BOUND
:
923 case DHCP_STATE_STOPPED
:
927 if (client
->hostname
) {
928 if (dns_name_is_single_label(client
->hostname
))
929 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
930 SD_DHCP_OPTION_HOST_NAME
,
931 strlen(client
->hostname
), client
->hostname
);
933 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
939 if (client
->vendor_class_identifier
) {
940 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
941 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
942 strlen(client
->vendor_class_identifier
),
943 client
->vendor_class_identifier
);
948 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
949 SD_DHCP_OPTION_END
, 0, NULL
);
953 if (client
->state
== DHCP_STATE_RENEWING
) {
954 r
= dhcp_network_send_udp_socket(client
->fd
,
955 client
->lease
->server_address
,
958 sizeof(DHCPMessage
) + optoffset
);
960 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
965 switch (client
->state
) {
967 case DHCP_STATE_REQUESTING
:
968 log_dhcp_client(client
, "REQUEST (requesting)");
971 case DHCP_STATE_INIT_REBOOT
:
972 log_dhcp_client(client
, "REQUEST (init-reboot)");
975 case DHCP_STATE_RENEWING
:
976 log_dhcp_client(client
, "REQUEST (renewing)");
979 case DHCP_STATE_REBINDING
:
980 log_dhcp_client(client
, "REQUEST (rebinding)");
984 log_dhcp_client(client
, "REQUEST (invalid)");
991 static int client_start(sd_dhcp_client
*client
);
993 static int client_timeout_resend(
998 sd_dhcp_client
*client
= userdata
;
999 DHCP_CLIENT_DONT_DESTROY(client
);
1000 usec_t next_timeout
= 0;
1007 assert(client
->event
);
1009 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1013 switch (client
->state
) {
1015 case DHCP_STATE_RENEWING
:
1017 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
1021 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1025 case DHCP_STATE_REBINDING
:
1027 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
1031 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
1034 case DHCP_STATE_REBOOTING
:
1035 /* start over as we did not receive a timely ack or nak */
1036 r
= client_initialize(client
);
1040 r
= client_start(client
);
1044 log_dhcp_client(client
, "REBOOTED");
1048 case DHCP_STATE_INIT
:
1049 case DHCP_STATE_INIT_REBOOT
:
1050 case DHCP_STATE_SELECTING
:
1051 case DHCP_STATE_REQUESTING
:
1052 case DHCP_STATE_BOUND
:
1054 if (client
->attempt
< 64)
1055 client
->attempt
*= 2;
1057 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
1061 case DHCP_STATE_STOPPED
:
1066 next_timeout
+= (random_u32() & 0x1fffff);
1068 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1069 clock_boottime_or_monotonic(),
1070 next_timeout
, 10 * USEC_PER_MSEC
,
1071 client_timeout_resend
, client
,
1072 client
->event_priority
, "dhcp4-resend-timer", true);
1076 switch (client
->state
) {
1077 case DHCP_STATE_INIT
:
1078 r
= client_send_discover(client
);
1080 client
->state
= DHCP_STATE_SELECTING
;
1081 client
->attempt
= 1;
1083 if (client
->attempt
>= 64)
1089 case DHCP_STATE_SELECTING
:
1090 r
= client_send_discover(client
);
1091 if (r
< 0 && client
->attempt
>= 64)
1096 case DHCP_STATE_INIT_REBOOT
:
1097 case DHCP_STATE_REQUESTING
:
1098 case DHCP_STATE_RENEWING
:
1099 case DHCP_STATE_REBINDING
:
1100 r
= client_send_request(client
);
1101 if (r
< 0 && client
->attempt
>= 64)
1104 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1105 client
->state
= DHCP_STATE_REBOOTING
;
1107 client
->request_sent
= time_now
;
1111 case DHCP_STATE_REBOOTING
:
1112 case DHCP_STATE_BOUND
:
1116 case DHCP_STATE_STOPPED
:
1124 client_stop(client
, r
);
1126 /* Errors were dealt with when stopping the client, don't spill
1127 errors into the event loop handler */
1131 static int client_initialize_io_events(
1132 sd_dhcp_client
*client
,
1133 sd_event_io_handler_t io_callback
) {
1138 assert(client
->event
);
1140 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1141 client
->fd
, EPOLLIN
, io_callback
,
1146 r
= sd_event_source_set_priority(client
->receive_message
,
1147 client
->event_priority
);
1151 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1157 client_stop(client
, r
);
1162 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1167 assert(client
->event
);
1169 if (client
->start_delay
) {
1170 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1171 usec
+= client
->start_delay
;
1174 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1175 clock_boottime_or_monotonic(),
1177 client_timeout_resend
, client
,
1178 client
->event_priority
, "dhcp4-resend-timer", true);
1180 client_stop(client
, r
);
1186 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1187 client_initialize_io_events(client
, io_callback
);
1188 client_initialize_time_events(client
);
1193 static int client_start_delayed(sd_dhcp_client
*client
) {
1196 assert_return(client
, -EINVAL
);
1197 assert_return(client
->event
, -EINVAL
);
1198 assert_return(client
->ifindex
> 0, -EINVAL
);
1199 assert_return(client
->fd
< 0, -EBUSY
);
1200 assert_return(client
->xid
== 0, -EINVAL
);
1201 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1203 client
->xid
= random_u32();
1205 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1206 client
->xid
, client
->mac_addr
,
1207 client
->mac_addr_len
, client
->arp_type
, client
->port
);
1209 client_stop(client
, r
);
1214 if (IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
))
1215 client
->start_time
= now(clock_boottime_or_monotonic());
1217 return client_initialize_events(client
, client_receive_message_raw
);
1220 static int client_start(sd_dhcp_client
*client
) {
1221 client
->start_delay
= 0;
1222 return client_start_delayed(client
);
1225 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1226 sd_dhcp_client
*client
= userdata
;
1227 DHCP_CLIENT_DONT_DESTROY(client
);
1229 log_dhcp_client(client
, "EXPIRED");
1231 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1233 /* lease was lost, start over if not freed or stopped in callback */
1234 if (client
->state
!= DHCP_STATE_STOPPED
) {
1235 client_initialize(client
);
1236 client_start(client
);
1242 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1243 sd_dhcp_client
*client
= userdata
;
1244 DHCP_CLIENT_DONT_DESTROY(client
);
1249 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1250 client
->fd
= asynchronous_close(client
->fd
);
1252 client
->state
= DHCP_STATE_REBINDING
;
1253 client
->attempt
= 1;
1255 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1256 client
->xid
, client
->mac_addr
,
1257 client
->mac_addr_len
, client
->arp_type
,
1260 client_stop(client
, r
);
1265 return client_initialize_events(client
, client_receive_message_raw
);
1268 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1269 sd_dhcp_client
*client
= userdata
;
1270 DHCP_CLIENT_DONT_DESTROY(client
);
1272 client
->state
= DHCP_STATE_RENEWING
;
1273 client
->attempt
= 1;
1275 return client_initialize_time_events(client
);
1278 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1279 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1282 r
= dhcp_lease_new(&lease
);
1286 if (client
->client_id_len
) {
1287 r
= dhcp_lease_set_client_id(lease
,
1288 (uint8_t *) &client
->client_id
,
1289 client
->client_id_len
);
1294 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1295 if (r
!= DHCP_OFFER
) {
1296 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1300 lease
->next_server
= offer
->siaddr
;
1301 lease
->address
= offer
->yiaddr
;
1303 if (lease
->address
== 0 ||
1304 lease
->server_address
== 0 ||
1305 lease
->lifetime
== 0) {
1306 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1310 if (!lease
->have_subnet_mask
) {
1311 r
= dhcp_lease_set_default_subnet_mask(lease
);
1313 log_dhcp_client(client
,
1314 "received lease lacks subnet mask, "
1315 "and a fallback one cannot be generated, ignoring");
1320 sd_dhcp_lease_unref(client
->lease
);
1321 client
->lease
= TAKE_PTR(lease
);
1323 log_dhcp_client(client
, "OFFER");
1328 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1331 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1332 if (r
!= DHCP_FORCERENEW
)
1335 log_dhcp_client(client
, "FORCERENEW");
1340 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1341 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1342 _cleanup_free_
char *error_message
= NULL
;
1345 r
= dhcp_lease_new(&lease
);
1349 if (client
->client_id_len
) {
1350 r
= dhcp_lease_set_client_id(lease
,
1351 (uint8_t *) &client
->client_id
,
1352 client
->client_id_len
);
1357 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1358 if (r
== DHCP_NAK
) {
1359 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1360 return -EADDRNOTAVAIL
;
1363 if (r
!= DHCP_ACK
) {
1364 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1368 lease
->next_server
= ack
->siaddr
;
1370 lease
->address
= ack
->yiaddr
;
1372 if (lease
->address
== INADDR_ANY
||
1373 lease
->server_address
== INADDR_ANY
||
1374 lease
->lifetime
== 0) {
1375 log_dhcp_client(client
, "received lease lacks address, server "
1376 "address or lease lifetime, ignoring");
1380 if (lease
->subnet_mask
== INADDR_ANY
) {
1381 r
= dhcp_lease_set_default_subnet_mask(lease
);
1383 log_dhcp_client(client
,
1384 "received lease lacks subnet mask, "
1385 "and a fallback one cannot be generated, ignoring");
1390 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1391 if (client
->lease
) {
1392 if (client
->lease
->address
!= lease
->address
||
1393 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1394 client
->lease
->router
!= lease
->router
) {
1395 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1397 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1399 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1402 client
->lease
= TAKE_PTR(lease
);
1404 log_dhcp_client(client
, "ACK");
1409 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1411 assert(client
->request_sent
);
1412 assert(lifetime
> 0);
1419 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1420 + (random_u32() & 0x1fffff);
1423 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1425 uint64_t lifetime_timeout
;
1426 uint64_t t2_timeout
;
1427 uint64_t t1_timeout
;
1428 char time_string
[FORMAT_TIMESPAN_MAX
];
1432 assert(client
->event
);
1433 assert(client
->lease
);
1434 assert(client
->lease
->lifetime
);
1436 /* don't set timers for infinite leases */
1437 if (client
->lease
->lifetime
== 0xffffffff) {
1438 (void) event_source_disable(client
->timeout_t1
);
1439 (void) event_source_disable(client
->timeout_t2
);
1440 (void) event_source_disable(client
->timeout_expire
);
1445 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1448 assert(client
->request_sent
<= time_now
);
1450 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1451 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1452 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1453 /* both T1 and T2 are given */
1454 if (client
->lease
->t1
< client
->lease
->t2
&&
1455 client
->lease
->t2
< client
->lease
->lifetime
) {
1456 /* they are both valid */
1457 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1458 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1461 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1462 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1463 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1464 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1466 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1467 /* only T2 is given, and it is valid */
1468 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1469 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1470 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1471 if (t2_timeout
<= t1_timeout
) {
1472 /* the computed T1 would be invalid, so discard T2 */
1473 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1474 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1476 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1477 /* only T1 is given, and it is valid */
1478 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1479 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1480 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1481 if (t2_timeout
<= t1_timeout
) {
1482 /* the computed T2 would be invalid, so discard T1 */
1483 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1484 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1487 /* fall back to the default timeouts */
1488 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1489 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1490 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1491 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1494 /* arm lifetime timeout */
1495 r
= event_reset_time(client
->event
, &client
->timeout_expire
,
1496 clock_boottime_or_monotonic(),
1497 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1498 client_timeout_expire
, client
,
1499 client
->event_priority
, "dhcp4-lifetime", true);
1503 log_dhcp_client(client
, "lease expires in %s",
1504 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1506 /* don't arm earlier timeouts if this has already expired */
1507 if (lifetime_timeout
<= time_now
)
1510 /* arm T2 timeout */
1511 r
= event_reset_time(client
->event
, &client
->timeout_t2
,
1512 clock_boottime_or_monotonic(),
1513 t2_timeout
, 10 * USEC_PER_MSEC
,
1514 client_timeout_t2
, client
,
1515 client
->event_priority
, "dhcp4-t2-timeout", true);
1519 log_dhcp_client(client
, "T2 expires in %s",
1520 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1522 /* don't arm earlier timeout if this has already expired */
1523 if (t2_timeout
<= time_now
)
1526 /* arm T1 timeout */
1527 r
= event_reset_time(client
->event
, &client
->timeout_t1
,
1528 clock_boottime_or_monotonic(),
1529 t1_timeout
, 10 * USEC_PER_MSEC
,
1530 client_timeout_t1
, client
,
1531 client
->event_priority
, "dhcp4-t1-timer", true);
1535 log_dhcp_client(client
, "T1 expires in %s",
1536 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1541 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1542 DHCP_CLIENT_DONT_DESTROY(client
);
1543 char time_string
[FORMAT_TIMESPAN_MAX
];
1544 int r
= 0, notify_event
= 0;
1547 assert(client
->event
);
1550 switch (client
->state
) {
1551 case DHCP_STATE_SELECTING
:
1553 r
= client_handle_offer(client
, message
, len
);
1556 client
->state
= DHCP_STATE_REQUESTING
;
1557 client
->attempt
= 1;
1559 r
= event_reset_time(client
->event
, &client
->timeout_resend
,
1560 clock_boottime_or_monotonic(),
1562 client_timeout_resend
, client
,
1563 client
->event_priority
, "dhcp4-resend-timer", true);
1566 } else if (r
== -ENOMSG
)
1567 /* invalid message, let's ignore it */
1572 case DHCP_STATE_REBOOTING
:
1573 case DHCP_STATE_REQUESTING
:
1574 case DHCP_STATE_RENEWING
:
1575 case DHCP_STATE_REBINDING
:
1577 r
= client_handle_ack(client
, message
, len
);
1579 client
->start_delay
= 0;
1580 (void) event_source_disable(client
->timeout_resend
);
1581 client
->receive_message
=
1582 sd_event_source_unref(client
->receive_message
);
1583 client
->fd
= asynchronous_close(client
->fd
);
1585 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1586 DHCP_STATE_REBOOTING
))
1587 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1588 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1591 client
->state
= DHCP_STATE_BOUND
;
1592 client
->attempt
= 1;
1594 client
->last_addr
= client
->lease
->address
;
1596 r
= client_set_lease_timeouts(client
);
1598 log_dhcp_client(client
, "could not set lease timeouts");
1602 r
= dhcp_network_bind_udp_socket(client
->ifindex
, client
->lease
->address
, client
->port
);
1604 log_dhcp_client(client
, "could not bind UDP socket");
1610 client_initialize_io_events(client
, client_receive_message_udp
);
1613 client_notify(client
, notify_event
);
1614 if (client
->state
== DHCP_STATE_STOPPED
)
1618 } else if (r
== -EADDRNOTAVAIL
) {
1619 /* got a NAK, let's restart the client */
1620 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1622 r
= client_initialize(client
);
1626 r
= client_start_delayed(client
);
1630 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1631 client
->start_delay
, USEC_PER_SEC
));
1633 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1634 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1637 } else if (r
== -ENOMSG
)
1638 /* invalid message, let's ignore it */
1643 case DHCP_STATE_BOUND
:
1644 r
= client_handle_forcerenew(client
, message
, len
);
1646 r
= client_timeout_t1(NULL
, 0, client
);
1649 } else if (r
== -ENOMSG
)
1650 /* invalid message, let's ignore it */
1655 case DHCP_STATE_INIT
:
1656 case DHCP_STATE_INIT_REBOOT
:
1660 case DHCP_STATE_STOPPED
:
1667 client_stop(client
, r
);
1672 static int client_receive_message_udp(
1678 sd_dhcp_client
*client
= userdata
;
1679 _cleanup_free_ DHCPMessage
*message
= NULL
;
1680 const struct ether_addr zero_mac
= {};
1681 const struct ether_addr
*expected_chaddr
= NULL
;
1682 uint8_t expected_hlen
= 0;
1683 ssize_t len
, buflen
;
1688 buflen
= next_datagram_size_fd(fd
);
1692 message
= malloc0(buflen
);
1696 len
= recv(fd
, message
, buflen
, 0);
1698 if (IN_SET(errno
, EAGAIN
, EINTR
))
1701 return log_dhcp_client_errno(client
, errno
,
1702 "Could not receive message from UDP socket: %m");
1704 if ((size_t) len
< sizeof(DHCPMessage
)) {
1705 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1709 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1710 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1714 if (message
->op
!= BOOTREPLY
) {
1715 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1719 if (message
->htype
!= client
->arp_type
) {
1720 log_dhcp_client(client
, "Packet type does not match client type");
1724 if (client
->arp_type
== ARPHRD_ETHER
) {
1725 expected_hlen
= ETH_ALEN
;
1726 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1728 /* Non-Ethernet links expect zero chaddr */
1730 expected_chaddr
= &zero_mac
;
1733 if (message
->hlen
!= expected_hlen
) {
1734 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1738 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1739 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1743 if (client
->state
!= DHCP_STATE_BOUND
&&
1744 be32toh(message
->xid
) != client
->xid
) {
1745 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1746 so ignore the xid in this case */
1747 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1748 be32toh(message
->xid
), client
->xid
);
1752 return client_handle_message(client
, message
, len
);
1755 static int client_receive_message_raw(
1761 sd_dhcp_client
*client
= userdata
;
1762 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1763 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1764 struct iovec iov
= {};
1765 struct msghdr msg
= {
1768 .msg_control
= cmsgbuf
,
1769 .msg_controllen
= sizeof(cmsgbuf
),
1771 struct cmsghdr
*cmsg
;
1772 bool checksum
= true;
1773 ssize_t buflen
, len
;
1779 buflen
= next_datagram_size_fd(fd
);
1783 packet
= malloc0(buflen
);
1787 iov
.iov_base
= packet
;
1788 iov
.iov_len
= buflen
;
1790 len
= recvmsg(fd
, &msg
, 0);
1792 if (IN_SET(errno
, EAGAIN
, EINTR
))
1795 return log_dhcp_client_errno(client
, errno
,
1796 "Could not receive message from raw socket: %m");
1797 } else if ((size_t)len
< sizeof(DHCPPacket
))
1800 CMSG_FOREACH(cmsg
, &msg
) {
1801 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1802 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1803 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1804 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1806 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1811 r
= dhcp_packet_verify_headers(packet
, len
, checksum
, client
->port
);
1815 len
-= DHCP_IP_UDP_SIZE
;
1817 return client_handle_message(client
, &packet
->dhcp
, len
);
1820 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1823 assert_return(client
, -EINVAL
);
1825 r
= client_initialize(client
);
1829 /* RFC7844 section 3.3:
1830 SHOULD perform a complete four-way handshake, starting with a
1831 DHCPDISCOVER, to obtain a new address lease. If the client can
1832 ascertain that this is exactly the same network to which it was
1833 previously connected, and if the link-layer address did not change,
1834 the client MAY issue a DHCPREQUEST to try to reclaim the current
1836 if (client
->last_addr
&& !client
->anonymize
)
1837 client
->state
= DHCP_STATE_INIT_REBOOT
;
1839 r
= client_start(client
);
1841 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1846 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1847 DHCP_CLIENT_DONT_DESTROY(client
);
1849 assert_return(client
, -EINVAL
);
1851 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1852 client
->state
= DHCP_STATE_STOPPED
;
1857 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1860 assert_return(client
, -EINVAL
);
1861 assert_return(!client
->event
, -EBUSY
);
1864 client
->event
= sd_event_ref(event
);
1866 r
= sd_event_default(&client
->event
);
1871 client
->event_priority
= priority
;
1876 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1877 assert_return(client
, -EINVAL
);
1879 client
->event
= sd_event_unref(client
->event
);
1884 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1885 assert_return(client
, NULL
);
1887 return client
->event
;
1890 static sd_dhcp_client
*dhcp_client_free(sd_dhcp_client
*client
) {
1893 log_dhcp_client(client
, "FREE");
1895 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1896 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1897 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1898 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1900 client_initialize(client
);
1902 sd_dhcp_client_detach_event(client
);
1904 sd_dhcp_lease_unref(client
->lease
);
1906 free(client
->req_opts
);
1907 free(client
->hostname
);
1908 free(client
->vendor_class_identifier
);
1909 client
->user_class
= strv_free(client
->user_class
);
1910 return mfree(client
);
1913 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client
, sd_dhcp_client
, dhcp_client_free
);
1915 int sd_dhcp_client_new(sd_dhcp_client
**ret
, int anonymize
) {
1916 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1918 assert_return(ret
, -EINVAL
);
1920 client
= new(sd_dhcp_client
, 1);
1924 *client
= (sd_dhcp_client
) {
1926 .state
= DHCP_STATE_INIT
,
1930 .mtu
= DHCP_DEFAULT_MIN_SIZE
,
1931 .port
= DHCP_PORT_CLIENT
,
1932 .anonymize
= !!anonymize
,
1934 /* NOTE: this could be moved to a function. */
1936 client
->req_opts_size
= ELEMENTSOF(default_req_opts_anonymize
);
1937 client
->req_opts
= memdup(default_req_opts_anonymize
, client
->req_opts_size
);
1939 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1940 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1942 if (!client
->req_opts
)
1945 *ret
= TAKE_PTR(client
);