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 cb
;
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
,
134 assert_return(client
, -EINVAL
);
137 client
->userdata
= userdata
;
142 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
143 assert_return(client
, -EINVAL
);
145 client
->request_broadcast
= !!broadcast
;
150 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
153 assert_return(client
, -EINVAL
);
154 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
155 DHCP_STATE_STOPPED
), -EBUSY
);
158 case SD_DHCP_OPTION_PAD
:
159 case SD_DHCP_OPTION_OVERLOAD
:
160 case SD_DHCP_OPTION_MESSAGE_TYPE
:
161 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
162 case SD_DHCP_OPTION_END
:
169 for (i
= 0; i
< client
->req_opts_size
; i
++)
170 if (client
->req_opts
[i
] == option
)
173 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
174 client
->req_opts_size
+ 1))
177 client
->req_opts
[client
->req_opts_size
++] = option
;
182 int sd_dhcp_client_set_request_address(
183 sd_dhcp_client
*client
,
184 const struct in_addr
*last_addr
) {
185 assert_return(client
, -EINVAL
);
186 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
187 DHCP_STATE_STOPPED
), -EBUSY
);
190 client
->last_addr
= last_addr
->s_addr
;
192 client
->last_addr
= INADDR_ANY
;
197 int sd_dhcp_client_set_index(sd_dhcp_client
*client
, int interface_index
) {
198 assert_return(client
, -EINVAL
);
199 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
200 DHCP_STATE_STOPPED
), -EBUSY
);
201 assert_return(interface_index
> 0, -EINVAL
);
203 client
->index
= interface_index
;
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 "
235 "client, restarting");
237 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
240 memcpy(&client
->mac_addr
, addr
, addr_len
);
241 client
->mac_addr_len
= addr_len
;
242 client
->arp_type
= arp_type
;
244 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
245 sd_dhcp_client_start(client
);
250 int sd_dhcp_client_get_client_id(
251 sd_dhcp_client
*client
,
253 const uint8_t **data
,
256 assert_return(client
, -EINVAL
);
257 assert_return(type
, -EINVAL
);
258 assert_return(data
, -EINVAL
);
259 assert_return(data_len
, -EINVAL
);
264 if (client
->client_id_len
) {
265 *type
= client
->client_id
.type
;
266 *data
= client
->client_id
.raw
.data
;
267 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
273 int sd_dhcp_client_set_client_id(
274 sd_dhcp_client
*client
,
279 DHCP_CLIENT_DONT_DESTROY(client
);
280 bool need_restart
= false;
282 assert_return(client
, -EINVAL
);
283 assert_return(data
, -EINVAL
);
284 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
288 if (data_len
!= ETH_ALEN
)
291 case ARPHRD_INFINIBAND
:
292 if (data_len
!= INFINIBAND_ALEN
)
299 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
300 client
->client_id
.type
== type
&&
301 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
304 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
305 log_dhcp_client(client
, "Changing client ID on running DHCP "
306 "client, restarting");
308 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
311 client
->client_id
.type
= type
;
312 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
313 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
315 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
316 sd_dhcp_client_start(client
);
322 * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
323 * without further modification. Otherwise, if duid_type is supported, DUID
324 * is set based on that type. Otherwise, an error is returned.
326 int sd_dhcp_client_set_iaid_duid(
327 sd_dhcp_client
*client
,
333 DHCP_CLIENT_DONT_DESTROY(client
);
337 assert_return(client
, -EINVAL
);
338 assert_return(duid_len
== 0 || duid
!= NULL
, -EINVAL
);
341 r
= dhcp_validate_duid_len(duid_type
, duid_len
);
346 zero(client
->client_id
);
347 client
->client_id
.type
= 255;
349 /* If IAID is not configured, generate it. */
351 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
,
352 client
->mac_addr_len
,
353 &client
->client_id
.ns
.iaid
);
357 client
->client_id
.ns
.iaid
= htobe32(iaid
);
360 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
361 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
362 len
= sizeof(client
->client_id
.ns
.duid
.type
) + duid_len
;
363 } else if (duid_type
== DUID_TYPE_EN
) {
364 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &len
);
370 client
->client_id_len
= sizeof(client
->client_id
.type
) + len
+
371 sizeof(client
->client_id
.ns
.iaid
);
373 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
374 log_dhcp_client(client
, "Configured IAID+DUID, restarting.");
375 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
376 sd_dhcp_client_start(client
);
382 int sd_dhcp_client_set_hostname(
383 sd_dhcp_client
*client
,
384 const char *hostname
) {
386 char *new_hostname
= NULL
;
388 assert_return(client
, -EINVAL
);
390 if (!hostname_is_valid(hostname
, false) && !dns_name_is_valid(hostname
))
393 if (streq_ptr(client
->hostname
, hostname
))
397 new_hostname
= strdup(hostname
);
402 free(client
->hostname
);
403 client
->hostname
= new_hostname
;
408 int sd_dhcp_client_set_vendor_class_identifier(
409 sd_dhcp_client
*client
,
412 char *new_vci
= NULL
;
414 assert_return(client
, -EINVAL
);
416 new_vci
= strdup(vci
);
420 free(client
->vendor_class_identifier
);
422 client
->vendor_class_identifier
= new_vci
;
427 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
428 assert_return(client
, -EINVAL
);
429 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
436 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
437 assert_return(client
, -EINVAL
);
438 assert_return(ret
, -EINVAL
);
440 if (client
->state
!= DHCP_STATE_BOUND
&&
441 client
->state
!= DHCP_STATE_RENEWING
&&
442 client
->state
!= DHCP_STATE_REBINDING
)
443 return -EADDRNOTAVAIL
;
445 *ret
= client
->lease
;
450 static void client_notify(sd_dhcp_client
*client
, int event
) {
452 client
->cb(client
, event
, client
->userdata
);
455 static int client_initialize(sd_dhcp_client
*client
) {
456 assert_return(client
, -EINVAL
);
458 client
->receive_message
=
459 sd_event_source_unref(client
->receive_message
);
461 client
->fd
= asynchronous_close(client
->fd
);
463 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
465 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
466 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
467 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
471 client
->state
= DHCP_STATE_INIT
;
474 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
479 static void client_stop(sd_dhcp_client
*client
, int error
) {
483 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
484 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
485 log_dhcp_client(client
, "STOPPED");
487 log_dhcp_client(client
, "STOPPED: Unknown event");
489 client_notify(client
, error
);
491 client_initialize(client
);
494 static int client_message_init(
495 sd_dhcp_client
*client
,
499 size_t *_optoffset
) {
501 _cleanup_free_ DHCPPacket
*packet
= NULL
;
502 size_t optlen
, optoffset
, size
;
509 assert(client
->start_time
);
513 assert(type
== DHCP_DISCOVER
|| type
== DHCP_REQUEST
);
515 optlen
= DHCP_MIN_OPTIONS_SIZE
;
516 size
= sizeof(DHCPPacket
) + optlen
;
518 packet
= malloc0(size
);
522 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
523 client
->arp_type
, optlen
, &optoffset
);
527 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
528 refuse to issue an DHCP lease if 'secs' is set to zero */
529 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
532 assert(time_now
>= client
->start_time
);
534 /* seconds between sending first and last DISCOVER
535 * must always be strictly positive to deal with broken servers */
536 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
537 packet
->dhcp
.secs
= htobe16(secs
);
539 /* RFC2132 section 4.1
540 A client that cannot receive unicast IP datagrams until its protocol
541 software has been configured with an IP address SHOULD set the
542 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
543 DHCPREQUEST messages that client sends. The BROADCAST bit will
544 provide a hint to the DHCP server and BOOTP relay agent to broadcast
545 any messages to the client on the client's subnet.
547 Note: some interfaces needs this to be enabled, but some networks
548 needs this to be disabled as broadcasts are filteretd, so this
549 needs to be configurable */
550 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
551 packet
->dhcp
.flags
= htobe16(0x8000);
553 /* RFC2132 section 4.1.1:
554 The client MUST include its hardware address in the ’chaddr’ field, if
555 necessary for delivery of DHCP reply messages. Non-Ethernet
556 interfaces will leave 'chaddr' empty and use the client identifier
557 instead (eg, RFC 4390 section 2.1).
559 if (client
->arp_type
== ARPHRD_ETHER
)
560 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
562 /* If no client identifier exists, construct an RFC 4361-compliant one */
563 if (client
->client_id_len
== 0) {
566 client
->client_id
.type
= 255;
568 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
572 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
576 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
579 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
580 Identifier option is not set */
581 if (client
->client_id_len
) {
582 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
583 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
584 client
->client_id_len
,
590 /* RFC2131 section 3.5:
591 in its initial DHCPDISCOVER or DHCPREQUEST message, a
592 client may provide the server with a list of specific
593 parameters the client is interested in. If the client
594 includes a list of parameters in a DHCPDISCOVER message,
595 it MUST include that list in any subsequent DHCPREQUEST
598 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
599 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
600 client
->req_opts_size
, client
->req_opts
);
604 /* RFC2131 section 3.5:
605 The client SHOULD include the ’maximum DHCP message size’ option to
606 let the server know how large the server may make its DHCP messages.
608 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
609 than the defined default size unless the Maximum Messge Size option
612 RFC3442 "Requirements to Avoid Sizing Constraints":
613 Because a full routing table can be quite large, the standard 576
614 octet maximum size for a DHCP message may be too short to contain
615 some legitimate Classless Static Route options. Because of this,
616 clients implementing the Classless Static Route option SHOULD send a
617 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
618 stack is capable of receiving larger IP datagrams. In this case, the
619 client SHOULD set the value of this option to at least the MTU of the
620 interface that the client is configuring. The client MAY set the
621 value of this option higher, up to the size of the largest UDP packet
622 it is prepared to accept. (Note that the value specified in the
623 Maximum DHCP Message Size option is the total maximum packet size,
624 including IP and UDP headers.)
626 max_size
= htobe16(size
);
627 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
628 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
634 *_optoffset
= optoffset
;
641 static int client_append_fqdn_option(
642 DHCPMessage
*message
,
647 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
650 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
651 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
652 buffer
[1] = 0; /* RCODE1 (deprecated) */
653 buffer
[2] = 0; /* RCODE2 (deprecated) */
655 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
657 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
658 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
663 static int dhcp_client_send_raw(
664 sd_dhcp_client
*client
,
668 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, DHCP_PORT_CLIENT
,
669 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
671 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
675 static int client_send_discover(sd_dhcp_client
*client
) {
676 _cleanup_free_ DHCPPacket
*discover
= NULL
;
677 size_t optoffset
, optlen
;
681 assert(client
->state
== DHCP_STATE_INIT
||
682 client
->state
== DHCP_STATE_SELECTING
);
684 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
685 &optlen
, &optoffset
);
689 /* the client may suggest values for the network address
690 and lease time in the DHCPDISCOVER message. The client may include
691 the ’requested IP address’ option to suggest that a particular IP
692 address be assigned, and may include the ’IP address lease time’
693 option to suggest the lease time it would like.
695 if (client
->last_addr
!= INADDR_ANY
) {
696 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
697 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
698 4, &client
->last_addr
);
703 if (client
->hostname
) {
704 /* According to RFC 4702 "clients that send the Client FQDN option in
705 their messages MUST NOT also send the Host Name option". Just send
706 one of the two depending on the hostname type.
708 if (dns_name_is_single_label(client
->hostname
)) {
709 /* it is unclear from RFC 2131 if client should send hostname in
710 DHCPDISCOVER but dhclient does and so we do as well
712 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
713 SD_DHCP_OPTION_HOST_NAME
,
714 strlen(client
->hostname
), client
->hostname
);
716 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
722 if (client
->vendor_class_identifier
) {
723 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
724 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
725 strlen(client
->vendor_class_identifier
),
726 client
->vendor_class_identifier
);
731 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
732 SD_DHCP_OPTION_END
, 0, NULL
);
736 /* We currently ignore:
737 The client SHOULD wait a random time between one and ten seconds to
738 desynchronize the use of DHCP at startup.
740 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
744 log_dhcp_client(client
, "DISCOVER");
749 static int client_send_request(sd_dhcp_client
*client
) {
750 _cleanup_free_ DHCPPacket
*request
= NULL
;
751 size_t optoffset
, optlen
;
754 r
= client_message_init(client
, &request
, DHCP_REQUEST
,
755 &optlen
, &optoffset
);
759 switch (client
->state
) {
760 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
761 SELECTING should be REQUESTING)
764 case DHCP_STATE_REQUESTING
:
765 /* Client inserts the address of the selected server in ’server
766 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
767 filled in with the yiaddr value from the chosen DHCPOFFER.
770 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
771 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
772 4, &client
->lease
->server_address
);
776 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
777 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
778 4, &client
->lease
->address
);
784 case DHCP_STATE_INIT_REBOOT
:
785 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
786 option MUST be filled in with client’s notion of its previously
787 assigned address. ’ciaddr’ MUST be zero.
789 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
790 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
791 4, &client
->last_addr
);
796 case DHCP_STATE_RENEWING
:
797 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
798 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
799 client’s IP address.
803 case DHCP_STATE_REBINDING
:
804 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
805 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
806 client’s IP address.
808 This message MUST be broadcast to the 0xffffffff IP broadcast address.
810 request
->dhcp
.ciaddr
= client
->lease
->address
;
814 case DHCP_STATE_INIT
:
815 case DHCP_STATE_SELECTING
:
816 case DHCP_STATE_REBOOTING
:
817 case DHCP_STATE_BOUND
:
818 case DHCP_STATE_STOPPED
:
822 if (client
->hostname
) {
823 if (dns_name_is_single_label(client
->hostname
))
824 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
825 SD_DHCP_OPTION_HOST_NAME
,
826 strlen(client
->hostname
), client
->hostname
);
828 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
834 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
835 SD_DHCP_OPTION_END
, 0, NULL
);
839 if (client
->state
== DHCP_STATE_RENEWING
) {
840 r
= dhcp_network_send_udp_socket(client
->fd
,
841 client
->lease
->server_address
,
844 sizeof(DHCPMessage
) + optoffset
);
846 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
851 switch (client
->state
) {
852 case DHCP_STATE_REQUESTING
:
853 log_dhcp_client(client
, "REQUEST (requesting)");
855 case DHCP_STATE_INIT_REBOOT
:
856 log_dhcp_client(client
, "REQUEST (init-reboot)");
858 case DHCP_STATE_RENEWING
:
859 log_dhcp_client(client
, "REQUEST (renewing)");
861 case DHCP_STATE_REBINDING
:
862 log_dhcp_client(client
, "REQUEST (rebinding)");
865 log_dhcp_client(client
, "REQUEST (invalid)");
872 static int client_start(sd_dhcp_client
*client
);
874 static int client_timeout_resend(
879 sd_dhcp_client
*client
= userdata
;
880 DHCP_CLIENT_DONT_DESTROY(client
);
881 usec_t next_timeout
= 0;
888 assert(client
->event
);
890 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
894 switch (client
->state
) {
895 case DHCP_STATE_RENEWING
:
897 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
901 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
905 case DHCP_STATE_REBINDING
:
907 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
911 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
914 case DHCP_STATE_REBOOTING
:
915 /* start over as we did not receive a timely ack or nak */
916 r
= client_initialize(client
);
920 r
= client_start(client
);
924 log_dhcp_client(client
, "REBOOTED");
928 case DHCP_STATE_INIT
:
929 case DHCP_STATE_INIT_REBOOT
:
930 case DHCP_STATE_SELECTING
:
931 case DHCP_STATE_REQUESTING
:
932 case DHCP_STATE_BOUND
:
934 if (client
->attempt
< 64)
935 client
->attempt
*= 2;
937 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
941 case DHCP_STATE_STOPPED
:
946 next_timeout
+= (random_u32() & 0x1fffff);
948 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
950 r
= sd_event_add_time(client
->event
,
951 &client
->timeout_resend
,
952 clock_boottime_or_monotonic(),
953 next_timeout
, 10 * USEC_PER_MSEC
,
954 client_timeout_resend
, client
);
958 r
= sd_event_source_set_priority(client
->timeout_resend
,
959 client
->event_priority
);
963 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
967 switch (client
->state
) {
968 case DHCP_STATE_INIT
:
969 r
= client_send_discover(client
);
971 client
->state
= DHCP_STATE_SELECTING
;
974 if (client
->attempt
>= 64)
980 case DHCP_STATE_SELECTING
:
981 r
= client_send_discover(client
);
982 if (r
< 0 && client
->attempt
>= 64)
987 case DHCP_STATE_INIT_REBOOT
:
988 case DHCP_STATE_REQUESTING
:
989 case DHCP_STATE_RENEWING
:
990 case DHCP_STATE_REBINDING
:
991 r
= client_send_request(client
);
992 if (r
< 0 && client
->attempt
>= 64)
995 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
996 client
->state
= DHCP_STATE_REBOOTING
;
998 client
->request_sent
= time_now
;
1002 case DHCP_STATE_REBOOTING
:
1003 case DHCP_STATE_BOUND
:
1007 case DHCP_STATE_STOPPED
:
1015 client_stop(client
, r
);
1017 /* Errors were dealt with when stopping the client, don't spill
1018 errors into the event loop handler */
1022 static int client_initialize_io_events(
1023 sd_dhcp_client
*client
,
1024 sd_event_io_handler_t io_callback
) {
1029 assert(client
->event
);
1031 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
1032 client
->fd
, EPOLLIN
, io_callback
,
1037 r
= sd_event_source_set_priority(client
->receive_message
,
1038 client
->event_priority
);
1042 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
1048 client_stop(client
, r
);
1053 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1058 assert(client
->event
);
1060 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1062 if (client
->start_delay
) {
1063 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1064 usec
+= client
->start_delay
;
1067 r
= sd_event_add_time(client
->event
,
1068 &client
->timeout_resend
,
1069 clock_boottime_or_monotonic(),
1071 client_timeout_resend
, client
);
1075 r
= sd_event_source_set_priority(client
->timeout_resend
,
1076 client
->event_priority
);
1080 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1086 client_stop(client
, r
);
1092 static int client_initialize_events(sd_dhcp_client
*client
, sd_event_io_handler_t io_callback
) {
1093 client_initialize_io_events(client
, io_callback
);
1094 client_initialize_time_events(client
);
1099 static int client_start_delayed(sd_dhcp_client
*client
) {
1102 assert_return(client
, -EINVAL
);
1103 assert_return(client
->event
, -EINVAL
);
1104 assert_return(client
->index
> 0, -EINVAL
);
1105 assert_return(client
->fd
< 0, -EBUSY
);
1106 assert_return(client
->xid
== 0, -EINVAL
);
1107 assert_return(client
->state
== DHCP_STATE_INIT
||
1108 client
->state
== DHCP_STATE_INIT_REBOOT
, -EBUSY
);
1110 client
->xid
= random_u32();
1112 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1113 client
->xid
, client
->mac_addr
,
1114 client
->mac_addr_len
, client
->arp_type
);
1116 client_stop(client
, r
);
1121 if (client
->state
== DHCP_STATE_INIT
|| client
->state
== DHCP_STATE_INIT_REBOOT
)
1122 client
->start_time
= now(clock_boottime_or_monotonic());
1124 return client_initialize_events(client
, client_receive_message_raw
);
1127 static int client_start(sd_dhcp_client
*client
) {
1128 client
->start_delay
= 0;
1129 return client_start_delayed(client
);
1132 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1133 sd_dhcp_client
*client
= userdata
;
1134 DHCP_CLIENT_DONT_DESTROY(client
);
1136 log_dhcp_client(client
, "EXPIRED");
1138 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1140 /* lease was lost, start over if not freed or stopped in callback */
1141 if (client
->state
!= DHCP_STATE_STOPPED
) {
1142 client_initialize(client
);
1143 client_start(client
);
1149 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1150 sd_dhcp_client
*client
= userdata
;
1151 DHCP_CLIENT_DONT_DESTROY(client
);
1154 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1155 client
->fd
= asynchronous_close(client
->fd
);
1157 client
->state
= DHCP_STATE_REBINDING
;
1158 client
->attempt
= 1;
1160 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1161 client
->xid
, client
->mac_addr
,
1162 client
->mac_addr_len
, client
->arp_type
);
1164 client_stop(client
, r
);
1169 return client_initialize_events(client
, client_receive_message_raw
);
1172 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1173 sd_dhcp_client
*client
= userdata
;
1174 DHCP_CLIENT_DONT_DESTROY(client
);
1176 client
->state
= DHCP_STATE_RENEWING
;
1177 client
->attempt
= 1;
1179 return client_initialize_time_events(client
);
1182 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
, size_t len
) {
1183 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1186 r
= dhcp_lease_new(&lease
);
1190 if (client
->client_id_len
) {
1191 r
= dhcp_lease_set_client_id(lease
,
1192 (uint8_t *) &client
->client_id
,
1193 client
->client_id_len
);
1198 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1199 if (r
!= DHCP_OFFER
) {
1200 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1204 lease
->next_server
= offer
->siaddr
;
1205 lease
->address
= offer
->yiaddr
;
1207 if (lease
->address
== 0 ||
1208 lease
->server_address
== 0 ||
1209 lease
->lifetime
== 0) {
1210 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1214 if (!lease
->have_subnet_mask
) {
1215 r
= dhcp_lease_set_default_subnet_mask(lease
);
1217 log_dhcp_client(client
, "received lease lacks subnet "
1218 "mask, and a fallback one can not be "
1219 "generated, ignoring");
1224 sd_dhcp_lease_unref(client
->lease
);
1225 client
->lease
= lease
;
1228 log_dhcp_client(client
, "OFFER");
1233 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
, size_t len
) {
1236 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1237 if (r
!= DHCP_FORCERENEW
)
1240 log_dhcp_client(client
, "FORCERENEW");
1245 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
, size_t len
) {
1246 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1247 _cleanup_free_
char *error_message
= NULL
;
1250 r
= dhcp_lease_new(&lease
);
1254 if (client
->client_id_len
) {
1255 r
= dhcp_lease_set_client_id(lease
,
1256 (uint8_t *) &client
->client_id
,
1257 client
->client_id_len
);
1262 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1263 if (r
== DHCP_NAK
) {
1264 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1265 return -EADDRNOTAVAIL
;
1268 if (r
!= DHCP_ACK
) {
1269 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1273 lease
->next_server
= ack
->siaddr
;
1275 lease
->address
= ack
->yiaddr
;
1277 if (lease
->address
== INADDR_ANY
||
1278 lease
->server_address
== INADDR_ANY
||
1279 lease
->lifetime
== 0) {
1280 log_dhcp_client(client
, "received lease lacks address, server "
1281 "address or lease lifetime, ignoring");
1285 if (lease
->subnet_mask
== INADDR_ANY
) {
1286 r
= dhcp_lease_set_default_subnet_mask(lease
);
1288 log_dhcp_client(client
, "received lease lacks subnet "
1289 "mask, and a fallback one can not be "
1290 "generated, ignoring");
1295 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1296 if (client
->lease
) {
1297 if (client
->lease
->address
!= lease
->address
||
1298 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1299 client
->lease
->router
!= lease
->router
) {
1300 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1302 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1304 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1307 client
->lease
= lease
;
1310 log_dhcp_client(client
, "ACK");
1315 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1317 assert(client
->request_sent
);
1318 assert(lifetime
> 0);
1325 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1326 + (random_u32() & 0x1fffff);
1329 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1331 uint64_t lifetime_timeout
;
1332 uint64_t t2_timeout
;
1333 uint64_t t1_timeout
;
1334 char time_string
[FORMAT_TIMESPAN_MAX
];
1338 assert(client
->event
);
1339 assert(client
->lease
);
1340 assert(client
->lease
->lifetime
);
1342 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1343 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1344 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1346 /* don't set timers for infinite leases */
1347 if (client
->lease
->lifetime
== 0xffffffff)
1350 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1353 assert(client
->request_sent
<= time_now
);
1355 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1356 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1357 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1358 /* both T1 and T2 are given */
1359 if (client
->lease
->t1
< client
->lease
->t2
&&
1360 client
->lease
->t2
< client
->lease
->lifetime
) {
1361 /* they are both valid */
1362 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1363 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1366 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1367 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1368 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1369 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1371 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1372 /* only T2 is given, and it is valid */
1373 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1374 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1375 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1376 if (t2_timeout
<= t1_timeout
) {
1377 /* the computed T1 would be invalid, so discard T2 */
1378 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1379 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1381 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1382 /* only T1 is given, and it is valid */
1383 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1384 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1385 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1386 if (t2_timeout
<= t1_timeout
) {
1387 /* the computed T2 would be invalid, so discard T1 */
1388 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1389 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1392 /* fall back to the default timeouts */
1393 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1394 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1395 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1396 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1399 /* arm lifetime timeout */
1400 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1401 clock_boottime_or_monotonic(),
1402 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1403 client_timeout_expire
, client
);
1407 r
= sd_event_source_set_priority(client
->timeout_expire
,
1408 client
->event_priority
);
1412 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1416 log_dhcp_client(client
, "lease expires in %s",
1417 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1419 /* don't arm earlier timeouts if this has already expired */
1420 if (lifetime_timeout
<= time_now
)
1423 /* arm T2 timeout */
1424 r
= sd_event_add_time(client
->event
,
1425 &client
->timeout_t2
,
1426 clock_boottime_or_monotonic(),
1429 client_timeout_t2
, client
);
1433 r
= sd_event_source_set_priority(client
->timeout_t2
,
1434 client
->event_priority
);
1438 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1442 log_dhcp_client(client
, "T2 expires in %s",
1443 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1445 /* don't arm earlier timeout if this has already expired */
1446 if (t2_timeout
<= time_now
)
1449 /* arm T1 timeout */
1450 r
= sd_event_add_time(client
->event
,
1451 &client
->timeout_t1
,
1452 clock_boottime_or_monotonic(),
1453 t1_timeout
, 10 * USEC_PER_MSEC
,
1454 client_timeout_t1
, client
);
1458 r
= sd_event_source_set_priority(client
->timeout_t1
,
1459 client
->event_priority
);
1463 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1467 log_dhcp_client(client
, "T1 expires in %s",
1468 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1473 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
, int len
) {
1474 DHCP_CLIENT_DONT_DESTROY(client
);
1475 char time_string
[FORMAT_TIMESPAN_MAX
];
1476 int r
= 0, notify_event
= 0;
1479 assert(client
->event
);
1482 switch (client
->state
) {
1483 case DHCP_STATE_SELECTING
:
1485 r
= client_handle_offer(client
, message
, len
);
1488 client
->timeout_resend
=
1489 sd_event_source_unref(client
->timeout_resend
);
1491 client
->state
= DHCP_STATE_REQUESTING
;
1492 client
->attempt
= 1;
1494 r
= sd_event_add_time(client
->event
,
1495 &client
->timeout_resend
,
1496 clock_boottime_or_monotonic(),
1498 client_timeout_resend
, client
);
1502 r
= sd_event_source_set_priority(client
->timeout_resend
,
1503 client
->event_priority
);
1507 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1510 } else if (r
== -ENOMSG
)
1511 /* invalid message, let's ignore it */
1516 case DHCP_STATE_REBOOTING
:
1517 case DHCP_STATE_REQUESTING
:
1518 case DHCP_STATE_RENEWING
:
1519 case DHCP_STATE_REBINDING
:
1521 r
= client_handle_ack(client
, message
, len
);
1523 client
->start_delay
= 0;
1524 client
->timeout_resend
=
1525 sd_event_source_unref(client
->timeout_resend
);
1526 client
->receive_message
=
1527 sd_event_source_unref(client
->receive_message
);
1528 client
->fd
= asynchronous_close(client
->fd
);
1530 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1531 DHCP_STATE_REBOOTING
))
1532 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1533 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1536 client
->state
= DHCP_STATE_BOUND
;
1537 client
->attempt
= 1;
1539 client
->last_addr
= client
->lease
->address
;
1541 r
= client_set_lease_timeouts(client
);
1543 log_dhcp_client(client
, "could not set lease timeouts");
1547 r
= dhcp_network_bind_udp_socket(client
->lease
->address
,
1550 log_dhcp_client(client
, "could not bind UDP socket");
1556 client_initialize_io_events(client
, client_receive_message_udp
);
1559 client_notify(client
, notify_event
);
1560 if (client
->state
== DHCP_STATE_STOPPED
)
1564 } else if (r
== -EADDRNOTAVAIL
) {
1565 /* got a NAK, let's restart the client */
1566 client
->timeout_resend
=
1567 sd_event_source_unref(client
->timeout_resend
);
1569 r
= client_initialize(client
);
1573 r
= client_start_delayed(client
);
1577 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1578 client
->start_delay
, USEC_PER_SEC
));
1580 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1581 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1584 } else if (r
== -ENOMSG
)
1585 /* invalid message, let's ignore it */
1590 case DHCP_STATE_BOUND
:
1591 r
= client_handle_forcerenew(client
, message
, len
);
1593 r
= client_timeout_t1(NULL
, 0, client
);
1596 } else if (r
== -ENOMSG
)
1597 /* invalid message, let's ignore it */
1602 case DHCP_STATE_INIT
:
1603 case DHCP_STATE_INIT_REBOOT
:
1607 case DHCP_STATE_STOPPED
:
1614 client_stop(client
, r
);
1619 static int client_receive_message_udp(
1625 sd_dhcp_client
*client
= userdata
;
1626 _cleanup_free_ DHCPMessage
*message
= NULL
;
1627 const struct ether_addr zero_mac
= { { 0, 0, 0, 0, 0, 0 } };
1628 const struct ether_addr
*expected_chaddr
= NULL
;
1629 uint8_t expected_hlen
= 0;
1630 ssize_t len
, buflen
;
1635 buflen
= next_datagram_size_fd(fd
);
1639 message
= malloc0(buflen
);
1643 len
= read(fd
, message
, buflen
);
1645 if (errno
== EAGAIN
|| errno
== EINTR
)
1648 log_dhcp_client(client
, "Could not receive message from UDP socket: %m");
1650 } else if ((size_t)len
< sizeof(DHCPMessage
)) {
1651 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1655 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1656 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1660 if (message
->op
!= BOOTREPLY
) {
1661 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1665 if (message
->htype
!= client
->arp_type
) {
1666 log_dhcp_client(client
, "Packet type does not match client type");
1670 if (client
->arp_type
== ARPHRD_ETHER
) {
1671 expected_hlen
= ETH_ALEN
;
1672 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1674 /* Non-Ethernet links expect zero chaddr */
1676 expected_chaddr
= &zero_mac
;
1679 if (message
->hlen
!= expected_hlen
) {
1680 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1684 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1685 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1689 if (client
->state
!= DHCP_STATE_BOUND
&&
1690 be32toh(message
->xid
) != client
->xid
) {
1691 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1692 so ignore the xid in this case */
1693 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1694 be32toh(message
->xid
), client
->xid
);
1698 return client_handle_message(client
, message
, len
);
1701 static int client_receive_message_raw(
1707 sd_dhcp_client
*client
= userdata
;
1708 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1709 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1710 struct iovec iov
= {};
1711 struct msghdr msg
= {
1714 .msg_control
= cmsgbuf
,
1715 .msg_controllen
= sizeof(cmsgbuf
),
1717 struct cmsghdr
*cmsg
;
1718 bool checksum
= true;
1719 ssize_t buflen
, len
;
1725 buflen
= next_datagram_size_fd(fd
);
1729 packet
= malloc0(buflen
);
1733 iov
.iov_base
= packet
;
1734 iov
.iov_len
= buflen
;
1736 len
= recvmsg(fd
, &msg
, 0);
1738 if (errno
== EAGAIN
|| errno
== EINTR
)
1741 log_dhcp_client(client
, "Could not receive message from raw socket: %m");
1744 } else if ((size_t)len
< sizeof(DHCPPacket
))
1747 CMSG_FOREACH(cmsg
, &msg
) {
1748 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1749 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1750 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1751 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1753 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1758 r
= dhcp_packet_verify_headers(packet
, len
, checksum
);
1762 len
-= DHCP_IP_UDP_SIZE
;
1764 return client_handle_message(client
, &packet
->dhcp
, len
);
1767 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1770 assert_return(client
, -EINVAL
);
1772 r
= client_initialize(client
);
1776 if (client
->last_addr
)
1777 client
->state
= DHCP_STATE_INIT_REBOOT
;
1779 r
= client_start(client
);
1781 log_dhcp_client(client
, "STARTED on ifindex %i", client
->index
);
1786 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1787 DHCP_CLIENT_DONT_DESTROY(client
);
1789 assert_return(client
, -EINVAL
);
1791 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1792 client
->state
= DHCP_STATE_STOPPED
;
1797 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1800 assert_return(client
, -EINVAL
);
1801 assert_return(!client
->event
, -EBUSY
);
1804 client
->event
= sd_event_ref(event
);
1806 r
= sd_event_default(&client
->event
);
1811 client
->event_priority
= priority
;
1816 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1817 assert_return(client
, -EINVAL
);
1819 client
->event
= sd_event_unref(client
->event
);
1824 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1828 return client
->event
;
1831 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1836 assert(client
->n_ref
>= 1);
1842 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1847 assert(client
->n_ref
>= 1);
1850 if (client
->n_ref
> 0)
1853 log_dhcp_client(client
, "FREE");
1855 client_initialize(client
);
1857 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1859 sd_dhcp_client_detach_event(client
);
1861 sd_dhcp_lease_unref(client
->lease
);
1863 free(client
->req_opts
);
1864 free(client
->hostname
);
1865 free(client
->vendor_class_identifier
);
1871 int sd_dhcp_client_new(sd_dhcp_client
**ret
) {
1872 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1874 assert_return(ret
, -EINVAL
);
1876 client
= new0(sd_dhcp_client
, 1);
1881 client
->state
= DHCP_STATE_INIT
;
1884 client
->attempt
= 1;
1885 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1887 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1889 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1890 if (!client
->req_opts
)