2 This file is part of systemd.
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <net/ethernet.h>
22 #include <net/if_arp.h>
26 #include <sys/ioctl.h>
27 #include <linux/if_infiniband.h>
29 #include "sd-dhcp-client.h"
31 #include "alloc-util.h"
33 #include "dhcp-identifier.h"
34 #include "dhcp-internal.h"
35 #include "dhcp-lease-internal.h"
36 #include "dhcp-protocol.h"
37 #include "dns-domain.h"
38 #include "hostname-util.h"
39 #include "random-util.h"
40 #include "string-util.h"
43 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
44 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
46 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
47 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
49 struct sd_dhcp_client
{
55 sd_event_source
*timeout_resend
;
58 union sockaddr_union link
;
59 sd_event_source
*receive_message
;
60 bool request_broadcast
;
62 size_t req_opts_allocated
;
65 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
72 /* 0: Generic (non-LL) (RFC 2132) */
73 uint8_t data
[MAX_CLIENT_ID_LEN
];
76 /* 1: Ethernet Link-Layer (RFC 2132) */
77 uint8_t haddr
[ETH_ALEN
];
80 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
84 /* 255: Node-specific (RFC 4361) */
89 uint8_t data
[MAX_CLIENT_ID_LEN
];
95 char *vendor_class_identifier
;
101 sd_event_source
*timeout_t1
;
102 sd_event_source
*timeout_t2
;
103 sd_event_source
*timeout_expire
;
104 sd_dhcp_client_callback_t callback
;
106 sd_dhcp_lease
*lease
;
110 static const uint8_t default_req_opts
[] = {
111 SD_DHCP_OPTION_SUBNET_MASK
,
112 SD_DHCP_OPTION_ROUTER
,
113 SD_DHCP_OPTION_HOST_NAME
,
114 SD_DHCP_OPTION_DOMAIN_NAME
,
115 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
118 static int client_receive_message_raw(
123 static int client_receive_message_udp(
128 static void client_stop(sd_dhcp_client
*client
, int error
);
130 int sd_dhcp_client_set_callback(
131 sd_dhcp_client
*client
,
132 sd_dhcp_client_callback_t cb
,
135 assert_return(client
, -EINVAL
);
137 client
->callback
= cb
;
138 client
->userdata
= userdata
;
143 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
144 assert_return(client
, -EINVAL
);
146 client
->request_broadcast
= !!broadcast
;
151 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
154 assert_return(client
, -EINVAL
);
155 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
159 case SD_DHCP_OPTION_PAD
:
160 case SD_DHCP_OPTION_OVERLOAD
:
161 case SD_DHCP_OPTION_MESSAGE_TYPE
:
162 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
163 case SD_DHCP_OPTION_END
:
170 for (i
= 0; i
< client
->req_opts_size
; i
++)
171 if (client
->req_opts
[i
] == option
)
174 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
175 client
->req_opts_size
+ 1))
178 client
->req_opts
[client
->req_opts_size
++] = option
;
183 int sd_dhcp_client_set_request_address(
184 sd_dhcp_client
*client
,
185 const struct in_addr
*last_addr
) {
187 assert_return(client
, -EINVAL
);
188 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
191 client
->last_addr
= last_addr
->s_addr
;
193 client
->last_addr
= INADDR_ANY
;
198 int sd_dhcp_client_set_ifindex(sd_dhcp_client
*client
, int ifindex
) {
200 assert_return(client
, -EINVAL
);
201 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
), -EBUSY
);
202 assert_return(ifindex
> 0, -EINVAL
);
204 client
->ifindex
= ifindex
;
208 int sd_dhcp_client_set_mac(
209 sd_dhcp_client
*client
,
214 DHCP_CLIENT_DONT_DESTROY(client
);
215 bool need_restart
= false;
217 assert_return(client
, -EINVAL
);
218 assert_return(addr
, -EINVAL
);
219 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
220 assert_return(arp_type
> 0, -EINVAL
);
222 if (arp_type
== ARPHRD_ETHER
)
223 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
224 else if (arp_type
== ARPHRD_INFINIBAND
)
225 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
229 if (client
->mac_addr_len
== addr_len
&&
230 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
233 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
234 log_dhcp_client(client
, "Changing MAC address on running DHCP client, restarting");
236 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
239 memcpy(&client
->mac_addr
, addr
, addr_len
);
240 client
->mac_addr_len
= addr_len
;
241 client
->arp_type
= arp_type
;
243 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
244 sd_dhcp_client_start(client
);
249 int sd_dhcp_client_get_client_id(
250 sd_dhcp_client
*client
,
252 const uint8_t **data
,
255 assert_return(client
, -EINVAL
);
256 assert_return(type
, -EINVAL
);
257 assert_return(data
, -EINVAL
);
258 assert_return(data_len
, -EINVAL
);
263 if (client
->client_id_len
) {
264 *type
= client
->client_id
.type
;
265 *data
= client
->client_id
.raw
.data
;
266 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
272 int sd_dhcp_client_set_client_id(
273 sd_dhcp_client
*client
,
278 DHCP_CLIENT_DONT_DESTROY(client
);
279 bool need_restart
= false;
281 assert_return(client
, -EINVAL
);
282 assert_return(data
, -EINVAL
);
283 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
288 if (data_len
!= ETH_ALEN
)
292 case ARPHRD_INFINIBAND
:
293 if (data_len
!= INFINIBAND_ALEN
)
301 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
302 client
->client_id
.type
== type
&&
303 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
306 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
307 log_dhcp_client(client
, "Changing client ID on running DHCP "
308 "client, restarting");
310 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
313 client
->client_id
.type
= type
;
314 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
315 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
317 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
318 sd_dhcp_client_start(client
);
324 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
325 * without further modification. Otherwise, if duid_type is supported, DUID
326 * is set based on that type. Otherwise, an error is returned.
328 int sd_dhcp_client_set_iaid_duid(
329 sd_dhcp_client
*client
,
335 DHCP_CLIENT_DONT_DESTROY(client
);
339 assert_return(client
, -EINVAL
);
340 assert_return(duid_len
== 0 || duid
!= NULL
, -EINVAL
);
343 r
= dhcp_validate_duid_len(duid_type
, duid_len
);
348 zero(client
->client_id
);
349 client
->client_id
.type
= 255;
351 /* If IAID is not configured, generate it. */
353 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
,
354 client
->mac_addr_len
,
355 &client
->client_id
.ns
.iaid
);
359 client
->client_id
.ns
.iaid
= htobe32(iaid
);
362 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
363 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
364 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
365 } else if (duid_type
== DUID_TYPE_EN
) {
366 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
372 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
373 sizeof(client
->client_id
.ns
.iaid
);
375 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
376 log_dhcp_client(client
, "Configured IAID+DUID, restarting.");
377 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
378 sd_dhcp_client_start(client
);
384 int sd_dhcp_client_set_hostname(
385 sd_dhcp_client
*client
,
386 const char *hostname
) {
388 char *new_hostname
= NULL
;
390 assert_return(client
, -EINVAL
);
392 if (!hostname_is_valid(hostname
, false) && !dns_name_is_valid(hostname
))
395 if (streq_ptr(client
->hostname
, hostname
))
399 new_hostname
= strdup(hostname
);
404 free(client
->hostname
);
405 client
->hostname
= new_hostname
;
410 int sd_dhcp_client_set_vendor_class_identifier(
411 sd_dhcp_client
*client
,
414 char *new_vci
= NULL
;
416 assert_return(client
, -EINVAL
);
418 new_vci
= strdup(vci
);
422 free(client
->vendor_class_identifier
);
424 client
->vendor_class_identifier
= new_vci
;
429 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
430 assert_return(client
, -EINVAL
);
431 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
438 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
439 assert_return(client
, -EINVAL
);
441 if (client
->state
!= DHCP_STATE_BOUND
&&
442 client
->state
!= DHCP_STATE_RENEWING
&&
443 client
->state
!= DHCP_STATE_REBINDING
)
444 return -EADDRNOTAVAIL
;
447 *ret
= client
->lease
;
452 static void client_notify(sd_dhcp_client
*client
, int event
) {
455 if (client
->callback
)
456 client
->callback(client
, event
, client
->userdata
);
459 static int client_initialize(sd_dhcp_client
*client
) {
460 assert_return(client
, -EINVAL
);
462 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
464 client
->fd
= asynchronous_close(client
->fd
);
466 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
468 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
469 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
470 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
474 client
->state
= DHCP_STATE_INIT
;
477 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
482 static void client_stop(sd_dhcp_client
*client
, int error
) {
486 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
487 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
488 log_dhcp_client(client
, "STOPPED");
490 log_dhcp_client(client
, "STOPPED: Unknown event");
492 client_notify(client
, error
);
494 client_initialize(client
);
497 static int client_message_init(
498 sd_dhcp_client
*client
,
502 size_t *_optoffset
) {
504 _cleanup_free_ DHCPPacket
*packet
= NULL
;
505 size_t optlen
, optoffset
, size
;
512 assert(client
->start_time
);
516 assert(type
== DHCP_DISCOVER
|| type
== DHCP_REQUEST
);
518 optlen
= DHCP_MIN_OPTIONS_SIZE
;
519 size
= sizeof(DHCPPacket
) + optlen
;
521 packet
= malloc0(size
);
525 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
526 client
->arp_type
, optlen
, &optoffset
);
530 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
531 refuse to issue an DHCP lease if 'secs' is set to zero */
532 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
535 assert(time_now
>= client
->start_time
);
537 /* seconds between sending first and last DISCOVER
538 * must always be strictly positive to deal with broken servers */
539 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
540 packet
->dhcp
.secs
= htobe16(secs
);
542 /* RFC2132 section 4.1
543 A client that cannot receive unicast IP datagrams until its protocol
544 software has been configured with an IP address SHOULD set the
545 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
546 DHCPREQUEST messages that client sends. The BROADCAST bit will
547 provide a hint to the DHCP server and BOOTP relay agent to broadcast
548 any messages to the client on the client's subnet.
550 Note: some interfaces needs this to be enabled, but some networks
551 needs this to be disabled as broadcasts are filteretd, so this
552 needs to be configurable */
553 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
554 packet
->dhcp
.flags
= htobe16(0x8000);
556 /* RFC2132 section 4.1.1:
557 The client MUST include its hardware address in the ’chaddr’ field, if
558 necessary for delivery of DHCP reply messages. Non-Ethernet
559 interfaces will leave 'chaddr' empty and use the client identifier
560 instead (eg, RFC 4390 section 2.1).
562 if (client
->arp_type
== ARPHRD_ETHER
)
563 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
565 /* If no client identifier exists, construct an RFC 4361-compliant one */
566 if (client
->client_id_len
== 0) {
569 client
->client_id
.type
= 255;
571 r
= dhcp_identifier_set_iaid(client
->ifindex
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
575 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
579 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
582 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
583 Identifier option is not set */
584 if (client
->client_id_len
) {
585 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
586 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
587 client
->client_id_len
,
593 /* RFC2131 section 3.5:
594 in its initial DHCPDISCOVER or DHCPREQUEST message, a
595 client may provide the server with a list of specific
596 parameters the client is interested in. If the client
597 includes a list of parameters in a DHCPDISCOVER message,
598 it MUST include that list in any subsequent DHCPREQUEST
601 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
602 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
603 client
->req_opts_size
, client
->req_opts
);
607 /* RFC2131 section 3.5:
608 The client SHOULD include the ’maximum DHCP message size’ option to
609 let the server know how large the server may make its DHCP messages.
611 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
612 than the defined default size unless the Maximum Messge Size option
615 RFC3442 "Requirements to Avoid Sizing Constraints":
616 Because a full routing table can be quite large, the standard 576
617 octet maximum size for a DHCP message may be too short to contain
618 some legitimate Classless Static Route options. Because of this,
619 clients implementing the Classless Static Route option SHOULD send a
620 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
621 stack is capable of receiving larger IP datagrams. In this case, the
622 client SHOULD set the value of this option to at least the MTU of the
623 interface that the client is configuring. The client MAY set the
624 value of this option higher, up to the size of the largest UDP packet
625 it is prepared to accept. (Note that the value specified in the
626 Maximum DHCP Message Size option is the total maximum packet size,
627 including IP and UDP headers.)
629 max_size
= htobe16(size
);
630 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
631 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
637 *_optoffset
= optoffset
;
644 static int client_append_fqdn_option(
645 DHCPMessage
*message
,
650 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
653 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
654 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
655 buffer
[1] = 0; /* RCODE1 (deprecated) */
656 buffer
[2] = 0; /* RCODE2 (deprecated) */
658 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
660 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
661 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
666 static int dhcp_client_send_raw(
667 sd_dhcp_client
*client
,
671 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, DHCP_PORT_CLIENT
,
672 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
674 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
678 static int client_send_discover(sd_dhcp_client
*client
) {
679 _cleanup_free_ DHCPPacket
*discover
= NULL
;
680 size_t optoffset
, optlen
;
684 assert(client
->state
== DHCP_STATE_INIT
||
685 client
->state
== DHCP_STATE_SELECTING
);
687 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
688 &optlen
, &optoffset
);
692 /* the client may suggest values for the network address
693 and lease time in the DHCPDISCOVER message. The client may include
694 the ’requested IP address’ option to suggest that a particular IP
695 address be assigned, and may include the ’IP address lease time’
696 option to suggest the lease time it would like.
698 if (client
->last_addr
!= INADDR_ANY
) {
699 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
700 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
701 4, &client
->last_addr
);
706 if (client
->hostname
) {
707 /* According to RFC 4702 "clients that send the Client FQDN option in
708 their messages MUST NOT also send the Host Name option". Just send
709 one of the two depending on the hostname type.
711 if (dns_name_is_single_label(client
->hostname
)) {
712 /* it is unclear from RFC 2131 if client should send hostname in
713 DHCPDISCOVER but dhclient does and so we do as well
715 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
716 SD_DHCP_OPTION_HOST_NAME
,
717 strlen(client
->hostname
), client
->hostname
);
719 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
725 if (client
->vendor_class_identifier
) {
726 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
727 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
728 strlen(client
->vendor_class_identifier
),
729 client
->vendor_class_identifier
);
734 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
735 SD_DHCP_OPTION_END
, 0, NULL
);
739 /* We currently ignore:
740 The client SHOULD wait a random time between one and ten seconds to
741 desynchronize the use of DHCP at startup.
743 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
747 log_dhcp_client(client
, "DISCOVER");
752 static int client_send_request(sd_dhcp_client
*client
) {
753 _cleanup_free_ DHCPPacket
*request
= NULL
;
754 size_t optoffset
, optlen
;
759 r
= client_message_init(client
, &request
, DHCP_REQUEST
, &optlen
, &optoffset
);
763 switch (client
->state
) {
764 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
765 SELECTING should be REQUESTING)
768 case DHCP_STATE_REQUESTING
:
769 /* Client inserts the address of the selected server in ’server
770 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
771 filled in with the yiaddr value from the chosen DHCPOFFER.
774 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
775 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
776 4, &client
->lease
->server_address
);
780 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
781 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
782 4, &client
->lease
->address
);
788 case DHCP_STATE_INIT_REBOOT
:
789 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
790 option MUST be filled in with client’s notion of its previously
791 assigned address. ’ciaddr’ MUST be zero.
793 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
794 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
795 4, &client
->last_addr
);
800 case DHCP_STATE_RENEWING
:
801 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
802 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
803 client’s IP address.
807 case DHCP_STATE_REBINDING
:
808 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
809 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
810 client’s IP address.
812 This message MUST be broadcast to the 0xffffffff IP broadcast address.
814 request
->dhcp
.ciaddr
= client
->lease
->address
;
818 case DHCP_STATE_INIT
:
819 case DHCP_STATE_SELECTING
:
820 case DHCP_STATE_REBOOTING
:
821 case DHCP_STATE_BOUND
:
822 case DHCP_STATE_STOPPED
:
826 if (client
->hostname
) {
827 if (dns_name_is_single_label(client
->hostname
))
828 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
829 SD_DHCP_OPTION_HOST_NAME
,
830 strlen(client
->hostname
), client
->hostname
);
832 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
838 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
839 SD_DHCP_OPTION_END
, 0, NULL
);
843 if (client
->state
== DHCP_STATE_RENEWING
) {
844 r
= dhcp_network_send_udp_socket(client
->fd
,
845 client
->lease
->server_address
,
848 sizeof(DHCPMessage
) + optoffset
);
850 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
855 switch (client
->state
) {
857 case DHCP_STATE_REQUESTING
:
858 log_dhcp_client(client
, "REQUEST (requesting)");
861 case DHCP_STATE_INIT_REBOOT
:
862 log_dhcp_client(client
, "REQUEST (init-reboot)");
865 case DHCP_STATE_RENEWING
:
866 log_dhcp_client(client
, "REQUEST (renewing)");
869 case DHCP_STATE_REBINDING
:
870 log_dhcp_client(client
, "REQUEST (rebinding)");
874 log_dhcp_client(client
, "REQUEST (invalid)");
881 static int client_start(sd_dhcp_client
*client
);
883 static int client_timeout_resend(
888 sd_dhcp_client
*client
= userdata
;
889 DHCP_CLIENT_DONT_DESTROY(client
);
890 usec_t next_timeout
= 0;
897 assert(client
->event
);
899 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
903 switch (client
->state
) {
905 case DHCP_STATE_RENEWING
:
907 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
911 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
915 case DHCP_STATE_REBINDING
:
917 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
921 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
924 case DHCP_STATE_REBOOTING
:
925 /* start over as we did not receive a timely ack or nak */
926 r
= client_initialize(client
);
930 r
= client_start(client
);
934 log_dhcp_client(client
, "REBOOTED");
938 case DHCP_STATE_INIT
:
939 case DHCP_STATE_INIT_REBOOT
:
940 case DHCP_STATE_SELECTING
:
941 case DHCP_STATE_REQUESTING
:
942 case DHCP_STATE_BOUND
:
944 if (client
->attempt
< 64)
945 client
->attempt
*= 2;
947 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
951 case DHCP_STATE_STOPPED
:
956 next_timeout
+= (random_u32() & 0x1fffff);
958 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
960 r
= sd_event_add_time(client
->event
,
961 &client
->timeout_resend
,
962 clock_boottime_or_monotonic(),
963 next_timeout
, 10 * USEC_PER_MSEC
,
964 client_timeout_resend
, client
);
968 r
= sd_event_source_set_priority(client
->timeout_resend
,
969 client
->event_priority
);
973 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
977 switch (client
->state
) {
978 case DHCP_STATE_INIT
:
979 r
= client_send_discover(client
);
981 client
->state
= DHCP_STATE_SELECTING
;
984 if (client
->attempt
>= 64)
990 case DHCP_STATE_SELECTING
:
991 r
= client_send_discover(client
);
992 if (r
< 0 && client
->attempt
>= 64)
997 case DHCP_STATE_INIT_REBOOT
:
998 case DHCP_STATE_REQUESTING
:
999 case DHCP_STATE_RENEWING
:
1000 case DHCP_STATE_REBINDING
:
1001 r
= client_send_request(client
);
1002 if (r
< 0 && client
->attempt
>= 64)
1005 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
1006 client
->state
= DHCP_STATE_REBOOTING
;
1008 client
->request_sent
= time_now
;
1012 case DHCP_STATE_REBOOTING
:
1013 case DHCP_STATE_BOUND
:
1017 case DHCP_STATE_STOPPED
:
1025 client_stop(client
, r
);
1027 /* Errors were dealt with when stopping the client, don't spill
1028 errors into the event loop handler */
1032 static int client_initialize_io_events(
1033 sd_dhcp_client
*client
,
1034 sd_event_io_handler_t io_callback
) {
1039 assert(client
->event
);
1041 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1042 client
->fd
, EPOLLIN
, io_callback
,
1047 r
= sd_event_source_set_priority(client
->receive_message
,
1048 client
->event_priority
);
1052 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1058 client_stop(client
, r
);
1063 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1068 assert(client
->event
);
1070 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1072 if (client
->start_delay
) {
1073 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1074 usec
+= client
->start_delay
;
1077 r
= sd_event_add_time(client
->event
,
1078 &client
->timeout_resend
,
1079 clock_boottime_or_monotonic(),
1081 client_timeout_resend
, client
);
1085 r
= sd_event_source_set_priority(client
->timeout_resend
,
1086 client
->event_priority
);
1090 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1096 client_stop(client
, r
);
1102 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1103 client_initialize_io_events(client
, io_callback
);
1104 client_initialize_time_events(client
);
1109 static int client_start_delayed(sd_dhcp_client
*client
) {
1112 assert_return(client
, -EINVAL
);
1113 assert_return(client
->event
, -EINVAL
);
1114 assert_return(client
->ifindex
> 0, -EINVAL
);
1115 assert_return(client
->fd
< 0, -EBUSY
);
1116 assert_return(client
->xid
== 0, -EINVAL
);
1117 assert_return(IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_INIT_REBOOT
), -EBUSY
);
1119 client
->xid
= random_u32();
1121 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1122 client
->xid
, client
->mac_addr
,
1123 client
->mac_addr_len
, client
->arp_type
);
1125 client_stop(client
, r
);
1130 if (client
->state
== DHCP_STATE_INIT
|| client
->state
== DHCP_STATE_INIT_REBOOT
)
1131 client
->start_time
= now(clock_boottime_or_monotonic());
1133 return client_initialize_events(client
, client_receive_message_raw
);
1136 static int client_start(sd_dhcp_client
*client
) {
1137 client
->start_delay
= 0;
1138 return client_start_delayed(client
);
1141 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1142 sd_dhcp_client
*client
= userdata
;
1143 DHCP_CLIENT_DONT_DESTROY(client
);
1145 log_dhcp_client(client
, "EXPIRED");
1147 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1149 /* lease was lost, start over if not freed or stopped in callback */
1150 if (client
->state
!= DHCP_STATE_STOPPED
) {
1151 client_initialize(client
);
1152 client_start(client
);
1158 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1159 sd_dhcp_client
*client
= userdata
;
1160 DHCP_CLIENT_DONT_DESTROY(client
);
1165 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1166 client
->fd
= asynchronous_close(client
->fd
);
1168 client
->state
= DHCP_STATE_REBINDING
;
1169 client
->attempt
= 1;
1171 r
= dhcp_network_bind_raw_socket(client
->ifindex
, &client
->link
,
1172 client
->xid
, client
->mac_addr
,
1173 client
->mac_addr_len
, client
->arp_type
);
1175 client_stop(client
, r
);
1180 return client_initialize_events(client
, client_receive_message_raw
);
1183 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1184 sd_dhcp_client
*client
= userdata
;
1185 DHCP_CLIENT_DONT_DESTROY(client
);
1187 client
->state
= DHCP_STATE_RENEWING
;
1188 client
->attempt
= 1;
1190 return client_initialize_time_events(client
);
1193 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1194 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1197 r
= dhcp_lease_new(&lease
);
1201 if (client
->client_id_len
) {
1202 r
= dhcp_lease_set_client_id(lease
,
1203 (uint8_t *) &client
->client_id
,
1204 client
->client_id_len
);
1209 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1210 if (r
!= DHCP_OFFER
) {
1211 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1215 lease
->next_server
= offer
->siaddr
;
1216 lease
->address
= offer
->yiaddr
;
1218 if (lease
->address
== 0 ||
1219 lease
->server_address
== 0 ||
1220 lease
->lifetime
== 0) {
1221 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1225 if (!lease
->have_subnet_mask
) {
1226 r
= dhcp_lease_set_default_subnet_mask(lease
);
1228 log_dhcp_client(client
, "received lease lacks subnet "
1229 "mask, and a fallback one can not be "
1230 "generated, ignoring");
1235 sd_dhcp_lease_unref(client
->lease
);
1236 client
->lease
= lease
;
1239 log_dhcp_client(client
, "OFFER");
1244 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1247 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1248 if (r
!= DHCP_FORCERENEW
)
1251 log_dhcp_client(client
, "FORCERENEW");
1256 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1257 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1258 _cleanup_free_
char *error_message
= NULL
;
1261 r
= dhcp_lease_new(&lease
);
1265 if (client
->client_id_len
) {
1266 r
= dhcp_lease_set_client_id(lease
,
1267 (uint8_t *) &client
->client_id
,
1268 client
->client_id_len
);
1273 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1274 if (r
== DHCP_NAK
) {
1275 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1276 return -EADDRNOTAVAIL
;
1279 if (r
!= DHCP_ACK
) {
1280 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1284 lease
->next_server
= ack
->siaddr
;
1286 lease
->address
= ack
->yiaddr
;
1288 if (lease
->address
== INADDR_ANY
||
1289 lease
->server_address
== INADDR_ANY
||
1290 lease
->lifetime
== 0) {
1291 log_dhcp_client(client
, "received lease lacks address, server "
1292 "address or lease lifetime, ignoring");
1296 if (lease
->subnet_mask
== INADDR_ANY
) {
1297 r
= dhcp_lease_set_default_subnet_mask(lease
);
1299 log_dhcp_client(client
, "received lease lacks subnet "
1300 "mask, and a fallback one can not be "
1301 "generated, ignoring");
1306 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1307 if (client
->lease
) {
1308 if (client
->lease
->address
!= lease
->address
||
1309 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1310 client
->lease
->router
!= lease
->router
) {
1311 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1313 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1315 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1318 client
->lease
= lease
;
1321 log_dhcp_client(client
, "ACK");
1326 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1328 assert(client
->request_sent
);
1329 assert(lifetime
> 0);
1336 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1337 + (random_u32() & 0x1fffff);
1340 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1342 uint64_t lifetime_timeout
;
1343 uint64_t t2_timeout
;
1344 uint64_t t1_timeout
;
1345 char time_string
[FORMAT_TIMESPAN_MAX
];
1349 assert(client
->event
);
1350 assert(client
->lease
);
1351 assert(client
->lease
->lifetime
);
1353 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1354 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1355 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1357 /* don't set timers for infinite leases */
1358 if (client
->lease
->lifetime
== 0xffffffff)
1361 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1364 assert(client
->request_sent
<= time_now
);
1366 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1367 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1368 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1369 /* both T1 and T2 are given */
1370 if (client
->lease
->t1
< client
->lease
->t2
&&
1371 client
->lease
->t2
< client
->lease
->lifetime
) {
1372 /* they are both valid */
1373 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1374 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1377 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1378 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1379 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1380 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1382 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1383 /* only T2 is given, and it is valid */
1384 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1385 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1386 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1387 if (t2_timeout
<= t1_timeout
) {
1388 /* the computed T1 would be invalid, so discard T2 */
1389 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1390 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1392 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1393 /* only T1 is given, and it is valid */
1394 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1395 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1396 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1397 if (t2_timeout
<= t1_timeout
) {
1398 /* the computed T2 would be invalid, so discard T1 */
1399 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1400 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1403 /* fall back to the default timeouts */
1404 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1405 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1406 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1407 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1410 /* arm lifetime timeout */
1411 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1412 clock_boottime_or_monotonic(),
1413 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1414 client_timeout_expire
, client
);
1418 r
= sd_event_source_set_priority(client
->timeout_expire
,
1419 client
->event_priority
);
1423 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1427 log_dhcp_client(client
, "lease expires in %s",
1428 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1430 /* don't arm earlier timeouts if this has already expired */
1431 if (lifetime_timeout
<= time_now
)
1434 /* arm T2 timeout */
1435 r
= sd_event_add_time(client
->event
,
1436 &client
->timeout_t2
,
1437 clock_boottime_or_monotonic(),
1440 client_timeout_t2
, client
);
1444 r
= sd_event_source_set_priority(client
->timeout_t2
,
1445 client
->event_priority
);
1449 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1453 log_dhcp_client(client
, "T2 expires in %s",
1454 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1456 /* don't arm earlier timeout if this has already expired */
1457 if (t2_timeout
<= time_now
)
1460 /* arm T1 timeout */
1461 r
= sd_event_add_time(client
->event
,
1462 &client
->timeout_t1
,
1463 clock_boottime_or_monotonic(),
1464 t1_timeout
, 10 * USEC_PER_MSEC
,
1465 client_timeout_t1
, client
);
1469 r
= sd_event_source_set_priority(client
->timeout_t1
,
1470 client
->event_priority
);
1474 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1478 log_dhcp_client(client
, "T1 expires in %s",
1479 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1484 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1485 DHCP_CLIENT_DONT_DESTROY(client
);
1486 char time_string
[FORMAT_TIMESPAN_MAX
];
1487 int r
= 0, notify_event
= 0;
1490 assert(client
->event
);
1493 switch (client
->state
) {
1494 case DHCP_STATE_SELECTING
:
1496 r
= client_handle_offer(client
, message
, len
);
1499 client
->timeout_resend
=
1500 sd_event_source_unref(client
->timeout_resend
);
1502 client
->state
= DHCP_STATE_REQUESTING
;
1503 client
->attempt
= 1;
1505 r
= sd_event_add_time(client
->event
,
1506 &client
->timeout_resend
,
1507 clock_boottime_or_monotonic(),
1509 client_timeout_resend
, client
);
1513 r
= sd_event_source_set_priority(client
->timeout_resend
,
1514 client
->event_priority
);
1518 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1521 } else if (r
== -ENOMSG
)
1522 /* invalid message, let's ignore it */
1527 case DHCP_STATE_REBOOTING
:
1528 case DHCP_STATE_REQUESTING
:
1529 case DHCP_STATE_RENEWING
:
1530 case DHCP_STATE_REBINDING
:
1532 r
= client_handle_ack(client
, message
, len
);
1534 client
->start_delay
= 0;
1535 client
->timeout_resend
=
1536 sd_event_source_unref(client
->timeout_resend
);
1537 client
->receive_message
=
1538 sd_event_source_unref(client
->receive_message
);
1539 client
->fd
= asynchronous_close(client
->fd
);
1541 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1542 DHCP_STATE_REBOOTING
))
1543 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1544 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1547 client
->state
= DHCP_STATE_BOUND
;
1548 client
->attempt
= 1;
1550 client
->last_addr
= client
->lease
->address
;
1552 r
= client_set_lease_timeouts(client
);
1554 log_dhcp_client(client
, "could not set lease timeouts");
1558 r
= dhcp_network_bind_udp_socket(client
->lease
->address
,
1561 log_dhcp_client(client
, "could not bind UDP socket");
1567 client_initialize_io_events(client
, client_receive_message_udp
);
1570 client_notify(client
, notify_event
);
1571 if (client
->state
== DHCP_STATE_STOPPED
)
1575 } else if (r
== -EADDRNOTAVAIL
) {
1576 /* got a NAK, let's restart the client */
1577 client
->timeout_resend
=
1578 sd_event_source_unref(client
->timeout_resend
);
1580 r
= client_initialize(client
);
1584 r
= client_start_delayed(client
);
1588 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1589 client
->start_delay
, USEC_PER_SEC
));
1591 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1592 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1595 } else if (r
== -ENOMSG
)
1596 /* invalid message, let's ignore it */
1601 case DHCP_STATE_BOUND
:
1602 r
= client_handle_forcerenew(client
, message
, len
);
1604 r
= client_timeout_t1(NULL
, 0, client
);
1607 } else if (r
== -ENOMSG
)
1608 /* invalid message, let's ignore it */
1613 case DHCP_STATE_INIT
:
1614 case DHCP_STATE_INIT_REBOOT
:
1618 case DHCP_STATE_STOPPED
:
1625 client_stop(client
, r
);
1630 static int client_receive_message_udp(
1636 sd_dhcp_client
*client
= userdata
;
1637 _cleanup_free_ DHCPMessage
*message
= NULL
;
1638 const struct ether_addr zero_mac
= {};
1639 const struct ether_addr
*expected_chaddr
= NULL
;
1640 uint8_t expected_hlen
= 0;
1641 ssize_t len
, buflen
;
1646 buflen
= next_datagram_size_fd(fd
);
1650 message
= malloc0(buflen
);
1654 len
= recv(fd
, message
, buflen
, 0);
1656 if (errno
== EAGAIN
|| errno
== EINTR
)
1659 return log_dhcp_client_errno(client
, errno
, "Could not receive message from UDP socket: %m");
1661 if ((size_t) len
< sizeof(DHCPMessage
)) {
1662 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1666 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1667 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1671 if (message
->op
!= BOOTREPLY
) {
1672 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1676 if (message
->htype
!= client
->arp_type
) {
1677 log_dhcp_client(client
, "Packet type does not match client type");
1681 if (client
->arp_type
== ARPHRD_ETHER
) {
1682 expected_hlen
= ETH_ALEN
;
1683 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1685 /* Non-Ethernet links expect zero chaddr */
1687 expected_chaddr
= &zero_mac
;
1690 if (message
->hlen
!= expected_hlen
) {
1691 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1695 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1696 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1700 if (client
->state
!= DHCP_STATE_BOUND
&&
1701 be32toh(message
->xid
) != client
->xid
) {
1702 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1703 so ignore the xid in this case */
1704 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1705 be32toh(message
->xid
), client
->xid
);
1709 return client_handle_message(client
, message
, len
);
1712 static int client_receive_message_raw(
1718 sd_dhcp_client
*client
= userdata
;
1719 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1720 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1721 struct iovec iov
= {};
1722 struct msghdr msg
= {
1725 .msg_control
= cmsgbuf
,
1726 .msg_controllen
= sizeof(cmsgbuf
),
1728 struct cmsghdr
*cmsg
;
1729 bool checksum
= true;
1730 ssize_t buflen
, len
;
1736 buflen
= next_datagram_size_fd(fd
);
1740 packet
= malloc0(buflen
);
1744 iov
.iov_base
= packet
;
1745 iov
.iov_len
= buflen
;
1747 len
= recvmsg(fd
, &msg
, 0);
1749 if (errno
== EAGAIN
|| errno
== EINTR
)
1752 log_dhcp_client(client
, "Could not receive message from raw socket: %m");
1755 } else if ((size_t)len
< sizeof(DHCPPacket
))
1758 CMSG_FOREACH(cmsg
, &msg
) {
1759 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1760 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1761 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1762 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1764 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1769 r
= dhcp_packet_verify_headers(packet
, len
, checksum
);
1773 len
-= DHCP_IP_UDP_SIZE
;
1775 return client_handle_message(client
, &packet
->dhcp
, len
);
1778 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1781 assert_return(client
, -EINVAL
);
1783 r
= client_initialize(client
);
1787 if (client
->last_addr
)
1788 client
->state
= DHCP_STATE_INIT_REBOOT
;
1790 r
= client_start(client
);
1792 log_dhcp_client(client
, "STARTED on ifindex %i", client
->ifindex
);
1797 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1798 DHCP_CLIENT_DONT_DESTROY(client
);
1800 assert_return(client
, -EINVAL
);
1802 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1803 client
->state
= DHCP_STATE_STOPPED
;
1808 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1811 assert_return(client
, -EINVAL
);
1812 assert_return(!client
->event
, -EBUSY
);
1815 client
->event
= sd_event_ref(event
);
1817 r
= sd_event_default(&client
->event
);
1822 client
->event_priority
= priority
;
1827 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1828 assert_return(client
, -EINVAL
);
1830 client
->event
= sd_event_unref(client
->event
);
1835 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1836 assert_return(client
, NULL
);
1838 return client
->event
;
1841 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1846 assert(client
->n_ref
>= 1);
1852 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1857 assert(client
->n_ref
>= 1);
1860 if (client
->n_ref
> 0)
1863 log_dhcp_client(client
, "FREE");
1865 client_initialize(client
);
1867 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1869 sd_dhcp_client_detach_event(client
);
1871 sd_dhcp_lease_unref(client
->lease
);
1873 free(client
->req_opts
);
1874 free(client
->hostname
);
1875 free(client
->vendor_class_identifier
);
1881 int sd_dhcp_client_new(sd_dhcp_client
**ret
) {
1882 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1884 assert_return(ret
, -EINVAL
);
1886 client
= new0(sd_dhcp_client
, 1);
1891 client
->state
= DHCP_STATE_INIT
;
1892 client
->ifindex
= -1;
1894 client
->attempt
= 1;
1895 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1897 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1898 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1899 if (!client
->req_opts
)