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 struct sd_dhcp_client
{
52 sd_event_source
*timeout_resend
;
55 union sockaddr_union link
;
56 sd_event_source
*receive_message
;
57 bool request_broadcast
;
59 size_t req_opts_allocated
;
62 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
69 /* 0: Generic (non-LL) (RFC 2132) */
70 uint8_t data
[MAX_CLIENT_ID_LEN
];
73 /* 1: Ethernet Link-Layer (RFC 2132) */
74 uint8_t haddr
[ETH_ALEN
];
77 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
81 /* 255: Node-specific (RFC 4361) */
86 uint8_t data
[MAX_CLIENT_ID_LEN
];
92 char *vendor_class_identifier
;
98 sd_event_source
*timeout_t1
;
99 sd_event_source
*timeout_t2
;
100 sd_event_source
*timeout_expire
;
101 sd_dhcp_client_cb_t cb
;
103 sd_dhcp_lease
*lease
;
106 static const uint8_t default_req_opts
[] = {
107 DHCP_OPTION_SUBNET_MASK
,
109 DHCP_OPTION_HOST_NAME
,
110 DHCP_OPTION_DOMAIN_NAME
,
111 DHCP_OPTION_DOMAIN_NAME_SERVER
,
114 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
115 uint32_t revents
, void *userdata
);
116 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
117 uint32_t revents
, void *userdata
);
118 static void client_stop(sd_dhcp_client
*client
, int error
);
120 int sd_dhcp_client_set_callback(sd_dhcp_client
*client
, sd_dhcp_client_cb_t cb
,
122 assert_return(client
, -EINVAL
);
125 client
->userdata
= userdata
;
130 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
131 assert_return(client
, -EINVAL
);
133 client
->request_broadcast
= !!broadcast
;
138 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
141 assert_return(client
, -EINVAL
);
142 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
143 DHCP_STATE_STOPPED
), -EBUSY
);
146 case DHCP_OPTION_PAD
:
147 case DHCP_OPTION_OVERLOAD
:
148 case DHCP_OPTION_MESSAGE_TYPE
:
149 case DHCP_OPTION_PARAMETER_REQUEST_LIST
:
150 case DHCP_OPTION_END
:
157 for (i
= 0; i
< client
->req_opts_size
; i
++)
158 if (client
->req_opts
[i
] == option
)
161 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
162 client
->req_opts_size
+ 1))
165 client
->req_opts
[client
->req_opts_size
++] = option
;
170 int sd_dhcp_client_set_request_address(sd_dhcp_client
*client
,
171 const struct in_addr
*last_addr
) {
172 assert_return(client
, -EINVAL
);
173 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
174 DHCP_STATE_STOPPED
), -EBUSY
);
177 client
->last_addr
= last_addr
->s_addr
;
179 client
->last_addr
= INADDR_ANY
;
184 int sd_dhcp_client_set_index(sd_dhcp_client
*client
, int interface_index
) {
185 assert_return(client
, -EINVAL
);
186 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
187 DHCP_STATE_STOPPED
), -EBUSY
);
188 assert_return(interface_index
> 0, -EINVAL
);
190 client
->index
= interface_index
;
195 int sd_dhcp_client_set_mac(sd_dhcp_client
*client
, const uint8_t *addr
,
196 size_t addr_len
, uint16_t arp_type
) {
197 DHCP_CLIENT_DONT_DESTROY(client
);
198 bool need_restart
= false;
200 assert_return(client
, -EINVAL
);
201 assert_return(addr
, -EINVAL
);
202 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
203 assert_return(arp_type
> 0, -EINVAL
);
205 if (arp_type
== ARPHRD_ETHER
)
206 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
207 else if (arp_type
== ARPHRD_INFINIBAND
)
208 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
212 if (client
->mac_addr_len
== addr_len
&&
213 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
216 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
217 log_dhcp_client(client
, "Changing MAC address on running DHCP "
218 "client, restarting");
220 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
223 memcpy(&client
->mac_addr
, addr
, addr_len
);
224 client
->mac_addr_len
= addr_len
;
225 client
->arp_type
= arp_type
;
227 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
228 sd_dhcp_client_start(client
);
233 int sd_dhcp_client_get_client_id(sd_dhcp_client
*client
, uint8_t *type
,
234 const uint8_t **data
, size_t *data_len
) {
236 assert_return(client
, -EINVAL
);
237 assert_return(type
, -EINVAL
);
238 assert_return(data
, -EINVAL
);
239 assert_return(data_len
, -EINVAL
);
244 if (client
->client_id_len
) {
245 *type
= client
->client_id
.type
;
246 *data
= client
->client_id
.raw
.data
;
247 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
253 int sd_dhcp_client_set_client_id(sd_dhcp_client
*client
, uint8_t type
,
254 const uint8_t *data
, size_t data_len
) {
255 DHCP_CLIENT_DONT_DESTROY(client
);
256 bool need_restart
= false;
258 assert_return(client
, -EINVAL
);
259 assert_return(data
, -EINVAL
);
260 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
264 if (data_len
!= ETH_ALEN
)
267 case ARPHRD_INFINIBAND
:
268 if (data_len
!= INFINIBAND_ALEN
)
275 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
276 client
->client_id
.type
== type
&&
277 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
280 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
281 log_dhcp_client(client
, "Changing client ID on running DHCP "
282 "client, restarting");
284 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
287 client
->client_id
.type
= type
;
288 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
289 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
291 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
292 sd_dhcp_client_start(client
);
297 int sd_dhcp_client_set_hostname(sd_dhcp_client
*client
,
298 const char *hostname
) {
299 char *new_hostname
= NULL
;
301 assert_return(client
, -EINVAL
);
303 if (!hostname_is_valid(hostname
, false) && !dns_name_is_valid(hostname
))
306 if (streq_ptr(client
->hostname
, hostname
))
310 new_hostname
= strdup(hostname
);
315 free(client
->hostname
);
316 client
->hostname
= new_hostname
;
321 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client
*client
,
323 char *new_vci
= NULL
;
325 assert_return(client
, -EINVAL
);
327 new_vci
= strdup(vci
);
331 free(client
->vendor_class_identifier
);
333 client
->vendor_class_identifier
= new_vci
;
338 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
339 assert_return(client
, -EINVAL
);
340 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
347 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
348 assert_return(client
, -EINVAL
);
349 assert_return(ret
, -EINVAL
);
351 if (client
->state
!= DHCP_STATE_BOUND
&&
352 client
->state
!= DHCP_STATE_RENEWING
&&
353 client
->state
!= DHCP_STATE_REBINDING
)
354 return -EADDRNOTAVAIL
;
356 *ret
= client
->lease
;
361 static void client_notify(sd_dhcp_client
*client
, int event
) {
363 client
->cb(client
, event
, client
->userdata
);
366 static int client_initialize(sd_dhcp_client
*client
) {
367 assert_return(client
, -EINVAL
);
369 client
->receive_message
=
370 sd_event_source_unref(client
->receive_message
);
372 client
->fd
= asynchronous_close(client
->fd
);
374 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
376 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
377 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
378 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
382 client
->state
= DHCP_STATE_INIT
;
385 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
390 static void client_stop(sd_dhcp_client
*client
, int error
) {
394 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
395 else if (error
== SD_DHCP_CLIENT_EVENT_STOP
)
396 log_dhcp_client(client
, "STOPPED");
398 log_dhcp_client(client
, "STOPPED: Unknown event");
400 client_notify(client
, error
);
402 client_initialize(client
);
405 static int client_message_init(sd_dhcp_client
*client
, DHCPPacket
**ret
,
406 uint8_t type
, size_t *_optlen
, size_t *_optoffset
) {
407 _cleanup_free_ DHCPPacket
*packet
;
408 size_t optlen
, optoffset
, size
;
415 assert(client
->start_time
);
419 assert(type
== DHCP_DISCOVER
|| type
== DHCP_REQUEST
);
421 optlen
= DHCP_MIN_OPTIONS_SIZE
;
422 size
= sizeof(DHCPPacket
) + optlen
;
424 packet
= malloc0(size
);
428 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
429 client
->arp_type
, optlen
, &optoffset
);
433 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
434 refuse to issue an DHCP lease if 'secs' is set to zero */
435 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
438 assert(time_now
>= client
->start_time
);
440 /* seconds between sending first and last DISCOVER
441 * must always be strictly positive to deal with broken servers */
442 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
443 packet
->dhcp
.secs
= htobe16(secs
);
445 /* RFC2132 section 4.1
446 A client that cannot receive unicast IP datagrams until its protocol
447 software has been configured with an IP address SHOULD set the
448 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
449 DHCPREQUEST messages that client sends. The BROADCAST bit will
450 provide a hint to the DHCP server and BOOTP relay agent to broadcast
451 any messages to the client on the client's subnet.
453 Note: some interfaces needs this to be enabled, but some networks
454 needs this to be disabled as broadcasts are filteretd, so this
455 needs to be configurable */
456 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
457 packet
->dhcp
.flags
= htobe16(0x8000);
459 /* RFC2132 section 4.1.1:
460 The client MUST include its hardware address in the ’chaddr’ field, if
461 necessary for delivery of DHCP reply messages. Non-Ethernet
462 interfaces will leave 'chaddr' empty and use the client identifier
463 instead (eg, RFC 4390 section 2.1).
465 if (client
->arp_type
== ARPHRD_ETHER
)
466 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
468 /* If no client identifier exists, construct an RFC 4361-compliant one */
469 if (client
->client_id_len
== 0) {
472 client
->client_id
.type
= 255;
474 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
478 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
482 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
485 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
486 Identifier option is not set */
487 if (client
->client_id_len
) {
488 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
489 DHCP_OPTION_CLIENT_IDENTIFIER
,
490 client
->client_id_len
,
496 /* RFC2131 section 3.5:
497 in its initial DHCPDISCOVER or DHCPREQUEST message, a
498 client may provide the server with a list of specific
499 parameters the client is interested in. If the client
500 includes a list of parameters in a DHCPDISCOVER message,
501 it MUST include that list in any subsequent DHCPREQUEST
504 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
505 DHCP_OPTION_PARAMETER_REQUEST_LIST
,
506 client
->req_opts_size
, client
->req_opts
);
510 /* RFC2131 section 3.5:
511 The client SHOULD include the ’maximum DHCP message size’ option to
512 let the server know how large the server may make its DHCP messages.
514 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
515 than the defined default size unless the Maximum Messge Size option
518 RFC3442 "Requirements to Avoid Sizing Constraints":
519 Because a full routing table can be quite large, the standard 576
520 octet maximum size for a DHCP message may be too short to contain
521 some legitimate Classless Static Route options. Because of this,
522 clients implementing the Classless Static Route option SHOULD send a
523 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
524 stack is capable of receiving larger IP datagrams. In this case, the
525 client SHOULD set the value of this option to at least the MTU of the
526 interface that the client is configuring. The client MAY set the
527 value of this option higher, up to the size of the largest UDP packet
528 it is prepared to accept. (Note that the value specified in the
529 Maximum DHCP Message Size option is the total maximum packet size,
530 including IP and UDP headers.)
532 max_size
= htobe16(size
);
533 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
534 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
540 *_optoffset
= optoffset
;
547 static int client_append_fqdn_option(DHCPMessage
*message
, size_t optlen
, size_t *optoffset
,
549 uint8_t buffer
[3 + DHCP_MAX_FQDN_LENGTH
];
552 buffer
[0] = DHCP_FQDN_FLAG_S
| /* Request server to perform A RR DNS updates */
553 DHCP_FQDN_FLAG_E
; /* Canonical wire format */
554 buffer
[1] = 0; /* RCODE1 (deprecated) */
555 buffer
[2] = 0; /* RCODE2 (deprecated) */
557 r
= dns_name_to_wire_format(fqdn
, buffer
+ 3, sizeof(buffer
) - 3, false);
559 r
= dhcp_option_append(message
, optlen
, optoffset
, 0,
560 DHCP_OPTION_FQDN
, 3 + r
, buffer
);
565 static int dhcp_client_send_raw(sd_dhcp_client
*client
, DHCPPacket
*packet
,
567 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, DHCP_PORT_CLIENT
,
568 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
570 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
574 static int client_send_discover(sd_dhcp_client
*client
) {
575 _cleanup_free_ DHCPPacket
*discover
= NULL
;
576 size_t optoffset
, optlen
;
580 assert(client
->state
== DHCP_STATE_INIT
||
581 client
->state
== DHCP_STATE_SELECTING
);
583 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
584 &optlen
, &optoffset
);
588 /* the client may suggest values for the network address
589 and lease time in the DHCPDISCOVER message. The client may include
590 the ’requested IP address’ option to suggest that a particular IP
591 address be assigned, and may include the ’IP address lease time’
592 option to suggest the lease time it would like.
594 if (client
->last_addr
!= INADDR_ANY
) {
595 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
596 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
597 4, &client
->last_addr
);
602 if (client
->hostname
) {
603 /* According to RFC 4702 "clients that send the Client FQDN option in
604 their messages MUST NOT also send the Host Name option". Just send
605 one of the two depending on the hostname type.
607 if (dns_name_is_single_label(client
->hostname
)) {
608 /* it is unclear from RFC 2131 if client should send hostname in
609 DHCPDISCOVER but dhclient does and so we do as well
611 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
612 DHCP_OPTION_HOST_NAME
,
613 strlen(client
->hostname
), client
->hostname
);
615 r
= client_append_fqdn_option(&discover
->dhcp
, optlen
, &optoffset
,
621 if (client
->vendor_class_identifier
) {
622 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
623 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
624 strlen(client
->vendor_class_identifier
),
625 client
->vendor_class_identifier
);
630 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
631 DHCP_OPTION_END
, 0, NULL
);
635 /* We currently ignore:
636 The client SHOULD wait a random time between one and ten seconds to
637 desynchronize the use of DHCP at startup.
639 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
643 log_dhcp_client(client
, "DISCOVER");
648 static int client_send_request(sd_dhcp_client
*client
) {
649 _cleanup_free_ DHCPPacket
*request
= NULL
;
650 size_t optoffset
, optlen
;
653 r
= client_message_init(client
, &request
, DHCP_REQUEST
,
654 &optlen
, &optoffset
);
658 switch (client
->state
) {
659 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
660 SELECTING should be REQUESTING)
663 case DHCP_STATE_REQUESTING
:
664 /* Client inserts the address of the selected server in ’server
665 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
666 filled in with the yiaddr value from the chosen DHCPOFFER.
669 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
670 DHCP_OPTION_SERVER_IDENTIFIER
,
671 4, &client
->lease
->server_address
);
675 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
676 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
677 4, &client
->lease
->address
);
683 case DHCP_STATE_INIT_REBOOT
:
684 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
685 option MUST be filled in with client’s notion of its previously
686 assigned address. ’ciaddr’ MUST be zero.
688 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
689 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
690 4, &client
->last_addr
);
695 case DHCP_STATE_RENEWING
:
696 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
697 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
698 client’s IP address.
702 case DHCP_STATE_REBINDING
:
703 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
704 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
705 client’s IP address.
707 This message MUST be broadcast to the 0xffffffff IP broadcast address.
709 request
->dhcp
.ciaddr
= client
->lease
->address
;
713 case DHCP_STATE_INIT
:
714 case DHCP_STATE_SELECTING
:
715 case DHCP_STATE_REBOOTING
:
716 case DHCP_STATE_BOUND
:
717 case DHCP_STATE_STOPPED
:
721 if (client
->hostname
) {
722 if (dns_name_is_single_label(client
->hostname
))
723 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
724 DHCP_OPTION_HOST_NAME
,
725 strlen(client
->hostname
), client
->hostname
);
727 r
= client_append_fqdn_option(&request
->dhcp
, optlen
, &optoffset
,
733 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
734 DHCP_OPTION_END
, 0, NULL
);
738 if (client
->state
== DHCP_STATE_RENEWING
) {
739 r
= dhcp_network_send_udp_socket(client
->fd
,
740 client
->lease
->server_address
,
743 sizeof(DHCPMessage
) + optoffset
);
745 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
750 switch (client
->state
) {
751 case DHCP_STATE_REQUESTING
:
752 log_dhcp_client(client
, "REQUEST (requesting)");
754 case DHCP_STATE_INIT_REBOOT
:
755 log_dhcp_client(client
, "REQUEST (init-reboot)");
757 case DHCP_STATE_RENEWING
:
758 log_dhcp_client(client
, "REQUEST (renewing)");
760 case DHCP_STATE_REBINDING
:
761 log_dhcp_client(client
, "REQUEST (rebinding)");
764 log_dhcp_client(client
, "REQUEST (invalid)");
771 static int client_start(sd_dhcp_client
*client
);
773 static int client_timeout_resend(sd_event_source
*s
, uint64_t usec
,
775 sd_dhcp_client
*client
= userdata
;
776 DHCP_CLIENT_DONT_DESTROY(client
);
777 usec_t next_timeout
= 0;
784 assert(client
->event
);
786 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
790 switch (client
->state
) {
791 case DHCP_STATE_RENEWING
:
793 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
797 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
801 case DHCP_STATE_REBINDING
:
803 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
807 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
810 case DHCP_STATE_REBOOTING
:
811 /* start over as we did not receive a timely ack or nak */
812 r
= client_initialize(client
);
816 r
= client_start(client
);
820 log_dhcp_client(client
, "REBOOTED");
824 case DHCP_STATE_INIT
:
825 case DHCP_STATE_INIT_REBOOT
:
826 case DHCP_STATE_SELECTING
:
827 case DHCP_STATE_REQUESTING
:
828 case DHCP_STATE_BOUND
:
830 if (client
->attempt
< 64)
831 client
->attempt
*= 2;
833 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
837 case DHCP_STATE_STOPPED
:
842 next_timeout
+= (random_u32() & 0x1fffff);
844 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
846 r
= sd_event_add_time(client
->event
,
847 &client
->timeout_resend
,
848 clock_boottime_or_monotonic(),
849 next_timeout
, 10 * USEC_PER_MSEC
,
850 client_timeout_resend
, client
);
854 r
= sd_event_source_set_priority(client
->timeout_resend
,
855 client
->event_priority
);
859 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
863 switch (client
->state
) {
864 case DHCP_STATE_INIT
:
865 r
= client_send_discover(client
);
867 client
->state
= DHCP_STATE_SELECTING
;
870 if (client
->attempt
>= 64)
876 case DHCP_STATE_SELECTING
:
877 r
= client_send_discover(client
);
878 if (r
< 0 && client
->attempt
>= 64)
883 case DHCP_STATE_INIT_REBOOT
:
884 case DHCP_STATE_REQUESTING
:
885 case DHCP_STATE_RENEWING
:
886 case DHCP_STATE_REBINDING
:
887 r
= client_send_request(client
);
888 if (r
< 0 && client
->attempt
>= 64)
891 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
892 client
->state
= DHCP_STATE_REBOOTING
;
894 client
->request_sent
= time_now
;
898 case DHCP_STATE_REBOOTING
:
899 case DHCP_STATE_BOUND
:
903 case DHCP_STATE_STOPPED
:
911 client_stop(client
, r
);
913 /* Errors were dealt with when stopping the client, don't spill
914 errors into the event loop handler */
918 static int client_initialize_io_events(sd_dhcp_client
*client
,
919 sd_event_io_handler_t io_callback
) {
923 assert(client
->event
);
925 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
926 client
->fd
, EPOLLIN
, io_callback
,
931 r
= sd_event_source_set_priority(client
->receive_message
,
932 client
->event_priority
);
936 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
942 client_stop(client
, r
);
947 static int client_initialize_time_events(sd_dhcp_client
*client
) {
951 assert(client
->event
);
953 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
955 r
= sd_event_add_time(client
->event
,
956 &client
->timeout_resend
,
957 clock_boottime_or_monotonic(),
959 client_timeout_resend
, client
);
963 r
= sd_event_source_set_priority(client
->timeout_resend
,
964 client
->event_priority
);
968 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
974 client_stop(client
, r
);
980 static int client_initialize_events(sd_dhcp_client
*client
,
981 sd_event_io_handler_t io_callback
) {
982 client_initialize_io_events(client
, io_callback
);
983 client_initialize_time_events(client
);
988 static int client_start(sd_dhcp_client
*client
) {
991 assert_return(client
, -EINVAL
);
992 assert_return(client
->event
, -EINVAL
);
993 assert_return(client
->index
> 0, -EINVAL
);
994 assert_return(client
->fd
< 0, -EBUSY
);
995 assert_return(client
->xid
== 0, -EINVAL
);
996 assert_return(client
->state
== DHCP_STATE_INIT
||
997 client
->state
== DHCP_STATE_INIT_REBOOT
, -EBUSY
);
999 client
->xid
= random_u32();
1001 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1002 client
->xid
, client
->mac_addr
,
1003 client
->mac_addr_len
, client
->arp_type
);
1005 client_stop(client
, r
);
1010 if (client
->state
== DHCP_STATE_INIT
|| client
->state
== DHCP_STATE_INIT_REBOOT
)
1011 client
->start_time
= now(clock_boottime_or_monotonic());
1013 return client_initialize_events(client
, client_receive_message_raw
);
1016 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
,
1018 sd_dhcp_client
*client
= userdata
;
1019 DHCP_CLIENT_DONT_DESTROY(client
);
1021 log_dhcp_client(client
, "EXPIRED");
1023 client_notify(client
, SD_DHCP_CLIENT_EVENT_EXPIRED
);
1025 /* lease was lost, start over if not freed or stopped in callback */
1026 if (client
->state
!= DHCP_STATE_STOPPED
) {
1027 client_initialize(client
);
1028 client_start(client
);
1034 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1035 sd_dhcp_client
*client
= userdata
;
1036 DHCP_CLIENT_DONT_DESTROY(client
);
1039 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1040 client
->fd
= asynchronous_close(client
->fd
);
1042 client
->state
= DHCP_STATE_REBINDING
;
1043 client
->attempt
= 1;
1045 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1046 client
->xid
, client
->mac_addr
,
1047 client
->mac_addr_len
, client
->arp_type
);
1049 client_stop(client
, r
);
1054 return client_initialize_events(client
, client_receive_message_raw
);
1057 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
,
1059 sd_dhcp_client
*client
= userdata
;
1060 DHCP_CLIENT_DONT_DESTROY(client
);
1062 client
->state
= DHCP_STATE_RENEWING
;
1063 client
->attempt
= 1;
1065 return client_initialize_time_events(client
);
1068 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
,
1070 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1073 r
= dhcp_lease_new(&lease
);
1077 if (client
->client_id_len
) {
1078 r
= dhcp_lease_set_client_id(lease
,
1079 (uint8_t *) &client
->client_id
,
1080 client
->client_id_len
);
1085 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
, NULL
);
1086 if (r
!= DHCP_OFFER
) {
1087 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1091 lease
->next_server
= offer
->siaddr
;
1092 lease
->address
= offer
->yiaddr
;
1094 if (lease
->address
== 0 ||
1095 lease
->server_address
== 0 ||
1096 lease
->lifetime
== 0) {
1097 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1101 if (!lease
->have_subnet_mask
) {
1102 r
= dhcp_lease_set_default_subnet_mask(lease
);
1104 log_dhcp_client(client
, "received lease lacks subnet "
1105 "mask, and a fallback one can not be "
1106 "generated, ignoring");
1111 sd_dhcp_lease_unref(client
->lease
);
1112 client
->lease
= lease
;
1115 log_dhcp_client(client
, "OFFER");
1120 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
,
1124 r
= dhcp_option_parse(force
, len
, NULL
, NULL
, NULL
);
1125 if (r
!= DHCP_FORCERENEW
)
1128 log_dhcp_client(client
, "FORCERENEW");
1133 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
,
1135 _cleanup_(sd_dhcp_lease_unrefp
) sd_dhcp_lease
*lease
= NULL
;
1136 _cleanup_free_
char *error_message
= NULL
;
1139 r
= dhcp_lease_new(&lease
);
1143 if (client
->client_id_len
) {
1144 r
= dhcp_lease_set_client_id(lease
,
1145 (uint8_t *) &client
->client_id
,
1146 client
->client_id_len
);
1151 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
, &error_message
);
1152 if (r
== DHCP_NAK
) {
1153 log_dhcp_client(client
, "NAK: %s", strna(error_message
));
1154 return -EADDRNOTAVAIL
;
1157 if (r
!= DHCP_ACK
) {
1158 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1162 lease
->next_server
= ack
->siaddr
;
1164 lease
->address
= ack
->yiaddr
;
1166 if (lease
->address
== INADDR_ANY
||
1167 lease
->server_address
== INADDR_ANY
||
1168 lease
->lifetime
== 0) {
1169 log_dhcp_client(client
, "received lease lacks address, server "
1170 "address or lease lifetime, ignoring");
1174 if (lease
->subnet_mask
== INADDR_ANY
) {
1175 r
= dhcp_lease_set_default_subnet_mask(lease
);
1177 log_dhcp_client(client
, "received lease lacks subnet "
1178 "mask, and a fallback one can not be "
1179 "generated, ignoring");
1184 r
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1185 if (client
->lease
) {
1186 if (client
->lease
->address
!= lease
->address
||
1187 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1188 client
->lease
->router
!= lease
->router
) {
1189 r
= SD_DHCP_CLIENT_EVENT_IP_CHANGE
;
1191 r
= SD_DHCP_CLIENT_EVENT_RENEW
;
1193 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1196 client
->lease
= lease
;
1199 log_dhcp_client(client
, "ACK");
1204 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1206 assert(client
->request_sent
);
1207 assert(lifetime
> 0);
1214 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1215 + (random_u32() & 0x1fffff);
1218 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1220 uint64_t lifetime_timeout
;
1221 uint64_t t2_timeout
;
1222 uint64_t t1_timeout
;
1223 char time_string
[FORMAT_TIMESPAN_MAX
];
1227 assert(client
->event
);
1228 assert(client
->lease
);
1229 assert(client
->lease
->lifetime
);
1231 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1232 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1233 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1235 /* don't set timers for infinite leases */
1236 if (client
->lease
->lifetime
== 0xffffffff)
1239 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1242 assert(client
->request_sent
<= time_now
);
1244 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1245 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1246 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1247 /* both T1 and T2 are given */
1248 if (client
->lease
->t1
< client
->lease
->t2
&&
1249 client
->lease
->t2
< client
->lease
->lifetime
) {
1250 /* they are both valid */
1251 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1252 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1255 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1256 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1257 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1258 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1260 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1261 /* only T2 is given, and it is valid */
1262 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1263 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1264 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1265 if (t2_timeout
<= t1_timeout
) {
1266 /* the computed T1 would be invalid, so discard T2 */
1267 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1268 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1270 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1271 /* only T1 is given, and it is valid */
1272 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1273 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1274 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1275 if (t2_timeout
<= t1_timeout
) {
1276 /* the computed T2 would be invalid, so discard T1 */
1277 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1278 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1281 /* fall back to the default timeouts */
1282 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1283 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1284 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1285 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1288 /* arm lifetime timeout */
1289 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1290 clock_boottime_or_monotonic(),
1291 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1292 client_timeout_expire
, client
);
1296 r
= sd_event_source_set_priority(client
->timeout_expire
,
1297 client
->event_priority
);
1301 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1305 log_dhcp_client(client
, "lease expires in %s",
1306 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, lifetime_timeout
- time_now
, USEC_PER_SEC
));
1308 /* don't arm earlier timeouts if this has already expired */
1309 if (lifetime_timeout
<= time_now
)
1312 /* arm T2 timeout */
1313 r
= sd_event_add_time(client
->event
,
1314 &client
->timeout_t2
,
1315 clock_boottime_or_monotonic(),
1318 client_timeout_t2
, client
);
1322 r
= sd_event_source_set_priority(client
->timeout_t2
,
1323 client
->event_priority
);
1327 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1331 log_dhcp_client(client
, "T2 expires in %s",
1332 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t2_timeout
- time_now
, USEC_PER_SEC
));
1334 /* don't arm earlier timeout if this has already expired */
1335 if (t2_timeout
<= time_now
)
1338 /* arm T1 timeout */
1339 r
= sd_event_add_time(client
->event
,
1340 &client
->timeout_t1
,
1341 clock_boottime_or_monotonic(),
1342 t1_timeout
, 10 * USEC_PER_MSEC
,
1343 client_timeout_t1
, client
);
1347 r
= sd_event_source_set_priority(client
->timeout_t1
,
1348 client
->event_priority
);
1352 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1356 log_dhcp_client(client
, "T1 expires in %s",
1357 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, t1_timeout
- time_now
, USEC_PER_SEC
));
1362 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
,
1364 DHCP_CLIENT_DONT_DESTROY(client
);
1365 int r
= 0, notify_event
= 0;
1368 assert(client
->event
);
1371 switch (client
->state
) {
1372 case DHCP_STATE_SELECTING
:
1374 r
= client_handle_offer(client
, message
, len
);
1377 client
->timeout_resend
=
1378 sd_event_source_unref(client
->timeout_resend
);
1380 client
->state
= DHCP_STATE_REQUESTING
;
1381 client
->attempt
= 1;
1383 r
= sd_event_add_time(client
->event
,
1384 &client
->timeout_resend
,
1385 clock_boottime_or_monotonic(),
1387 client_timeout_resend
, client
);
1391 r
= sd_event_source_set_priority(client
->timeout_resend
,
1392 client
->event_priority
);
1396 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1399 } else if (r
== -ENOMSG
)
1400 /* invalid message, let's ignore it */
1405 case DHCP_STATE_REBOOTING
:
1406 case DHCP_STATE_REQUESTING
:
1407 case DHCP_STATE_RENEWING
:
1408 case DHCP_STATE_REBINDING
:
1410 r
= client_handle_ack(client
, message
, len
);
1412 client
->timeout_resend
=
1413 sd_event_source_unref(client
->timeout_resend
);
1414 client
->receive_message
=
1415 sd_event_source_unref(client
->receive_message
);
1416 client
->fd
= asynchronous_close(client
->fd
);
1418 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1419 DHCP_STATE_REBOOTING
))
1420 notify_event
= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
;
1421 else if (r
!= SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
)
1424 client
->state
= DHCP_STATE_BOUND
;
1425 client
->attempt
= 1;
1427 client
->last_addr
= client
->lease
->address
;
1429 r
= client_set_lease_timeouts(client
);
1431 log_dhcp_client(client
, "could not set lease timeouts");
1435 r
= dhcp_network_bind_udp_socket(client
->lease
->address
,
1438 log_dhcp_client(client
, "could not bind UDP socket");
1444 client_initialize_io_events(client
, client_receive_message_udp
);
1447 client_notify(client
, notify_event
);
1448 if (client
->state
== DHCP_STATE_STOPPED
)
1452 } else if (r
== -EADDRNOTAVAIL
) {
1453 /* got a NAK, let's restart the client */
1454 client
->timeout_resend
=
1455 sd_event_source_unref(client
->timeout_resend
);
1457 r
= client_initialize(client
);
1461 r
= client_start(client
);
1465 log_dhcp_client(client
, "REBOOTED");
1468 } else if (r
== -ENOMSG
)
1469 /* invalid message, let's ignore it */
1474 case DHCP_STATE_BOUND
:
1475 r
= client_handle_forcerenew(client
, message
, len
);
1477 r
= client_timeout_t1(NULL
, 0, client
);
1480 } else if (r
== -ENOMSG
)
1481 /* invalid message, let's ignore it */
1486 case DHCP_STATE_INIT
:
1487 case DHCP_STATE_INIT_REBOOT
:
1491 case DHCP_STATE_STOPPED
:
1498 client_stop(client
, r
);
1503 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
1504 uint32_t revents
, void *userdata
) {
1505 sd_dhcp_client
*client
= userdata
;
1506 _cleanup_free_ DHCPMessage
*message
= NULL
;
1507 int buflen
= 0, len
, r
;
1508 const struct ether_addr zero_mac
= { { 0, 0, 0, 0, 0, 0 } };
1509 const struct ether_addr
*expected_chaddr
= NULL
;
1510 uint8_t expected_hlen
= 0;
1515 r
= ioctl(fd
, FIONREAD
, &buflen
);
1518 else if (buflen
< 0)
1519 /* this can't be right */
1522 message
= malloc0(buflen
);
1526 len
= read(fd
, message
, buflen
);
1528 if (errno
== EAGAIN
|| errno
== EINTR
)
1531 log_dhcp_client(client
, "Could not receive message from UDP socket: %m");
1533 } else if ((size_t)len
< sizeof(DHCPMessage
)) {
1534 log_dhcp_client(client
, "Too small to be a DHCP message: ignoring");
1538 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1539 log_dhcp_client(client
, "Not a DHCP message: ignoring");
1543 if (message
->op
!= BOOTREPLY
) {
1544 log_dhcp_client(client
, "Not a BOOTREPLY message: ignoring");
1548 if (message
->htype
!= client
->arp_type
) {
1549 log_dhcp_client(client
, "Packet type does not match client type");
1553 if (client
->arp_type
== ARPHRD_ETHER
) {
1554 expected_hlen
= ETH_ALEN
;
1555 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1557 /* Non-Ethernet links expect zero chaddr */
1559 expected_chaddr
= &zero_mac
;
1562 if (message
->hlen
!= expected_hlen
) {
1563 log_dhcp_client(client
, "Unexpected packet hlen %d", message
->hlen
);
1567 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1568 log_dhcp_client(client
, "Received chaddr does not match expected: ignoring");
1572 if (client
->state
!= DHCP_STATE_BOUND
&&
1573 be32toh(message
->xid
) != client
->xid
) {
1574 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1575 so ignore the xid in this case */
1576 log_dhcp_client(client
, "Received xid (%u) does not match expected (%u): ignoring",
1577 be32toh(message
->xid
), client
->xid
);
1581 return client_handle_message(client
, message
, len
);
1584 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
1585 uint32_t revents
, void *userdata
) {
1586 sd_dhcp_client
*client
= userdata
;
1587 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1588 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1589 struct iovec iov
= {};
1590 struct msghdr msg
= {
1593 .msg_control
= cmsgbuf
,
1594 .msg_controllen
= sizeof(cmsgbuf
),
1596 struct cmsghdr
*cmsg
;
1597 bool checksum
= true;
1598 int buflen
= 0, len
, r
;
1603 r
= ioctl(fd
, FIONREAD
, &buflen
);
1606 else if (buflen
< 0)
1607 /* this can't be right */
1610 packet
= malloc0(buflen
);
1614 iov
.iov_base
= packet
;
1615 iov
.iov_len
= buflen
;
1617 len
= recvmsg(fd
, &msg
, 0);
1619 if (errno
== EAGAIN
|| errno
== EINTR
)
1622 log_dhcp_client(client
, "Could not receive message from raw socket: %m");
1625 } else if ((size_t)len
< sizeof(DHCPPacket
))
1628 CMSG_FOREACH(cmsg
, &msg
) {
1629 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1630 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1631 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1632 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1634 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1639 r
= dhcp_packet_verify_headers(packet
, len
, checksum
);
1643 len
-= DHCP_IP_UDP_SIZE
;
1645 return client_handle_message(client
, &packet
->dhcp
, len
);
1648 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1651 assert_return(client
, -EINVAL
);
1653 r
= client_initialize(client
);
1657 if (client
->last_addr
)
1658 client
->state
= DHCP_STATE_INIT_REBOOT
;
1660 r
= client_start(client
);
1662 log_dhcp_client(client
, "STARTED on ifindex %i", client
->index
);
1667 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1668 DHCP_CLIENT_DONT_DESTROY(client
);
1670 assert_return(client
, -EINVAL
);
1672 client_stop(client
, SD_DHCP_CLIENT_EVENT_STOP
);
1673 client
->state
= DHCP_STATE_STOPPED
;
1678 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
,
1682 assert_return(client
, -EINVAL
);
1683 assert_return(!client
->event
, -EBUSY
);
1686 client
->event
= sd_event_ref(event
);
1688 r
= sd_event_default(&client
->event
);
1693 client
->event_priority
= priority
;
1698 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1699 assert_return(client
, -EINVAL
);
1701 client
->event
= sd_event_unref(client
->event
);
1706 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1710 return client
->event
;
1713 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1718 assert(client
->n_ref
>= 1);
1724 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1729 assert(client
->n_ref
>= 1);
1732 if (client
->n_ref
> 0)
1735 log_dhcp_client(client
, "FREE");
1737 client_initialize(client
);
1739 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1741 sd_dhcp_client_detach_event(client
);
1743 sd_dhcp_lease_unref(client
->lease
);
1745 free(client
->req_opts
);
1746 free(client
->hostname
);
1747 free(client
->vendor_class_identifier
);
1753 int sd_dhcp_client_new(sd_dhcp_client
**ret
) {
1754 _cleanup_(sd_dhcp_client_unrefp
) sd_dhcp_client
*client
= NULL
;
1756 assert_return(ret
, -EINVAL
);
1758 client
= new0(sd_dhcp_client
, 1);
1763 client
->state
= DHCP_STATE_INIT
;
1766 client
->attempt
= 1;
1767 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1769 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1771 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1772 if (!client
->req_opts
)