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_hostname(sd_dhcp_client
*client
,
302 const char *hostname
) {
303 char *new_hostname
= NULL
;
305 assert_return(client
, -EINVAL
);
307 if (!hostname_is_valid(hostname
, false) && !dns_name_is_valid(hostname
))
310 if (streq_ptr(client
->hostname
, hostname
))
314 new_hostname
= strdup(hostname
);
319 free(client
->hostname
);
320 client
->hostname
= new_hostname
;
325 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client
*client
,
327 char *new_vci
= NULL
;
329 assert_return(client
, -EINVAL
);
331 new_vci
= strdup(vci
);
335 free(client
->vendor_class_identifier
);
337 client
->vendor_class_identifier
= new_vci
;
342 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
343 assert_return(client
, -EINVAL
);
344 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
351 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
352 assert_return(client
, -EINVAL
);
353 assert_return(ret
, -EINVAL
);
355 if (client
->state
!= DHCP_STATE_BOUND
&&
356 client
->state
!= DHCP_STATE_RENEWING
&&
357 client
->state
!= DHCP_STATE_REBINDING
)
358 return -EADDRNOTAVAIL
;
360 *ret
= client
->lease
;
365 static void client_notify(sd_dhcp_client
*client
, int event
) {
367 client
->cb(client
, event
, client
->userdata
);
370 static int client_initialize(sd_dhcp_client
*client
) {
371 assert_return(client
, -EINVAL
);
373 client
->receive_message
=
374 sd_event_source_unref(client
->receive_message
);
376 client
->fd
= asynchronous_close(client
->fd
);
378 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
380 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
381 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
382 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
386 client
->state
= DHCP_STATE_INIT
;
389 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
394 static void client_stop(sd_dhcp_client
*client
, int error
) {
398 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
399 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
400 log_dhcp_client(client
, "STOPPED");
402 log_dhcp_client(client
, "STOPPED: Unknown event");
404 client_notify(client
, error
);
406 client_initialize(client
);
409 static int client_message_init(sd_dhcp_client
*client
, DHCPPacket
**ret
,
410 uint8_t type
, size_t *_optlen
, size_t *_optoffset
) {
411 _cleanup_free_ DHCPPacket
*packet
;
412 size_t optlen
, optoffset
, size
;
419 assert(client
->start_time
);
423 assert(type
== DHCP_DISCOVER
|| type
== DHCP_REQUEST
);
425 optlen
= DHCP_MIN_OPTIONS_SIZE
;
426 size
= sizeof(DHCPPacket
) + optlen
;
428 packet
= malloc0(size
);
432 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
433 client
->arp_type
, optlen
, &optoffset
);
437 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
438 refuse to issue an DHCP lease if 'secs' is set to zero */
439 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
442 assert(time_now
>= client
->start_time
);
444 /* seconds between sending first and last DISCOVER
445 * must always be strictly positive to deal with broken servers */
446 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
447 packet
->dhcp
.secs
= htobe16(secs
);
449 /* RFC2132 section 4.1
450 A client that cannot receive unicast IP datagrams until its protocol
451 software has been configured with an IP address SHOULD set the
452 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
453 DHCPREQUEST messages that client sends. The BROADCAST bit will
454 provide a hint to the DHCP server and BOOTP relay agent to broadcast
455 any messages to the client on the client's subnet.
457 Note: some interfaces needs this to be enabled, but some networks
458 needs this to be disabled as broadcasts are filteretd, so this
459 needs to be configurable */
460 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
461 packet
->dhcp
.flags
= htobe16(0x8000);
463 /* RFC2132 section 4.1.1:
464 The client MUST include its hardware address in the ’chaddr’ field, if
465 necessary for delivery of DHCP reply messages. Non-Ethernet
466 interfaces will leave 'chaddr' empty and use the client identifier
467 instead (eg, RFC 4390 section 2.1).
469 if (client
->arp_type
== ARPHRD_ETHER
)
470 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
472 /* If no client identifier exists, construct an RFC 4361-compliant one */
473 if (client
->client_id_len
== 0) {
476 client
->client_id
.type
= 255;
478 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
482 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
486 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
489 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
490 Identifier option is not set */
491 if (client
->client_id_len
) {
492 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
493 SD_DHCP_OPTION_CLIENT_IDENTIFIER
,
494 client
->client_id_len
,
500 /* RFC2131 section 3.5:
501 in its initial DHCPDISCOVER or DHCPREQUEST message, a
502 client may provide the server with a list of specific
503 parameters the client is interested in. If the client
504 includes a list of parameters in a DHCPDISCOVER message,
505 it MUST include that list in any subsequent DHCPREQUEST
508 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
509 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
,
510 client
->req_opts_size
, client
->req_opts
);
514 /* RFC2131 section 3.5:
515 The client SHOULD include the ’maximum DHCP message size’ option to
516 let the server know how large the server may make its DHCP messages.
518 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
519 than the defined default size unless the Maximum Messge Size option
522 RFC3442 "Requirements to Avoid Sizing Constraints":
523 Because a full routing table can be quite large, the standard 576
524 octet maximum size for a DHCP message may be too short to contain
525 some legitimate Classless Static Route options. Because of this,
526 clients implementing the Classless Static Route option SHOULD send a
527 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
528 stack is capable of receiving larger IP datagrams. In this case, the
529 client SHOULD set the value of this option to at least the MTU of the
530 interface that the client is configuring. The client MAY set the
531 value of this option higher, up to the size of the largest UDP packet
532 it is prepared to accept. (Note that the value specified in the
533 Maximum DHCP Message Size option is the total maximum packet size,
534 including IP and UDP headers.)
536 max_size
= htobe16(size
);
537 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
538 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
544 *_optoffset
= optoffset
;
551 static int client_append_fqdn_option(DHCPMessage
*message
, size_t optlen
, size_t *optoffset
,
553 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
556 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
557 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
558 buffer
[1] = 0; /* RCODE1 (deprecated) */
559 buffer
[2] = 0; /* RCODE2 (deprecated) */
561 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
563 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
564 SD_DHCP_OPTION_FQDN
, 3 + r
, buffer
);
569 static int dhcp_client_send_raw(sd_dhcp_client
*client
, DHCPPacket
*packet
,
571 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, DHCP_PORT_CLIENT
,
572 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
574 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
578 static int client_send_discover(sd_dhcp_client
*client
) {
579 _cleanup_free_ DHCPPacket
*discover
= NULL
;
580 size_t optoffset
, optlen
;
584 assert(client
->state
== DHCP_STATE_INIT
||
585 client
->state
== DHCP_STATE_SELECTING
);
587 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
588 &optlen
, &optoffset
);
592 /* the client may suggest values for the network address
593 and lease time in the DHCPDISCOVER message. The client may include
594 the ’requested IP address’ option to suggest that a particular IP
595 address be assigned, and may include the ’IP address lease time’
596 option to suggest the lease time it would like.
598 if (client
->last_addr
!= INADDR_ANY
) {
599 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
600 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
601 4, &client
->last_addr
);
606 if (client
->hostname
) {
607 /* According to RFC 4702 "clients that send the Client FQDN option in
608 their messages MUST NOT also send the Host Name option". Just send
609 one of the two depending on the hostname type.
611 if (dns_name_is_single_label(client
->hostname
)) {
612 /* it is unclear from RFC 2131 if client should send hostname in
613 DHCPDISCOVER but dhclient does and so we do as well
615 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
616 SD_DHCP_OPTION_HOST_NAME
,
617 strlen(client
->hostname
), client
->hostname
);
619 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
625 if (client
->vendor_class_identifier
) {
626 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
627 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
628 strlen(client
->vendor_class_identifier
),
629 client
->vendor_class_identifier
);
634 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
635 SD_DHCP_OPTION_END
, 0, NULL
);
639 /* We currently ignore:
640 The client SHOULD wait a random time between one and ten seconds to
641 desynchronize the use of DHCP at startup.
643 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
647 log_dhcp_client(client
, "DISCOVER");
652 static int client_send_request(sd_dhcp_client
*client
) {
653 _cleanup_free_ DHCPPacket
*request
= NULL
;
654 size_t optoffset
, optlen
;
657 r
= client_message_init(client
, &request
, DHCP_REQUEST
,
658 &optlen
, &optoffset
);
662 switch (client
->state
) {
663 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
664 SELECTING should be REQUESTING)
667 case DHCP_STATE_REQUESTING
:
668 /* Client inserts the address of the selected server in ’server
669 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
670 filled in with the yiaddr value from the chosen DHCPOFFER.
673 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
674 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
675 4, &client
->lease
->server_address
);
679 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
680 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
681 4, &client
->lease
->address
);
687 case DHCP_STATE_INIT_REBOOT
:
688 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
689 option MUST be filled in with client’s notion of its previously
690 assigned address. ’ciaddr’ MUST be zero.
692 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
693 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
,
694 4, &client
->last_addr
);
699 case DHCP_STATE_RENEWING
:
700 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
701 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
702 client’s IP address.
706 case DHCP_STATE_REBINDING
:
707 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
708 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
709 client’s IP address.
711 This message MUST be broadcast to the 0xffffffff IP broadcast address.
713 request
->dhcp
.ciaddr
= client
->lease
->address
;
717 case DHCP_STATE_INIT
:
718 case DHCP_STATE_SELECTING
:
719 case DHCP_STATE_REBOOTING
:
720 case DHCP_STATE_BOUND
:
721 case DHCP_STATE_STOPPED
:
725 if (client
->hostname
) {
726 if (dns_name_is_single_label(client
->hostname
))
727 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
728 SD_DHCP_OPTION_HOST_NAME
,
729 strlen(client
->hostname
), client
->hostname
);
731 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
737 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
738 SD_DHCP_OPTION_END
, 0, NULL
);
742 if (client
->state
== DHCP_STATE_RENEWING
) {
743 r
= dhcp_network_send_udp_socket(client
->fd
,
744 client
->lease
->server_address
,
747 sizeof(DHCPMessage
) + optoffset
);
749 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
754 switch (client
->state
) {
755 case DHCP_STATE_REQUESTING
:
756 log_dhcp_client(client
, "REQUEST (requesting)");
758 case DHCP_STATE_INIT_REBOOT
:
759 log_dhcp_client(client
, "REQUEST (init-reboot)");
761 case DHCP_STATE_RENEWING
:
762 log_dhcp_client(client
, "REQUEST (renewing)");
764 case DHCP_STATE_REBINDING
:
765 log_dhcp_client(client
, "REQUEST (rebinding)");
768 log_dhcp_client(client
, "REQUEST (invalid)");
775 static int client_start(sd_dhcp_client
*client
);
777 static int client_timeout_resend(sd_event_source
*s
, uint64_t usec
,
779 sd_dhcp_client
*client
= userdata
;
780 DHCP_CLIENT_DONT_DESTROY(client
);
781 usec_t next_timeout
= 0;
788 assert(client
->event
);
790 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
794 switch (client
->state
) {
795 case DHCP_STATE_RENEWING
:
797 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
801 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
805 case DHCP_STATE_REBINDING
:
807 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
811 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
814 case DHCP_STATE_REBOOTING
:
815 /* start over as we did not receive a timely ack or nak */
816 r
= client_initialize(client
);
820 r
= client_start(client
);
824 log_dhcp_client(client
, "REBOOTED");
828 case DHCP_STATE_INIT
:
829 case DHCP_STATE_INIT_REBOOT
:
830 case DHCP_STATE_SELECTING
:
831 case DHCP_STATE_REQUESTING
:
832 case DHCP_STATE_BOUND
:
834 if (client
->attempt
< 64)
835 client
->attempt
*= 2;
837 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
841 case DHCP_STATE_STOPPED
:
846 next_timeout
+= (random_u32() & 0x1fffff);
848 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
850 r
= sd_event_add_time(client
->event
,
851 &client
->timeout_resend
,
852 clock_boottime_or_monotonic(),
853 next_timeout
, 10 * USEC_PER_MSEC
,
854 client_timeout_resend
, client
);
858 r
= sd_event_source_set_priority(client
->timeout_resend
,
859 client
->event_priority
);
863 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
867 switch (client
->state
) {
868 case DHCP_STATE_INIT
:
869 r
= client_send_discover(client
);
871 client
->state
= DHCP_STATE_SELECTING
;
874 if (client
->attempt
>= 64)
880 case DHCP_STATE_SELECTING
:
881 r
= client_send_discover(client
);
882 if (r
< 0 && client
->attempt
>= 64)
887 case DHCP_STATE_INIT_REBOOT
:
888 case DHCP_STATE_REQUESTING
:
889 case DHCP_STATE_RENEWING
:
890 case DHCP_STATE_REBINDING
:
891 r
= client_send_request(client
);
892 if (r
< 0 && client
->attempt
>= 64)
895 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
896 client
->state
= DHCP_STATE_REBOOTING
;
898 client
->request_sent
= time_now
;
902 case DHCP_STATE_REBOOTING
:
903 case DHCP_STATE_BOUND
:
907 case DHCP_STATE_STOPPED
:
915 client_stop(client
, r
);
917 /* Errors were dealt with when stopping the client, don't spill
918 errors into the event loop handler */
922 static int client_initialize_io_events(sd_dhcp_client
*client
,
923 sd_event_io_handler_t io_callback
) {
927 assert(client
->event
);
929 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
930 client
->fd
, EPOLLIN
, io_callback
,
935 r
= sd_event_source_set_priority(client
->receive_message
,
936 client
->event_priority
);
940 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
946 client_stop(client
, r
);
951 static int client_initialize_time_events(sd_dhcp_client
*client
) {
956 assert(client
->event
);
958 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
960 if (client
->start_delay
) {
961 assert_se(sd_event_now(client
->event
, clock_boottime_or_monotonic(), &usec
) >= 0);
962 usec
+= client
->start_delay
;
965 r
= sd_event_add_time(client
->event
,
966 &client
->timeout_resend
,
967 clock_boottime_or_monotonic(),
969 client_timeout_resend
, client
);
973 r
= sd_event_source_set_priority(client
->timeout_resend
,
974 client
->event_priority
);
978 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
984 client_stop(client
, r
);
990 static int client_initialize_events(sd_dhcp_client
*client
,
991 sd_event_io_handler_t io_callback
) {
992 client_initialize_io_events(client
, io_callback
);
993 client_initialize_time_events(client
);
998 static int client_start_delayed(sd_dhcp_client
*client
) {
1001 assert_return(client
, -EINVAL
);
1002 assert_return(client
->event
, -EINVAL
);
1003 assert_return(client
->index
> 0, -EINVAL
);
1004 assert_return(client
->fd
< 0, -EBUSY
);
1005 assert_return(client
->xid
== 0, -EINVAL
);
1006 assert_return(client
->state
== DHCP_STATE_INIT
||
1007 client
->state
== DHCP_STATE_INIT_REBOOT
, -EBUSY
);
1009 client
->xid
= random_u32();
1011 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1012 client
->xid
, client
->mac_addr
,
1013 client
->mac_addr_len
, client
->arp_type
);
1015 client_stop(client
, r
);
1020 if (client
->state
== DHCP_STATE_INIT
|| client
->state
== DHCP_STATE_INIT_REBOOT
)
1021 client
->start_time
= now(clock_boottime_or_monotonic());
1023 return client_initialize_events(client
, client_receive_message_raw
);
1026 static int client_start(sd_dhcp_client
*client
) {
1027 client
->start_delay
= 0;
1028 return client_start_delayed(client
);
1031 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
,
1033 sd_dhcp_client
*client
= userdata
;
1034 DHCP_CLIENT_DONT_DESTROY(client
);
1036 log_dhcp_client(client
, "EXPIRED");
1038 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1040 /* lease was lost, start over if not freed or stopped in callback */
1041 if (client
->state
!= DHCP_STATE_STOPPED
) {
1042 client_initialize(client
);
1043 client_start(client
);
1049 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1050 sd_dhcp_client
*client
= userdata
;
1051 DHCP_CLIENT_DONT_DESTROY(client
);
1054 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1055 client
->fd
= asynchronous_close(client
->fd
);
1057 client
->state
= DHCP_STATE_REBINDING
;
1058 client
->attempt
= 1;
1060 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1061 client
->xid
, client
->mac_addr
,
1062 client
->mac_addr_len
, client
->arp_type
);
1064 client_stop(client
, r
);
1069 return client_initialize_events(client
, client_receive_message_raw
);
1072 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
,
1074 sd_dhcp_client
*client
= userdata
;
1075 DHCP_CLIENT_DONT_DESTROY(client
);
1077 client
->state
= DHCP_STATE_RENEWING
;
1078 client
->attempt
= 1;
1080 return client_initialize_time_events(client
);
1083 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
,
1085 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1088 r
= dhcp_lease_new(&lease
);
1092 if (client
->client_id_len
) {
1093 r
= dhcp_lease_set_client_id(lease
,
1094 (uint8_t *) &client
->client_id
,
1095 client
->client_id_len
);
1100 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1101 if (r
!= DHCP_OFFER
) {
1102 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1106 lease
->next_server
= offer
->siaddr
;
1107 lease
->address
= offer
->yiaddr
;
1109 if (lease
->address
== 0 ||
1110 lease
->server_address
== 0 ||
1111 lease
->lifetime
== 0) {
1112 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1116 if (!lease
->have_subnet_mask
) {
1117 r
= dhcp_lease_set_default_subnet_mask(lease
);
1119 log_dhcp_client(client
, "received lease lacks subnet "
1120 "mask, and a fallback one can not be "
1121 "generated, ignoring");
1126 sd_dhcp_lease_unref(client
->lease
);
1127 client
->lease
= lease
;
1130 log_dhcp_client(client
, "OFFER");
1135 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
,
1139 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1140 if (r
!= DHCP_FORCERENEW
)
1143 log_dhcp_client(client
, "FORCERENEW");
1148 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
,
1150 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1151 _cleanup_free_
char *error_message
= NULL
;
1154 r
= dhcp_lease_new(&lease
);
1158 if (client
->client_id_len
) {
1159 r
= dhcp_lease_set_client_id(lease
,
1160 (uint8_t *) &client
->client_id
,
1161 client
->client_id_len
);
1166 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1167 if (r
== DHCP_NAK
) {
1168 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1169 return -EADDRNOTAVAIL
;
1172 if (r
!= DHCP_ACK
) {
1173 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1177 lease
->next_server
= ack
->siaddr
;
1179 lease
->address
= ack
->yiaddr
;
1181 if (lease
->address
== INADDR_ANY
||
1182 lease
->server_address
== INADDR_ANY
||
1183 lease
->lifetime
== 0) {
1184 log_dhcp_client(client
, "received lease lacks address, server "
1185 "address or lease lifetime, ignoring");
1189 if (lease
->subnet_mask
== INADDR_ANY
) {
1190 r
= dhcp_lease_set_default_subnet_mask(lease
);
1192 log_dhcp_client(client
, "received lease lacks subnet "
1193 "mask, and a fallback one can not be "
1194 "generated, ignoring");
1199 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1200 if (client
->lease
) {
1201 if (client
->lease
->address
!= lease
->address
||
1202 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1203 client
->lease
->router
!= lease
->router
) {
1204 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1206 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1208 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1211 client
->lease
= lease
;
1214 log_dhcp_client(client
, "ACK");
1219 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1221 assert(client
->request_sent
);
1222 assert(lifetime
> 0);
1229 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1230 + (random_u32() & 0x1fffff);
1233 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1235 uint64_t lifetime_timeout
;
1236 uint64_t t2_timeout
;
1237 uint64_t t1_timeout
;
1238 char time_string
[FORMAT_TIMESPAN_MAX
];
1242 assert(client
->event
);
1243 assert(client
->lease
);
1244 assert(client
->lease
->lifetime
);
1246 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1247 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1248 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1250 /* don't set timers for infinite leases */
1251 if (client
->lease
->lifetime
== 0xffffffff)
1254 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1257 assert(client
->request_sent
<= time_now
);
1259 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1260 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1261 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1262 /* both T1 and T2 are given */
1263 if (client
->lease
->t1
< client
->lease
->t2
&&
1264 client
->lease
->t2
< client
->lease
->lifetime
) {
1265 /* they are both valid */
1266 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1267 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1270 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1271 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1272 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1273 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1275 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1276 /* only T2 is given, and it is valid */
1277 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1278 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1279 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1280 if (t2_timeout
<= t1_timeout
) {
1281 /* the computed T1 would be invalid, so discard T2 */
1282 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1283 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1285 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1286 /* only T1 is given, and it is valid */
1287 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1288 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1289 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1290 if (t2_timeout
<= t1_timeout
) {
1291 /* the computed T2 would be invalid, so discard T1 */
1292 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1293 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1296 /* fall back to the default timeouts */
1297 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1298 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1299 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1300 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1303 /* arm lifetime timeout */
1304 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1305 clock_boottime_or_monotonic(),
1306 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1307 client_timeout_expire
, client
);
1311 r
= sd_event_source_set_priority(client
->timeout_expire
,
1312 client
->event_priority
);
1316 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1320 log_dhcp_client(client
, "lease expires in %s",
1321 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1323 /* don't arm earlier timeouts if this has already expired */
1324 if (lifetime_timeout
<= time_now
)
1327 /* arm T2 timeout */
1328 r
= sd_event_add_time(client
->event
,
1329 &client
->timeout_t2
,
1330 clock_boottime_or_monotonic(),
1333 client_timeout_t2
, client
);
1337 r
= sd_event_source_set_priority(client
->timeout_t2
,
1338 client
->event_priority
);
1342 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1346 log_dhcp_client(client
, "T2 expires in %s",
1347 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1349 /* don't arm earlier timeout if this has already expired */
1350 if (t2_timeout
<= time_now
)
1353 /* arm T1 timeout */
1354 r
= sd_event_add_time(client
->event
,
1355 &client
->timeout_t1
,
1356 clock_boottime_or_monotonic(),
1357 t1_timeout
, 10 * USEC_PER_MSEC
,
1358 client_timeout_t1
, client
);
1362 r
= sd_event_source_set_priority(client
->timeout_t1
,
1363 client
->event_priority
);
1367 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1371 log_dhcp_client(client
, "T1 expires in %s",
1372 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1377 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
,
1379 DHCP_CLIENT_DONT_DESTROY(client
);
1380 char time_string
[FORMAT_TIMESPAN_MAX
];
1381 int r
= 0, notify_event
= 0;
1384 assert(client
->event
);
1387 switch (client
->state
) {
1388 case DHCP_STATE_SELECTING
:
1390 r
= client_handle_offer(client
, message
, len
);
1393 client
->timeout_resend
=
1394 sd_event_source_unref(client
->timeout_resend
);
1396 client
->state
= DHCP_STATE_REQUESTING
;
1397 client
->attempt
= 1;
1399 r
= sd_event_add_time(client
->event
,
1400 &client
->timeout_resend
,
1401 clock_boottime_or_monotonic(),
1403 client_timeout_resend
, client
);
1407 r
= sd_event_source_set_priority(client
->timeout_resend
,
1408 client
->event_priority
);
1412 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1415 } else if (r
== -ENOMSG
)
1416 /* invalid message, let's ignore it */
1421 case DHCP_STATE_REBOOTING
:
1422 case DHCP_STATE_REQUESTING
:
1423 case DHCP_STATE_RENEWING
:
1424 case DHCP_STATE_REBINDING
:
1426 r
= client_handle_ack(client
, message
, len
);
1428 client
->start_delay
= 0;
1429 client
->timeout_resend
=
1430 sd_event_source_unref(client
->timeout_resend
);
1431 client
->receive_message
=
1432 sd_event_source_unref(client
->receive_message
);
1433 client
->fd
= asynchronous_close(client
->fd
);
1435 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1436 DHCP_STATE_REBOOTING
))
1437 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1438 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1441 client
->state
= DHCP_STATE_BOUND
;
1442 client
->attempt
= 1;
1444 client
->last_addr
= client
->lease
->address
;
1446 r
= client_set_lease_timeouts(client
);
1448 log_dhcp_client(client
, "could not set lease timeouts");
1452 r
= dhcp_network_bind_udp_socket(client
->lease
->address
,
1455 log_dhcp_client(client
, "could not bind UDP socket");
1461 client_initialize_io_events(client
, client_receive_message_udp
);
1464 client_notify(client
, notify_event
);
1465 if (client
->state
== DHCP_STATE_STOPPED
)
1469 } else if (r
== -EADDRNOTAVAIL
) {
1470 /* got a NAK, let's restart the client */
1471 client
->timeout_resend
=
1472 sd_event_source_unref(client
->timeout_resend
);
1474 r
= client_initialize(client
);
1478 r
= client_start_delayed(client
);
1482 log_dhcp_client(client
, "REBOOT in %s", format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1483 client
->start_delay
, USEC_PER_SEC
));
1485 client
->start_delay
= CLAMP(client
->start_delay
* 2,
1486 RESTART_AFTER_NAK_MIN_USEC
, RESTART_AFTER_NAK_MAX_USEC
);
1489 } else if (r
== -ENOMSG
)
1490 /* invalid message, let's ignore it */
1495 case DHCP_STATE_BOUND
:
1496 r
= client_handle_forcerenew(client
, message
, len
);
1498 r
= client_timeout_t1(NULL
, 0, client
);
1501 } else if (r
== -ENOMSG
)
1502 /* invalid message, let's ignore it */
1507 case DHCP_STATE_INIT
:
1508 case DHCP_STATE_INIT_REBOOT
:
1512 case DHCP_STATE_STOPPED
:
1519 client_stop(client
, r
);
1524 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
1525 uint32_t revents
, void *userdata
) {
1526 sd_dhcp_client
*client
= userdata
;
1527 _cleanup_free_ DHCPMessage
*message
= NULL
;
1528 const struct ether_addr zero_mac
= { { 0, 0, 0, 0, 0, 0 } };
1529 const struct ether_addr
*expected_chaddr
= NULL
;
1530 uint8_t expected_hlen
= 0;
1531 ssize_t len
, buflen
;
1536 buflen
= next_datagram_size_fd(fd
);
1540 message
= malloc0(buflen
);
1544 len
= read(fd
, message
, buflen
);
1546 if (errno
== EAGAIN
|| errno
== EINTR
)
1549 log_dhcp_client(client
, "Could not receive message from UDP socket: %m");
1551 } else if ((size_t)len
< sizeof(DHCPMessage
)) {
1552 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1556 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1557 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1561 if (message
->op
!= BOOTREPLY
) {
1562 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1566 if (message
->htype
!= client
->arp_type
) {
1567 log_dhcp_client(client
, "Packet type does not match client type");
1571 if (client
->arp_type
== ARPHRD_ETHER
) {
1572 expected_hlen
= ETH_ALEN
;
1573 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1575 /* Non-Ethernet links expect zero chaddr */
1577 expected_chaddr
= &zero_mac
;
1580 if (message
->hlen
!= expected_hlen
) {
1581 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1585 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1586 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1590 if (client
->state
!= DHCP_STATE_BOUND
&&
1591 be32toh(message
->xid
) != client
->xid
) {
1592 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1593 so ignore the xid in this case */
1594 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1595 be32toh(message
->xid
), client
->xid
);
1599 return client_handle_message(client
, message
, len
);
1602 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
1603 uint32_t revents
, void *userdata
) {
1604 sd_dhcp_client
*client
= userdata
;
1605 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1606 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1607 struct iovec iov
= {};
1608 struct msghdr msg
= {
1611 .msg_control
= cmsgbuf
,
1612 .msg_controllen
= sizeof(cmsgbuf
),
1614 struct cmsghdr
*cmsg
;
1615 bool checksum
= true;
1616 ssize_t buflen
, len
;
1622 buflen
= next_datagram_size_fd(fd
);
1626 packet
= malloc0(buflen
);
1630 iov
.iov_base
= packet
;
1631 iov
.iov_len
= buflen
;
1633 len
= recvmsg(fd
, &msg
, 0);
1635 if (errno
== EAGAIN
|| errno
== EINTR
)
1638 log_dhcp_client(client
, "Could not receive message from raw socket: %m");
1641 } else if ((size_t)len
< sizeof(DHCPPacket
))
1644 CMSG_FOREACH(cmsg
, &msg
) {
1645 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1646 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1647 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1648 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1650 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1655 r
= dhcp_packet_verify_headers(packet
, len
, checksum
);
1659 len
-= DHCP_IP_UDP_SIZE
;
1661 return client_handle_message(client
, &packet
->dhcp
, len
);
1664 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1667 assert_return(client
, -EINVAL
);
1669 r
= client_initialize(client
);
1673 if (client
->last_addr
)
1674 client
->state
= DHCP_STATE_INIT_REBOOT
;
1676 r
= client_start(client
);
1678 log_dhcp_client(client
, "STARTED on ifindex %i", client
->index
);
1683 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1684 DHCP_CLIENT_DONT_DESTROY(client
);
1686 assert_return(client
, -EINVAL
);
1688 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1689 client
->state
= DHCP_STATE_STOPPED
;
1694 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
,
1698 assert_return(client
, -EINVAL
);
1699 assert_return(!client
->event
, -EBUSY
);
1702 client
->event
= sd_event_ref(event
);
1704 r
= sd_event_default(&client
->event
);
1709 client
->event_priority
= priority
;
1714 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1715 assert_return(client
, -EINVAL
);
1717 client
->event
= sd_event_unref(client
->event
);
1722 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1726 return client
->event
;
1729 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1734 assert(client
->n_ref
>= 1);
1740 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1745 assert(client
->n_ref
>= 1);
1748 if (client
->n_ref
> 0)
1751 log_dhcp_client(client
, "FREE");
1753 client_initialize(client
);
1755 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1757 sd_dhcp_client_detach_event(client
);
1759 sd_dhcp_lease_unref(client
->lease
);
1761 free(client
->req_opts
);
1762 free(client
->hostname
);
1763 free(client
->vendor_class_identifier
);
1769 int sd_dhcp_client_new(sd_dhcp_client
**ret
) {
1770 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1772 assert_return(ret
, -EINVAL
);
1774 client
= new0(sd_dhcp_client
, 1);
1779 client
->state
= DHCP_STATE_INIT
;
1782 client
->attempt
= 1;
1783 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1785 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1787 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1788 if (!client
->req_opts
)