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(sd_event_source
*s
, int fd
,
119 uint32_t revents
, void *userdata
);
120 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
121 uint32_t revents
, void *userdata
);
122 static void client_stop(sd_dhcp_client
*client
, int error
);
124 int sd_dhcp_client_set_callback(sd_dhcp_client
*client
, sd_dhcp_client_callback_t cb
,
126 assert_return(client
, -EINVAL
);
129 client
->userdata
= userdata
;
134 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
135 assert_return(client
, -EINVAL
);
137 client
->request_broadcast
= !!broadcast
;
142 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
145 assert_return(client
, -EINVAL
);
146 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
147 DHCP_STATE_STOPPED
), -EBUSY
);
150 case SD_DHCP_OPTION_PAD
:
151 case SD_DHCP_OPTION_OVERLOAD
:
152 case SD_DHCP_OPTION_MESSAGE_TYPE
:
153 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
:
154 case SD_DHCP_OPTION_END
:
161 for (i
= 0; i
< client
->req_opts_size
; i
++)
162 if (client
->req_opts
[i
] == option
)
165 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
166 client
->req_opts_size
+ 1))
169 client
->req_opts
[client
->req_opts_size
++] = option
;
174 int sd_dhcp_client_set_request_address(sd_dhcp_client
*client
,
175 const struct in_addr
*last_addr
) {
176 assert_return(client
, -EINVAL
);
177 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
178 DHCP_STATE_STOPPED
), -EBUSY
);
181 client
->last_addr
= last_addr
->s_addr
;
183 client
->last_addr
= INADDR_ANY
;
188 int sd_dhcp_client_set_index(sd_dhcp_client
*client
, int interface_index
) {
189 assert_return(client
, -EINVAL
);
190 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
191 DHCP_STATE_STOPPED
), -EBUSY
);
192 assert_return(interface_index
> 0, -EINVAL
);
194 client
->index
= interface_index
;
199 int sd_dhcp_client_set_mac(sd_dhcp_client
*client
, const uint8_t *addr
,
200 size_t addr_len
, uint16_t arp_type
) {
201 DHCP_CLIENT_DONT_DESTROY(client
);
202 bool need_restart
= false;
204 assert_return(client
, -EINVAL
);
205 assert_return(addr
, -EINVAL
);
206 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
207 assert_return(arp_type
> 0, -EINVAL
);
209 if (arp_type
== ARPHRD_ETHER
)
210 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
211 else if (arp_type
== ARPHRD_INFINIBAND
)
212 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
216 if (client
->mac_addr_len
== addr_len
&&
217 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
220 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
221 log_dhcp_client(client
, "Changing MAC address on running DHCP "
222 "client, restarting");
224 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
227 memcpy(&client
->mac_addr
, addr
, addr_len
);
228 client
->mac_addr_len
= addr_len
;
229 client
->arp_type
= arp_type
;
231 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
232 sd_dhcp_client_start(client
);
237 int sd_dhcp_client_get_client_id(sd_dhcp_client
*client
, uint8_t *type
,
238 const uint8_t **data
, size_t *data_len
) {
240 assert_return(client
, -EINVAL
);
241 assert_return(type
, -EINVAL
);
242 assert_return(data
, -EINVAL
);
243 assert_return(data_len
, -EINVAL
);
248 if (client
->client_id_len
) {
249 *type
= client
->client_id
.type
;
250 *data
= client
->client_id
.raw
.data
;
251 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
257 int sd_dhcp_client_set_client_id(sd_dhcp_client
*client
, uint8_t type
,
258 const uint8_t *data
, size_t data_len
) {
259 DHCP_CLIENT_DONT_DESTROY(client
);
260 bool need_restart
= false;
262 assert_return(client
, -EINVAL
);
263 assert_return(data
, -EINVAL
);
264 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
268 if (data_len
!= ETH_ALEN
)
271 case ARPHRD_INFINIBAND
:
272 if (data_len
!= INFINIBAND_ALEN
)
279 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
280 client
->client_id
.type
== type
&&
281 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
284 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
285 log_dhcp_client(client
, "Changing client ID on running DHCP "
286 "client, restarting");
288 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
291 client
->client_id
.type
= type
;
292 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
293 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
295 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
296 sd_dhcp_client_start(client
);
301 int sd_dhcp_client_set_iaid_duid(sd_dhcp_client
*client
, uint32_t iaid
,
302 uint16_t duid_type
, uint8_t *duid
, size_t duid_len
) {
303 DHCP_CLIENT_DONT_DESTROY(client
);
305 assert_return(client
, -EINVAL
);
306 zero(client
->client_id
);
308 client
->client_id
.type
= 255;
310 /* If IAID is not configured, generate it. */
312 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
,
313 client
->mac_addr_len
,
314 &client
->client_id
.ns
.iaid
);
318 client
->client_id
.ns
.iaid
= htobe32(iaid
);
320 /* If DUID is not configured, generate DUID-EN. */
322 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
,
327 r
= dhcp_validate_duid_len(client
->client_id
.type
, duid_len
);
330 client
->client_id
.ns
.duid
.type
= htobe16(duid_type
);
331 memcpy(&client
->client_id
.ns
.duid
.raw
.data
, duid
, duid_len
);
332 duid_len
+= sizeof(client
->client_id
.ns
.duid
.type
);
335 client
->client_id_len
= sizeof(client
->client_id
.type
) + duid_len
+
336 sizeof(client
->client_id
.ns
.iaid
);
338 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
339 log_dhcp_client(client
, "Configured IAID+DUID, restarting.");
340 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
341 sd_dhcp_client_start(client
);
347 int sd_dhcp_client_set_hostname(sd_dhcp_client
*client
,
348 const char *hostname
) {
349 char *new_hostname
= NULL
;
351 assert_return(client
, -EINVAL
);
353 if (!hostname_is_valid(hostname
, false) && !dns_name_is_valid(hostname
))
356 if (streq_ptr(client
->hostname
, hostname
))
360 new_hostname
= strdup(hostname
);
365 free(client
->hostname
);
366 client
->hostname
= new_hostname
;
371 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client
*client
,
373 char *new_vci
= NULL
;
375 assert_return(client
, -EINVAL
);
377 new_vci
= strdup(vci
);
381 free(client
->vendor_class_identifier
);
383 client
->vendor_class_identifier
= new_vci
;
388 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
389 assert_return(client
, -EINVAL
);
390 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
397 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
398 assert_return(client
, -EINVAL
);
399 assert_return(ret
, -EINVAL
);
401 if (client
->state
!= DHCP_STATE_BOUND
&&
402 client
->state
!= DHCP_STATE_RENEWING
&&
403 client
->state
!= DHCP_STATE_REBINDING
)
404 return -EADDRNOTAVAIL
;
406 *ret
= client
->lease
;
411 static void client_notify(sd_dhcp_client
*client
, int event
) {
413 client
->cb(client
, event
, client
->userdata
);
416 static int client_initialize(sd_dhcp_client
*client
) {
417 assert_return(client
, -EINVAL
);
419 client
->receive_message
=
420 sd_event_source_unref(client
->receive_message
);
422 client
->fd
= asynchronous_close(client
->fd
);
424 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
426 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
427 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
428 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
432 client
->state
= DHCP_STATE_INIT
;
435 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
440 static void client_stop(sd_dhcp_client
*client
, int error
) {
444 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
445 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
446 log_dhcp_client(client
, "STOPPED");
448 log_dhcp_client(client
, "STOPPED: Unknown event");
450 client_notify(client
, error
);
452 client_initialize(client
);
455 static int client_message_init(sd_dhcp_client
*client
, DHCPPacket
**ret
,
456 uint8_t type
, size_t *_optlen
, size_t *_optoffset
) {
457 _cleanup_free_ DHCPPacket
*packet
= NULL
;
458 size_t optlen
, optoffset
, size
;
465 assert(client
->start_time
);
469 assert(type
== DHCP_DISCOVER
|| type
== DHCP_REQUEST
);
471 optlen
= DHCP_MIN_OPTIONS_SIZE
;
472 size
= sizeof(DHCPPacket
) + optlen
;
474 packet
= malloc0(size
);
478 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
479 client
->arp_type
, optlen
, &optoffset
);
483 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
484 refuse to issue an DHCP lease if 'secs' is set to zero */
485 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
488 assert(time_now
>= client
->start_time
);
490 /* seconds between sending first and last DISCOVER
491 * must always be strictly positive to deal with broken servers */
492 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
493 packet
->dhcp
.secs
= htobe16(secs
);
495 /* RFC2132 section 4.1
496 A client that cannot receive unicast IP datagrams until its protocol
497 software has been configured with an IP address SHOULD set the
498 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
499 DHCPREQUEST messages that client sends. The BROADCAST bit will
500 provide a hint to the DHCP server and BOOTP relay agent to broadcast
501 any messages to the client on the client's subnet.
503 Note: some interfaces needs this to be enabled, but some networks
504 needs this to be disabled as broadcasts are filteretd, so this
505 needs to be configurable */
506 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
507 packet
->dhcp
.flags
= htobe16(0x8000);
509 /* RFC2132 section 4.1.1:
510 The client MUST include its hardware address in the ’chaddr’ field, if
511 necessary for delivery of DHCP reply messages. Non-Ethernet
512 interfaces will leave 'chaddr' empty and use the client identifier
513 instead (eg, RFC 4390 section 2.1).
515 if (client
->arp_type
== ARPHRD_ETHER
)
516 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
518 /* If no client identifier exists, construct an RFC 4361-compliant one */
519 if (client
->client_id_len
== 0) {
522 client
->client_id
.type
= 255;
524 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
528 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
532 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
535 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
536 Identifier option is not set */
537 if (client
->client_id_len
) {
538 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
539 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
540 client
->client_id_len
,
546 /* RFC2131 section 3.5:
547 in its initial DHCPDISCOVER or DHCPREQUEST message, a
548 client may provide the server with a list of specific
549 parameters the client is interested in. If the client
550 includes a list of parameters in a DHCPDISCOVER message,
551 it MUST include that list in any subsequent DHCPREQUEST
554 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
555 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
556 client
->req_opts_size
, client
->req_opts
);
560 /* RFC2131 section 3.5:
561 The client SHOULD include the ’maximum DHCP message size’ option to
562 let the server know how large the server may make its DHCP messages.
564 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
565 than the defined default size unless the Maximum Messge Size option
568 RFC3442 "Requirements to Avoid Sizing Constraints":
569 Because a full routing table can be quite large, the standard 576
570 octet maximum size for a DHCP message may be too short to contain
571 some legitimate Classless Static Route options. Because of this,
572 clients implementing the Classless Static Route option SHOULD send a
573 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
574 stack is capable of receiving larger IP datagrams. In this case, the
575 client SHOULD set the value of this option to at least the MTU of the
576 interface that the client is configuring. The client MAY set the
577 value of this option higher, up to the size of the largest UDP packet
578 it is prepared to accept. (Note that the value specified in the
579 Maximum DHCP Message Size option is the total maximum packet size,
580 including IP and UDP headers.)
582 max_size
= htobe16(size
);
583 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
584 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
590 *_optoffset
= optoffset
;
597 static int client_append_fqdn_option(DHCPMessage
*message
, size_t optlen
, size_t *optoffset
,
599 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
602 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
603 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
604 buffer
[1] = 0; /* RCODE1 (deprecated) */
605 buffer
[2] = 0; /* RCODE2 (deprecated) */
607 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
609 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
610 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
615 static int dhcp_client_send_raw(sd_dhcp_client
*client
, DHCPPacket
*packet
,
617 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, DHCP_PORT_CLIENT
,
618 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
620 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
624 static int client_send_discover(sd_dhcp_client
*client
) {
625 _cleanup_free_ DHCPPacket
*discover
= NULL
;
626 size_t optoffset
, optlen
;
630 assert(client
->state
== DHCP_STATE_INIT
||
631 client
->state
== DHCP_STATE_SELECTING
);
633 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
634 &optlen
, &optoffset
);
638 /* the client may suggest values for the network address
639 and lease time in the DHCPDISCOVER message. The client may include
640 the ’requested IP address’ option to suggest that a particular IP
641 address be assigned, and may include the ’IP address lease time’
642 option to suggest the lease time it would like.
644 if (client
->last_addr
!= INADDR_ANY
) {
645 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
646 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
647 4, &client
->last_addr
);
652 if (client
->hostname
) {
653 /* According to RFC 4702 "clients that send the Client FQDN option in
654 their messages MUST NOT also send the Host Name option". Just send
655 one of the two depending on the hostname type.
657 if (dns_name_is_single_label(client
->hostname
)) {
658 /* it is unclear from RFC 2131 if client should send hostname in
659 DHCPDISCOVER but dhclient does and so we do as well
661 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
662 SD_DHCP_OPTION_HOST_NAME
,
663 strlen(client
->hostname
), client
->hostname
);
665 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
671 if (client
->vendor_class_identifier
) {
672 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
673 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
674 strlen(client
->vendor_class_identifier
),
675 client
->vendor_class_identifier
);
680 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
681 SD_DHCP_OPTION_END
, 0, NULL
);
685 /* We currently ignore:
686 The client SHOULD wait a random time between one and ten seconds to
687 desynchronize the use of DHCP at startup.
689 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
693 log_dhcp_client(client
, "DISCOVER");
698 static int client_send_request(sd_dhcp_client
*client
) {
699 _cleanup_free_ DHCPPacket
*request
= NULL
;
700 size_t optoffset
, optlen
;
703 r
= client_message_init(client
, &request
, DHCP_REQUEST
,
704 &optlen
, &optoffset
);
708 switch (client
->state
) {
709 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
710 SELECTING should be REQUESTING)
713 case DHCP_STATE_REQUESTING
:
714 /* Client inserts the address of the selected server in ’server
715 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
716 filled in with the yiaddr value from the chosen DHCPOFFER.
719 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
720 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
721 4, &client
->lease
->server_address
);
725 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
726 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
727 4, &client
->lease
->address
);
733 case DHCP_STATE_INIT_REBOOT
:
734 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
735 option MUST be filled in with client’s notion of its previously
736 assigned address. ’ciaddr’ MUST be zero.
738 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
739 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
740 4, &client
->last_addr
);
745 case DHCP_STATE_RENEWING
:
746 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
747 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
748 client’s IP address.
752 case DHCP_STATE_REBINDING
:
753 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
754 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
755 client’s IP address.
757 This message MUST be broadcast to the 0xffffffff IP broadcast address.
759 request
->dhcp
.ciaddr
= client
->lease
->address
;
763 case DHCP_STATE_INIT
:
764 case DHCP_STATE_SELECTING
:
765 case DHCP_STATE_REBOOTING
:
766 case DHCP_STATE_BOUND
:
767 case DHCP_STATE_STOPPED
:
771 if (client
->hostname
) {
772 if (dns_name_is_single_label(client
->hostname
))
773 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
774 SD_DHCP_OPTION_HOST_NAME
,
775 strlen(client
->hostname
), client
->hostname
);
777 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
783 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
784 SD_DHCP_OPTION_END
, 0, NULL
);
788 if (client
->state
== DHCP_STATE_RENEWING
) {
789 r
= dhcp_network_send_udp_socket(client
->fd
,
790 client
->lease
->server_address
,
793 sizeof(DHCPMessage
) + optoffset
);
795 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
800 switch (client
->state
) {
801 case DHCP_STATE_REQUESTING
:
802 log_dhcp_client(client
, "REQUEST (requesting)");
804 case DHCP_STATE_INIT_REBOOT
:
805 log_dhcp_client(client
, "REQUEST (init-reboot)");
807 case DHCP_STATE_RENEWING
:
808 log_dhcp_client(client
, "REQUEST (renewing)");
810 case DHCP_STATE_REBINDING
:
811 log_dhcp_client(client
, "REQUEST (rebinding)");
814 log_dhcp_client(client
, "REQUEST (invalid)");
821 static int client_start(sd_dhcp_client
*client
);
823 static int client_timeout_resend(sd_event_source
*s
, uint64_t usec
,
825 sd_dhcp_client
*client
= userdata
;
826 DHCP_CLIENT_DONT_DESTROY(client
);
827 usec_t next_timeout
= 0;
834 assert(client
->event
);
836 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
840 switch (client
->state
) {
841 case DHCP_STATE_RENEWING
:
843 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
847 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
851 case DHCP_STATE_REBINDING
:
853 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
857 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
860 case DHCP_STATE_REBOOTING
:
861 /* start over as we did not receive a timely ack or nak */
862 r
= client_initialize(client
);
866 r
= client_start(client
);
870 log_dhcp_client(client
, "REBOOTED");
874 case DHCP_STATE_INIT
:
875 case DHCP_STATE_INIT_REBOOT
:
876 case DHCP_STATE_SELECTING
:
877 case DHCP_STATE_REQUESTING
:
878 case DHCP_STATE_BOUND
:
880 if (client
->attempt
< 64)
881 client
->attempt
*= 2;
883 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
887 case DHCP_STATE_STOPPED
:
892 next_timeout
+= (random_u32() & 0x1fffff);
894 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
896 r
= sd_event_add_time(client
->event
,
897 &client
->timeout_resend
,
898 clock_boottime_or_monotonic(),
899 next_timeout
, 10 * USEC_PER_MSEC
,
900 client_timeout_resend
, client
);
904 r
= sd_event_source_set_priority(client
->timeout_resend
,
905 client
->event_priority
);
909 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
913 switch (client
->state
) {
914 case DHCP_STATE_INIT
:
915 r
= client_send_discover(client
);
917 client
->state
= DHCP_STATE_SELECTING
;
920 if (client
->attempt
>= 64)
926 case DHCP_STATE_SELECTING
:
927 r
= client_send_discover(client
);
928 if (r
< 0 && client
->attempt
>= 64)
933 case DHCP_STATE_INIT_REBOOT
:
934 case DHCP_STATE_REQUESTING
:
935 case DHCP_STATE_RENEWING
:
936 case DHCP_STATE_REBINDING
:
937 r
= client_send_request(client
);
938 if (r
< 0 && client
->attempt
>= 64)
941 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
942 client
->state
= DHCP_STATE_REBOOTING
;
944 client
->request_sent
= time_now
;
948 case DHCP_STATE_REBOOTING
:
949 case DHCP_STATE_BOUND
:
953 case DHCP_STATE_STOPPED
:
961 client_stop(client
, r
);
963 /* Errors were dealt with when stopping the client, don't spill
964 errors into the event loop handler */
968 static int client_initialize_io_events(sd_dhcp_client
*client
,
969 sd_event_io_handler_t io_callback
) {
973 assert(client
->event
);
975 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
976 client
->fd
, EPOLLIN
, io_callback
,
981 r
= sd_event_source_set_priority(client
->receive_message
,
982 client
->event_priority
);
986 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
992 client_stop(client
, r
);
997 static int client_initialize_time_events(sd_dhcp_client
*client
) {
1002 assert(client
->event
);
1004 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
1006 if (client
->start_delay
) {
1007 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
1008 usec
+= client
->start_delay
;
1011 r
= sd_event_add_time(client
->event
,
1012 &client
->timeout_resend
,
1013 clock_boottime_or_monotonic(),
1015 client_timeout_resend
, client
);
1019 r
= sd_event_source_set_priority(client
->timeout_resend
,
1020 client
->event_priority
);
1024 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1030 client_stop(client
, r
);
1036 static int client_initialize_events(sd_dhcp_client
*client
,
1037 sd_event_io_handler_t io_callback
) {
1038 client_initialize_io_events(client
, io_callback
);
1039 client_initialize_time_events(client
);
1044 static int client_start_delayed(sd_dhcp_client
*client
) {
1047 assert_return(client
, -EINVAL
);
1048 assert_return(client
->event
, -EINVAL
);
1049 assert_return(client
->index
> 0, -EINVAL
);
1050 assert_return(client
->fd
< 0, -EBUSY
);
1051 assert_return(client
->xid
== 0, -EINVAL
);
1052 assert_return(client
->state
== DHCP_STATE_INIT
||
1053 client
->state
== DHCP_STATE_INIT_REBOOT
, -EBUSY
);
1055 client
->xid
= random_u32();
1057 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1058 client
->xid
, client
->mac_addr
,
1059 client
->mac_addr_len
, client
->arp_type
);
1061 client_stop(client
, r
);
1066 if (client
->state
== DHCP_STATE_INIT
|| client
->state
== DHCP_STATE_INIT_REBOOT
)
1067 client
->start_time
= now(clock_boottime_or_monotonic());
1069 return client_initialize_events(client
, client_receive_message_raw
);
1072 static int client_start(sd_dhcp_client
*client
) {
1073 client
->start_delay
= 0;
1074 return client_start_delayed(client
);
1077 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
,
1079 sd_dhcp_client
*client
= userdata
;
1080 DHCP_CLIENT_DONT_DESTROY(client
);
1082 log_dhcp_client(client
, "EXPIRED");
1084 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1086 /* lease was lost, start over if not freed or stopped in callback */
1087 if (client
->state
!= DHCP_STATE_STOPPED
) {
1088 client_initialize(client
);
1089 client_start(client
);
1095 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1096 sd_dhcp_client
*client
= userdata
;
1097 DHCP_CLIENT_DONT_DESTROY(client
);
1100 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1101 client
->fd
= asynchronous_close(client
->fd
);
1103 client
->state
= DHCP_STATE_REBINDING
;
1104 client
->attempt
= 1;
1106 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1107 client
->xid
, client
->mac_addr
,
1108 client
->mac_addr_len
, client
->arp_type
);
1110 client_stop(client
, r
);
1115 return client_initialize_events(client
, client_receive_message_raw
);
1118 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
,
1120 sd_dhcp_client
*client
= userdata
;
1121 DHCP_CLIENT_DONT_DESTROY(client
);
1123 client
->state
= DHCP_STATE_RENEWING
;
1124 client
->attempt
= 1;
1126 return client_initialize_time_events(client
);
1129 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
,
1131 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1134 r
= dhcp_lease_new(&lease
);
1138 if (client
->client_id_len
) {
1139 r
= dhcp_lease_set_client_id(lease
,
1140 (uint8_t *) &client
->client_id
,
1141 client
->client_id_len
);
1146 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1147 if (r
!= DHCP_OFFER
) {
1148 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1152 lease
->next_server
= offer
->siaddr
;
1153 lease
->address
= offer
->yiaddr
;
1155 if (lease
->address
== 0 ||
1156 lease
->server_address
== 0 ||
1157 lease
->lifetime
== 0) {
1158 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1162 if (!lease
->have_subnet_mask
) {
1163 r
= dhcp_lease_set_default_subnet_mask(lease
);
1165 log_dhcp_client(client
, "received lease lacks subnet "
1166 "mask, and a fallback one can not be "
1167 "generated, ignoring");
1172 sd_dhcp_lease_unref(client
->lease
);
1173 client
->lease
= lease
;
1176 log_dhcp_client(client
, "OFFER");
1181 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
,
1185 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1186 if (r
!= DHCP_FORCERENEW
)
1189 log_dhcp_client(client
, "FORCERENEW");
1194 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
,
1196 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1197 _cleanup_free_
char *error_message
= NULL
;
1200 r
= dhcp_lease_new(&lease
);
1204 if (client
->client_id_len
) {
1205 r
= dhcp_lease_set_client_id(lease
,
1206 (uint8_t *) &client
->client_id
,
1207 client
->client_id_len
);
1212 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1213 if (r
== DHCP_NAK
) {
1214 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1215 return -EADDRNOTAVAIL
;
1218 if (r
!= DHCP_ACK
) {
1219 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1223 lease
->next_server
= ack
->siaddr
;
1225 lease
->address
= ack
->yiaddr
;
1227 if (lease
->address
== INADDR_ANY
||
1228 lease
->server_address
== INADDR_ANY
||
1229 lease
->lifetime
== 0) {
1230 log_dhcp_client(client
, "received lease lacks address, server "
1231 "address or lease lifetime, ignoring");
1235 if (lease
->subnet_mask
== INADDR_ANY
) {
1236 r
= dhcp_lease_set_default_subnet_mask(lease
);
1238 log_dhcp_client(client
, "received lease lacks subnet "
1239 "mask, and a fallback one can not be "
1240 "generated, ignoring");
1245 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1246 if (client
->lease
) {
1247 if (client
->lease
->address
!= lease
->address
||
1248 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1249 client
->lease
->router
!= lease
->router
) {
1250 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1252 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1254 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1257 client
->lease
= lease
;
1260 log_dhcp_client(client
, "ACK");
1265 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1267 assert(client
->request_sent
);
1268 assert(lifetime
> 0);
1275 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1276 + (random_u32() & 0x1fffff);
1279 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1281 uint64_t lifetime_timeout
;
1282 uint64_t t2_timeout
;
1283 uint64_t t1_timeout
;
1284 char time_string
[FORMAT_TIMESPAN_MAX
];
1288 assert(client
->event
);
1289 assert(client
->lease
);
1290 assert(client
->lease
->lifetime
);
1292 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1293 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1294 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1296 /* don't set timers for infinite leases */
1297 if (client
->lease
->lifetime
== 0xffffffff)
1300 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1303 assert(client
->request_sent
<= time_now
);
1305 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1306 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1307 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1308 /* both T1 and T2 are given */
1309 if (client
->lease
->t1
< client
->lease
->t2
&&
1310 client
->lease
->t2
< client
->lease
->lifetime
) {
1311 /* they are both valid */
1312 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1313 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1316 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1317 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1318 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1319 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1321 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1322 /* only T2 is given, and it is valid */
1323 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1324 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1325 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1326 if (t2_timeout
<= t1_timeout
) {
1327 /* the computed T1 would be invalid, so discard T2 */
1328 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1329 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1331 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1332 /* only T1 is given, and it is valid */
1333 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1334 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1335 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1336 if (t2_timeout
<= t1_timeout
) {
1337 /* the computed T2 would be invalid, so discard T1 */
1338 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1339 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1342 /* fall back to the default timeouts */
1343 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1344 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1345 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1346 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1349 /* arm lifetime timeout */
1350 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1351 clock_boottime_or_monotonic(),
1352 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1353 client_timeout_expire
, client
);
1357 r
= sd_event_source_set_priority(client
->timeout_expire
,
1358 client
->event_priority
);
1362 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1366 log_dhcp_client(client
, "lease expires in %s",
1367 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1369 /* don't arm earlier timeouts if this has already expired */
1370 if (lifetime_timeout
<= time_now
)
1373 /* arm T2 timeout */
1374 r
= sd_event_add_time(client
->event
,
1375 &client
->timeout_t2
,
1376 clock_boottime_or_monotonic(),
1379 client_timeout_t2
, client
);
1383 r
= sd_event_source_set_priority(client
->timeout_t2
,
1384 client
->event_priority
);
1388 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1392 log_dhcp_client(client
, "T2 expires in %s",
1393 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1395 /* don't arm earlier timeout if this has already expired */
1396 if (t2_timeout
<= time_now
)
1399 /* arm T1 timeout */
1400 r
= sd_event_add_time(client
->event
,
1401 &client
->timeout_t1
,
1402 clock_boottime_or_monotonic(),
1403 t1_timeout
, 10 * USEC_PER_MSEC
,
1404 client_timeout_t1
, client
);
1408 r
= sd_event_source_set_priority(client
->timeout_t1
,
1409 client
->event_priority
);
1413 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1417 log_dhcp_client(client
, "T1 expires in %s",
1418 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1423 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
,
1425 DHCP_CLIENT_DONT_DESTROY(client
);
1426 char time_string
[FORMAT_TIMESPAN_MAX
];
1427 int r
= 0, notify_event
= 0;
1430 assert(client
->event
);
1433 switch (client
->state
) {
1434 case DHCP_STATE_SELECTING
:
1436 r
= client_handle_offer(client
, message
, len
);
1439 client
->timeout_resend
=
1440 sd_event_source_unref(client
->timeout_resend
);
1442 client
->state
= DHCP_STATE_REQUESTING
;
1443 client
->attempt
= 1;
1445 r
= sd_event_add_time(client
->event
,
1446 &client
->timeout_resend
,
1447 clock_boottime_or_monotonic(),
1449 client_timeout_resend
, client
);
1453 r
= sd_event_source_set_priority(client
->timeout_resend
,
1454 client
->event_priority
);
1458 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1461 } else if (r
== -ENOMSG
)
1462 /* invalid message, let's ignore it */
1467 case DHCP_STATE_REBOOTING
:
1468 case DHCP_STATE_REQUESTING
:
1469 case DHCP_STATE_RENEWING
:
1470 case DHCP_STATE_REBINDING
:
1472 r
= client_handle_ack(client
, message
, len
);
1474 client
->start_delay
= 0;
1475 client
->timeout_resend
=
1476 sd_event_source_unref(client
->timeout_resend
);
1477 client
->receive_message
=
1478 sd_event_source_unref(client
->receive_message
);
1479 client
->fd
= asynchronous_close(client
->fd
);
1481 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1482 DHCP_STATE_REBOOTING
))
1483 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1484 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1487 client
->state
= DHCP_STATE_BOUND
;
1488 client
->attempt
= 1;
1490 client
->last_addr
= client
->lease
->address
;
1492 r
= client_set_lease_timeouts(client
);
1494 log_dhcp_client(client
, "could not set lease timeouts");
1498 r
= dhcp_network_bind_udp_socket(client
->lease
->address
,
1501 log_dhcp_client(client
, "could not bind UDP socket");
1507 client_initialize_io_events(client
, client_receive_message_udp
);
1510 client_notify(client
, notify_event
);
1511 if (client
->state
== DHCP_STATE_STOPPED
)
1515 } else if (r
== -EADDRNOTAVAIL
) {
1516 /* got a NAK, let's restart the client */
1517 client
->timeout_resend
=
1518 sd_event_source_unref(client
->timeout_resend
);
1520 r
= client_initialize(client
);
1524 r
= client_start_delayed(client
);
1528 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1529 client
->start_delay
, USEC_PER_SEC
));
1531 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1532 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1535 } else if (r
== -ENOMSG
)
1536 /* invalid message, let's ignore it */
1541 case DHCP_STATE_BOUND
:
1542 r
= client_handle_forcerenew(client
, message
, len
);
1544 r
= client_timeout_t1(NULL
, 0, client
);
1547 } else if (r
== -ENOMSG
)
1548 /* invalid message, let's ignore it */
1553 case DHCP_STATE_INIT
:
1554 case DHCP_STATE_INIT_REBOOT
:
1558 case DHCP_STATE_STOPPED
:
1565 client_stop(client
, r
);
1570 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
1571 uint32_t revents
, void *userdata
) {
1572 sd_dhcp_client
*client
= userdata
;
1573 _cleanup_free_ DHCPMessage
*message
= NULL
;
1574 const struct ether_addr zero_mac
= { { 0, 0, 0, 0, 0, 0 } };
1575 const struct ether_addr
*expected_chaddr
= NULL
;
1576 uint8_t expected_hlen
= 0;
1577 ssize_t len
, buflen
;
1582 buflen
= next_datagram_size_fd(fd
);
1586 message
= malloc0(buflen
);
1590 len
= read(fd
, message
, buflen
);
1592 if (errno
== EAGAIN
|| errno
== EINTR
)
1595 log_dhcp_client(client
, "Could not receive message from UDP socket: %m");
1597 } else if ((size_t)len
< sizeof(DHCPMessage
)) {
1598 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1602 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1603 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1607 if (message
->op
!= BOOTREPLY
) {
1608 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1612 if (message
->htype
!= client
->arp_type
) {
1613 log_dhcp_client(client
, "Packet type does not match client type");
1617 if (client
->arp_type
== ARPHRD_ETHER
) {
1618 expected_hlen
= ETH_ALEN
;
1619 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1621 /* Non-Ethernet links expect zero chaddr */
1623 expected_chaddr
= &zero_mac
;
1626 if (message
->hlen
!= expected_hlen
) {
1627 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1631 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1632 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1636 if (client
->state
!= DHCP_STATE_BOUND
&&
1637 be32toh(message
->xid
) != client
->xid
) {
1638 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1639 so ignore the xid in this case */
1640 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1641 be32toh(message
->xid
), client
->xid
);
1645 return client_handle_message(client
, message
, len
);
1648 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
1649 uint32_t revents
, void *userdata
) {
1650 sd_dhcp_client
*client
= userdata
;
1651 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1652 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1653 struct iovec iov
= {};
1654 struct msghdr msg
= {
1657 .msg_control
= cmsgbuf
,
1658 .msg_controllen
= sizeof(cmsgbuf
),
1660 struct cmsghdr
*cmsg
;
1661 bool checksum
= true;
1662 ssize_t buflen
, len
;
1668 buflen
= next_datagram_size_fd(fd
);
1672 packet
= malloc0(buflen
);
1676 iov
.iov_base
= packet
;
1677 iov
.iov_len
= buflen
;
1679 len
= recvmsg(fd
, &msg
, 0);
1681 if (errno
== EAGAIN
|| errno
== EINTR
)
1684 log_dhcp_client(client
, "Could not receive message from raw socket: %m");
1687 } else if ((size_t)len
< sizeof(DHCPPacket
))
1690 CMSG_FOREACH(cmsg
, &msg
) {
1691 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1692 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1693 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1694 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1696 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1701 r
= dhcp_packet_verify_headers(packet
, len
, checksum
);
1705 len
-= DHCP_IP_UDP_SIZE
;
1707 return client_handle_message(client
, &packet
->dhcp
, len
);
1710 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1713 assert_return(client
, -EINVAL
);
1715 r
= client_initialize(client
);
1719 if (client
->last_addr
)
1720 client
->state
= DHCP_STATE_INIT_REBOOT
;
1722 r
= client_start(client
);
1724 log_dhcp_client(client
, "STARTED on ifindex %i", client
->index
);
1729 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1730 DHCP_CLIENT_DONT_DESTROY(client
);
1732 assert_return(client
, -EINVAL
);
1734 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1735 client
->state
= DHCP_STATE_STOPPED
;
1740 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
, int64_t priority
) {
1743 assert_return(client
, -EINVAL
);
1744 assert_return(!client
->event
, -EBUSY
);
1747 client
->event
= sd_event_ref(event
);
1749 r
= sd_event_default(&client
->event
);
1754 client
->event_priority
= priority
;
1759 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1760 assert_return(client
, -EINVAL
);
1762 client
->event
= sd_event_unref(client
->event
);
1767 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1771 return client
->event
;
1774 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1779 assert(client
->n_ref
>= 1);
1785 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1790 assert(client
->n_ref
>= 1);
1793 if (client
->n_ref
> 0)
1796 log_dhcp_client(client
, "FREE");
1798 client_initialize(client
);
1800 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1802 sd_dhcp_client_detach_event(client
);
1804 sd_dhcp_lease_unref(client
->lease
);
1806 free(client
->req_opts
);
1807 free(client
->hostname
);
1808 free(client
->vendor_class_identifier
);
1814 int sd_dhcp_client_new(sd_dhcp_client
**ret
) {
1815 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1817 assert_return(ret
, -EINVAL
);
1819 client
= new0(sd_dhcp_client
, 1);
1824 client
->state
= DHCP_STATE_INIT
;
1827 client
->attempt
= 1;
1828 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1830 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1832 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1833 if (!client
->req_opts
)