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/>.
24 #include <net/ethernet.h>
25 #include <net/if_arp.h>
26 #include <linux/if_infiniband.h>
27 #include <sys/ioctl.h>
31 #include "random-util.h"
34 #include "dhcp-protocol.h"
35 #include "dhcp-internal.h"
36 #include "dhcp-lease-internal.h"
37 #include "dhcp-identifier.h"
38 #include "sd-dhcp-client.h"
40 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
41 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
43 struct sd_dhcp_client
{
49 sd_event_source
*timeout_resend
;
52 union sockaddr_union link
;
53 sd_event_source
*receive_message
;
54 bool request_broadcast
;
56 size_t req_opts_allocated
;
59 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
66 /* 0: Generic (non-LL) (RFC 2132) */
67 uint8_t data
[MAX_CLIENT_ID_LEN
];
70 /* 1: Ethernet Link-Layer (RFC 2132) */
71 uint8_t haddr
[ETH_ALEN
];
74 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
78 /* 255: Node-specific (RFC 4361) */
83 uint8_t data
[MAX_CLIENT_ID_LEN
];
89 char *vendor_class_identifier
;
95 sd_event_source
*timeout_t1
;
96 sd_event_source
*timeout_t2
;
97 sd_event_source
*timeout_expire
;
98 sd_dhcp_client_cb_t cb
;
100 sd_dhcp_lease
*lease
;
103 static const uint8_t default_req_opts
[] = {
104 DHCP_OPTION_SUBNET_MASK
,
106 DHCP_OPTION_HOST_NAME
,
107 DHCP_OPTION_DOMAIN_NAME
,
108 DHCP_OPTION_DOMAIN_NAME_SERVER
,
109 DHCP_OPTION_NTP_SERVER
,
112 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
113 uint32_t revents
, void *userdata
);
114 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
115 uint32_t revents
, void *userdata
);
116 static void client_stop(sd_dhcp_client
*client
, int error
);
118 int sd_dhcp_client_set_callback(sd_dhcp_client
*client
, sd_dhcp_client_cb_t cb
,
120 assert_return(client
, -EINVAL
);
123 client
->userdata
= userdata
;
128 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
129 assert_return(client
, -EINVAL
);
131 client
->request_broadcast
= !!broadcast
;
136 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
139 assert_return(client
, -EINVAL
);
140 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
141 DHCP_STATE_STOPPED
), -EBUSY
);
144 case DHCP_OPTION_PAD
:
145 case DHCP_OPTION_OVERLOAD
:
146 case DHCP_OPTION_MESSAGE_TYPE
:
147 case DHCP_OPTION_PARAMETER_REQUEST_LIST
:
148 case DHCP_OPTION_END
:
155 for (i
= 0; i
< client
->req_opts_size
; i
++)
156 if (client
->req_opts
[i
] == option
)
159 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
160 client
->req_opts_size
+ 1))
163 client
->req_opts
[client
->req_opts_size
++] = option
;
168 int sd_dhcp_client_set_request_address(sd_dhcp_client
*client
,
169 const struct in_addr
*last_addr
) {
170 assert_return(client
, -EINVAL
);
171 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
172 DHCP_STATE_STOPPED
), -EBUSY
);
175 client
->last_addr
= last_addr
->s_addr
;
177 client
->last_addr
= INADDR_ANY
;
182 int sd_dhcp_client_set_index(sd_dhcp_client
*client
, int interface_index
) {
183 assert_return(client
, -EINVAL
);
184 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
185 DHCP_STATE_STOPPED
), -EBUSY
);
186 assert_return(interface_index
> 0, -EINVAL
);
188 client
->index
= interface_index
;
193 int sd_dhcp_client_set_mac(sd_dhcp_client
*client
, const uint8_t *addr
,
194 size_t addr_len
, uint16_t arp_type
) {
195 DHCP_CLIENT_DONT_DESTROY(client
);
196 bool need_restart
= false;
198 assert_return(client
, -EINVAL
);
199 assert_return(addr
, -EINVAL
);
200 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
201 assert_return(arp_type
> 0, -EINVAL
);
203 if (arp_type
== ARPHRD_ETHER
)
204 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
205 else if (arp_type
== ARPHRD_INFINIBAND
)
206 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
210 if (client
->mac_addr_len
== addr_len
&&
211 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
214 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
215 log_dhcp_client(client
, "Changing MAC address on running DHCP "
216 "client, restarting");
218 client_stop(client
, DHCP_EVENT_STOP
);
221 memcpy(&client
->mac_addr
, addr
, addr_len
);
222 client
->mac_addr_len
= addr_len
;
223 client
->arp_type
= arp_type
;
225 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
226 sd_dhcp_client_start(client
);
231 int sd_dhcp_client_get_client_id(sd_dhcp_client
*client
, uint8_t *type
,
232 const uint8_t **data
, size_t *data_len
) {
234 assert_return(client
, -EINVAL
);
235 assert_return(type
, -EINVAL
);
236 assert_return(data
, -EINVAL
);
237 assert_return(data_len
, -EINVAL
);
242 if (client
->client_id_len
) {
243 *type
= client
->client_id
.type
;
244 *data
= client
->client_id
.raw
.data
;
245 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
251 int sd_dhcp_client_set_client_id(sd_dhcp_client
*client
, uint8_t type
,
252 const uint8_t *data
, size_t data_len
) {
253 DHCP_CLIENT_DONT_DESTROY(client
);
254 bool need_restart
= false;
256 assert_return(client
, -EINVAL
);
257 assert_return(data
, -EINVAL
);
258 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
262 if (data_len
!= ETH_ALEN
)
265 case ARPHRD_INFINIBAND
:
266 if (data_len
!= INFINIBAND_ALEN
)
273 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
274 client
->client_id
.type
== type
&&
275 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
278 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
279 log_dhcp_client(client
, "Changing client ID on running DHCP "
280 "client, restarting");
282 client_stop(client
, DHCP_EVENT_STOP
);
285 client
->client_id
.type
= type
;
286 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
287 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
289 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
290 sd_dhcp_client_start(client
);
295 int sd_dhcp_client_set_hostname(sd_dhcp_client
*client
,
296 const char *hostname
) {
297 char *new_hostname
= NULL
;
299 assert_return(client
, -EINVAL
);
301 if (streq_ptr(client
->hostname
, hostname
))
305 new_hostname
= strdup(hostname
);
310 free(client
->hostname
);
311 client
->hostname
= new_hostname
;
316 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client
*client
,
318 char *new_vci
= NULL
;
320 assert_return(client
, -EINVAL
);
322 new_vci
= strdup(vci
);
326 free(client
->vendor_class_identifier
);
328 client
->vendor_class_identifier
= new_vci
;
333 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
334 assert_return(client
, -EINVAL
);
335 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
342 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
343 assert_return(client
, -EINVAL
);
344 assert_return(ret
, -EINVAL
);
346 if (client
->state
!= DHCP_STATE_BOUND
&&
347 client
->state
!= DHCP_STATE_RENEWING
&&
348 client
->state
!= DHCP_STATE_REBINDING
)
349 return -EADDRNOTAVAIL
;
351 *ret
= sd_dhcp_lease_ref(client
->lease
);
356 static void client_notify(sd_dhcp_client
*client
, int event
) {
358 client
->cb(client
, event
, client
->userdata
);
361 static int client_initialize(sd_dhcp_client
*client
) {
362 assert_return(client
, -EINVAL
);
364 client
->receive_message
=
365 sd_event_source_unref(client
->receive_message
);
367 client
->fd
= asynchronous_close(client
->fd
);
369 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
371 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
372 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
373 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
377 client
->state
= DHCP_STATE_INIT
;
381 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
386 static void client_stop(sd_dhcp_client
*client
, int error
) {
390 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
391 else if (error
== DHCP_EVENT_STOP
)
392 log_dhcp_client(client
, "STOPPED");
394 log_dhcp_client(client
, "STOPPED: Unknown event");
396 client_notify(client
, error
);
398 client_initialize(client
);
401 static int client_message_init(sd_dhcp_client
*client
, DHCPPacket
**ret
,
402 uint8_t type
, size_t *_optlen
, size_t *_optoffset
) {
403 _cleanup_free_ DHCPPacket
*packet
;
404 size_t optlen
, optoffset
, size
;
411 assert(client
->start_time
);
415 assert(type
== DHCP_DISCOVER
|| type
== DHCP_REQUEST
);
417 optlen
= DHCP_MIN_OPTIONS_SIZE
;
418 size
= sizeof(DHCPPacket
) + optlen
;
420 packet
= malloc0(size
);
424 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
425 client
->arp_type
, optlen
, &optoffset
);
429 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
430 refuse to issue an DHCP lease if 'secs' is set to zero */
431 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
434 assert(time_now
>= client
->start_time
);
436 /* seconds between sending first and last DISCOVER
437 * must always be strictly positive to deal with broken servers */
438 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
439 packet
->dhcp
.secs
= htobe16(secs
);
441 /* RFC2132 section 4.1
442 A client that cannot receive unicast IP datagrams until its protocol
443 software has been configured with an IP address SHOULD set the
444 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
445 DHCPREQUEST messages that client sends. The BROADCAST bit will
446 provide a hint to the DHCP server and BOOTP relay agent to broadcast
447 any messages to the client on the client's subnet.
449 Note: some interfaces needs this to be enabled, but some networks
450 needs this to be disabled as broadcasts are filteretd, so this
451 needs to be configurable */
452 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
453 packet
->dhcp
.flags
= htobe16(0x8000);
455 /* RFC2132 section 4.1.1:
456 The client MUST include its hardware address in the ’chaddr’ field, if
457 necessary for delivery of DHCP reply messages. Non-Ethernet
458 interfaces will leave 'chaddr' empty and use the client identifier
459 instead (eg, RFC 4390 section 2.1).
461 if (client
->arp_type
== ARPHRD_ETHER
)
462 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
464 /* If no client identifier exists, construct an RFC 4361-compliant one */
465 if (client
->client_id_len
== 0) {
468 client
->client_id
.type
= 255;
470 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
474 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
478 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
481 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
482 Identifier option is not set */
483 if (client
->client_id_len
) {
484 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
485 DHCP_OPTION_CLIENT_IDENTIFIER
,
486 client
->client_id_len
,
492 /* RFC2131 section 3.5:
493 in its initial DHCPDISCOVER or DHCPREQUEST message, a
494 client may provide the server with a list of specific
495 parameters the client is interested in. If the client
496 includes a list of parameters in a DHCPDISCOVER message,
497 it MUST include that list in any subsequent DHCPREQUEST
500 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
501 DHCP_OPTION_PARAMETER_REQUEST_LIST
,
502 client
->req_opts_size
, client
->req_opts
);
506 /* RFC2131 section 3.5:
507 The client SHOULD include the ’maximum DHCP message size’ option to
508 let the server know how large the server may make its DHCP messages.
510 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
511 than the defined default size unless the Maximum Messge Size option
514 RFC3442 "Requirements to Avoid Sizing Constraints":
515 Because a full routing table can be quite large, the standard 576
516 octet maximum size for a DHCP message may be too short to contain
517 some legitimate Classless Static Route options. Because of this,
518 clients implementing the Classless Static Route option SHOULD send a
519 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
520 stack is capable of receiving larger IP datagrams. In this case, the
521 client SHOULD set the value of this option to at least the MTU of the
522 interface that the client is configuring. The client MAY set the
523 value of this option higher, up to the size of the largest UDP packet
524 it is prepared to accept. (Note that the value specified in the
525 Maximum DHCP Message Size option is the total maximum packet size,
526 including IP and UDP headers.)
528 max_size
= htobe16(size
);
529 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
530 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
536 *_optoffset
= optoffset
;
543 static int dhcp_client_send_raw(sd_dhcp_client
*client
, DHCPPacket
*packet
,
545 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, DHCP_PORT_CLIENT
,
546 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
548 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
552 static int client_send_discover(sd_dhcp_client
*client
) {
553 _cleanup_free_ DHCPPacket
*discover
= NULL
;
554 size_t optoffset
, optlen
;
558 assert(client
->state
== DHCP_STATE_INIT
||
559 client
->state
== DHCP_STATE_SELECTING
);
561 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
562 &optlen
, &optoffset
);
566 /* the client may suggest values for the network address
567 and lease time in the DHCPDISCOVER message. The client may include
568 the ’requested IP address’ option to suggest that a particular IP
569 address be assigned, and may include the ’IP address lease time’
570 option to suggest the lease time it would like.
572 if (client
->last_addr
!= INADDR_ANY
) {
573 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
574 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
575 4, &client
->last_addr
);
580 /* it is unclear from RFC 2131 if client should send hostname in
581 DHCPDISCOVER but dhclient does and so we do as well
583 if (client
->hostname
) {
584 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
585 DHCP_OPTION_HOST_NAME
,
586 strlen(client
->hostname
), client
->hostname
);
591 if (client
->vendor_class_identifier
) {
592 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
593 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
594 strlen(client
->vendor_class_identifier
),
595 client
->vendor_class_identifier
);
600 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
601 DHCP_OPTION_END
, 0, NULL
);
605 /* We currently ignore:
606 The client SHOULD wait a random time between one and ten seconds to
607 desynchronize the use of DHCP at startup.
609 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
613 log_dhcp_client(client
, "DISCOVER");
618 static int client_send_request(sd_dhcp_client
*client
) {
619 _cleanup_free_ DHCPPacket
*request
= NULL
;
620 size_t optoffset
, optlen
;
623 r
= client_message_init(client
, &request
, DHCP_REQUEST
,
624 &optlen
, &optoffset
);
628 switch (client
->state
) {
629 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
630 SELECTING should be REQUESTING)
633 case DHCP_STATE_REQUESTING
:
634 /* Client inserts the address of the selected server in ’server
635 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
636 filled in with the yiaddr value from the chosen DHCPOFFER.
639 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
640 DHCP_OPTION_SERVER_IDENTIFIER
,
641 4, &client
->lease
->server_address
);
645 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
646 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
647 4, &client
->lease
->address
);
653 case DHCP_STATE_INIT_REBOOT
:
654 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
655 option MUST be filled in with client’s notion of its previously
656 assigned address. ’ciaddr’ MUST be zero.
658 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
659 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
660 4, &client
->last_addr
);
665 case DHCP_STATE_RENEWING
:
666 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
667 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
668 client’s IP address.
672 case DHCP_STATE_REBINDING
:
673 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
674 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
675 client’s IP address.
677 This message MUST be broadcast to the 0xffffffff IP broadcast address.
679 request
->dhcp
.ciaddr
= client
->lease
->address
;
683 case DHCP_STATE_INIT
:
684 case DHCP_STATE_SELECTING
:
685 case DHCP_STATE_REBOOTING
:
686 case DHCP_STATE_BOUND
:
687 case DHCP_STATE_STOPPED
:
691 if (client
->hostname
) {
692 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
693 DHCP_OPTION_HOST_NAME
,
694 strlen(client
->hostname
), client
->hostname
);
699 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
700 DHCP_OPTION_END
, 0, NULL
);
704 if (client
->state
== DHCP_STATE_RENEWING
) {
705 r
= dhcp_network_send_udp_socket(client
->fd
,
706 client
->lease
->server_address
,
709 sizeof(DHCPMessage
) + optoffset
);
711 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
716 switch (client
->state
) {
717 case DHCP_STATE_REQUESTING
:
718 log_dhcp_client(client
, "REQUEST (requesting)");
720 case DHCP_STATE_INIT_REBOOT
:
721 log_dhcp_client(client
, "REQUEST (init-reboot)");
723 case DHCP_STATE_RENEWING
:
724 log_dhcp_client(client
, "REQUEST (renewing)");
726 case DHCP_STATE_REBINDING
:
727 log_dhcp_client(client
, "REQUEST (rebinding)");
730 log_dhcp_client(client
, "REQUEST (invalid)");
737 static int client_start(sd_dhcp_client
*client
);
739 static int client_timeout_resend(sd_event_source
*s
, uint64_t usec
,
741 sd_dhcp_client
*client
= userdata
;
742 DHCP_CLIENT_DONT_DESTROY(client
);
743 usec_t next_timeout
= 0;
750 assert(client
->event
);
752 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
756 switch (client
->state
) {
757 case DHCP_STATE_RENEWING
:
759 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
763 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
767 case DHCP_STATE_REBINDING
:
769 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
773 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
776 case DHCP_STATE_REBOOTING
:
777 /* start over as we did not receive a timely ack or nak */
778 r
= client_initialize(client
);
782 r
= client_start(client
);
786 log_dhcp_client(client
, "REBOOTED");
790 case DHCP_STATE_INIT
:
791 case DHCP_STATE_INIT_REBOOT
:
792 case DHCP_STATE_SELECTING
:
793 case DHCP_STATE_REQUESTING
:
794 case DHCP_STATE_BOUND
:
796 if (client
->attempt
< 64)
797 client
->attempt
*= 2;
799 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
803 case DHCP_STATE_STOPPED
:
808 next_timeout
+= (random_u32() & 0x1fffff);
810 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
812 r
= sd_event_add_time(client
->event
,
813 &client
->timeout_resend
,
814 clock_boottime_or_monotonic(),
815 next_timeout
, 10 * USEC_PER_MSEC
,
816 client_timeout_resend
, client
);
820 r
= sd_event_source_set_priority(client
->timeout_resend
,
821 client
->event_priority
);
825 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
829 switch (client
->state
) {
830 case DHCP_STATE_INIT
:
831 r
= client_send_discover(client
);
833 client
->state
= DHCP_STATE_SELECTING
;
836 if (client
->attempt
>= 64)
842 case DHCP_STATE_SELECTING
:
843 r
= client_send_discover(client
);
844 if (r
< 0 && client
->attempt
>= 64)
849 case DHCP_STATE_INIT_REBOOT
:
850 case DHCP_STATE_REQUESTING
:
851 case DHCP_STATE_RENEWING
:
852 case DHCP_STATE_REBINDING
:
853 r
= client_send_request(client
);
854 if (r
< 0 && client
->attempt
>= 64)
857 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
858 client
->state
= DHCP_STATE_REBOOTING
;
860 client
->request_sent
= time_now
;
864 case DHCP_STATE_REBOOTING
:
865 case DHCP_STATE_BOUND
:
869 case DHCP_STATE_STOPPED
:
877 client_stop(client
, r
);
879 /* Errors were dealt with when stopping the client, don't spill
880 errors into the event loop handler */
884 static int client_initialize_io_events(sd_dhcp_client
*client
,
885 sd_event_io_handler_t io_callback
) {
889 assert(client
->event
);
891 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
892 client
->fd
, EPOLLIN
, io_callback
,
897 r
= sd_event_source_set_priority(client
->receive_message
,
898 client
->event_priority
);
902 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
908 client_stop(client
, r
);
913 static int client_initialize_time_events(sd_dhcp_client
*client
) {
917 assert(client
->event
);
919 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
921 r
= sd_event_add_time(client
->event
,
922 &client
->timeout_resend
,
923 clock_boottime_or_monotonic(),
925 client_timeout_resend
, client
);
929 r
= sd_event_source_set_priority(client
->timeout_resend
,
930 client
->event_priority
);
932 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
938 client_stop(client
, r
);
944 static int client_initialize_events(sd_dhcp_client
*client
,
945 sd_event_io_handler_t io_callback
) {
946 client_initialize_io_events(client
, io_callback
);
947 client_initialize_time_events(client
);
952 static int client_start(sd_dhcp_client
*client
) {
955 assert_return(client
, -EINVAL
);
956 assert_return(client
->event
, -EINVAL
);
957 assert_return(client
->index
> 0, -EINVAL
);
958 assert_return(client
->fd
< 0, -EBUSY
);
959 assert_return(client
->xid
== 0, -EINVAL
);
960 assert_return(client
->state
== DHCP_STATE_INIT
||
961 client
->state
== DHCP_STATE_INIT_REBOOT
, -EBUSY
);
963 client
->xid
= random_u32();
965 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
966 client
->xid
, client
->mac_addr
,
967 client
->mac_addr_len
, client
->arp_type
);
969 client_stop(client
, r
);
974 if (client
->state
== DHCP_STATE_INIT
|| client
->state
== DHCP_STATE_INIT_REBOOT
)
975 client
->start_time
= now(clock_boottime_or_monotonic());
977 return client_initialize_events(client
, client_receive_message_raw
);
980 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
,
982 sd_dhcp_client
*client
= userdata
;
983 DHCP_CLIENT_DONT_DESTROY(client
);
985 log_dhcp_client(client
, "EXPIRED");
987 client_notify(client
, DHCP_EVENT_EXPIRED
);
989 /* lease was lost, start over if not freed or stopped in callback */
990 if (client
->state
!= DHCP_STATE_STOPPED
) {
991 client_initialize(client
);
992 client_start(client
);
998 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
999 sd_dhcp_client
*client
= userdata
;
1000 DHCP_CLIENT_DONT_DESTROY(client
);
1003 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1004 client
->fd
= asynchronous_close(client
->fd
);
1006 client
->state
= DHCP_STATE_REBINDING
;
1007 client
->attempt
= 1;
1009 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1010 client
->xid
, client
->mac_addr
,
1011 client
->mac_addr_len
, client
->arp_type
);
1013 client_stop(client
, r
);
1018 return client_initialize_events(client
, client_receive_message_raw
);
1021 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
,
1023 sd_dhcp_client
*client
= userdata
;
1024 DHCP_CLIENT_DONT_DESTROY(client
);
1026 client
->state
= DHCP_STATE_RENEWING
;
1027 client
->attempt
= 1;
1029 return client_initialize_time_events(client
);
1032 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
,
1034 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
1037 r
= dhcp_lease_new(&lease
);
1041 if (client
->client_id_len
) {
1042 r
= dhcp_lease_set_client_id(lease
,
1043 (uint8_t *) &client
->client_id
,
1044 client
->client_id_len
);
1049 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
);
1050 if (r
!= DHCP_OFFER
) {
1051 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1055 lease
->next_server
= offer
->siaddr
;
1057 lease
->address
= offer
->yiaddr
;
1059 if (lease
->address
== INADDR_ANY
||
1060 lease
->server_address
== INADDR_ANY
||
1061 lease
->lifetime
== 0) {
1062 log_dhcp_client(client
, "received lease lacks address, server "
1063 "address or lease lifetime, ignoring");
1067 if (lease
->subnet_mask
== INADDR_ANY
) {
1068 r
= dhcp_lease_set_default_subnet_mask(lease
);
1070 log_dhcp_client(client
, "received lease lacks subnet "
1071 "mask, and a fallback one can not be "
1072 "generated, ignoring");
1077 sd_dhcp_lease_unref(client
->lease
);
1078 client
->lease
= lease
;
1081 log_dhcp_client(client
, "OFFER");
1086 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
,
1090 r
= dhcp_option_parse(force
, len
, NULL
, NULL
);
1091 if (r
!= DHCP_FORCERENEW
)
1094 log_dhcp_client(client
, "FORCERENEW");
1099 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
,
1101 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
1104 r
= dhcp_lease_new(&lease
);
1108 if (client
->client_id_len
) {
1109 r
= dhcp_lease_set_client_id(lease
,
1110 (uint8_t *) &client
->client_id
,
1111 client
->client_id_len
);
1116 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
);
1117 if (r
== DHCP_NAK
) {
1118 log_dhcp_client(client
, "NAK");
1119 return -EADDRNOTAVAIL
;
1122 if (r
!= DHCP_ACK
) {
1123 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1127 lease
->next_server
= ack
->siaddr
;
1129 lease
->address
= ack
->yiaddr
;
1131 if (lease
->address
== INADDR_ANY
||
1132 lease
->server_address
== INADDR_ANY
||
1133 lease
->lifetime
== 0) {
1134 log_dhcp_client(client
, "received lease lacks address, server "
1135 "address or lease lifetime, ignoring");
1139 if (lease
->subnet_mask
== INADDR_ANY
) {
1140 r
= dhcp_lease_set_default_subnet_mask(lease
);
1142 log_dhcp_client(client
, "received lease lacks subnet "
1143 "mask, and a fallback one can not be "
1144 "generated, ignoring");
1149 r
= DHCP_EVENT_IP_ACQUIRE
;
1150 if (client
->lease
) {
1151 if (client
->lease
->address
!= lease
->address
||
1152 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1153 client
->lease
->router
!= lease
->router
) {
1154 r
= DHCP_EVENT_IP_CHANGE
;
1156 r
= DHCP_EVENT_RENEW
;
1158 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1161 client
->lease
= lease
;
1164 log_dhcp_client(client
, "ACK");
1169 static uint64_t client_compute_timeout(sd_dhcp_client
*client
,
1170 uint32_t lifetime
, double factor
) {
1172 assert(client
->request_sent
);
1175 return client
->request_sent
+ ((lifetime
- 3) * USEC_PER_SEC
* factor
) +
1176 + (random_u32() & 0x1fffff);
1179 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1181 uint64_t lifetime_timeout
;
1182 uint64_t t2_timeout
;
1183 uint64_t t1_timeout
;
1184 char time_string
[FORMAT_TIMESPAN_MAX
];
1188 assert(client
->event
);
1189 assert(client
->lease
);
1190 assert(client
->lease
->lifetime
);
1192 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1193 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1194 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1196 /* don't set timers for infinite leases */
1197 if (client
->lease
->lifetime
== 0xffffffff)
1200 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1203 assert(client
->request_sent
<= time_now
);
1205 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1206 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1207 if (client
->lease
->t1
&& client
->lease
->t2
) {
1208 /* both T1 and T2 are given */
1209 if (client
->lease
->t1
< client
->lease
->t2
&&
1210 client
->lease
->t2
< client
->lease
->lifetime
) {
1211 /* they are both valid */
1212 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1213 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1216 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1217 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1218 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1219 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1221 } else if (client
->lease
->t2
&& client
->lease
->t2
< client
->lease
->lifetime
) {
1222 /* only T2 is given, and it is valid */
1223 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1224 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1225 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1226 if (t2_timeout
<= t1_timeout
) {
1227 /* the computed T1 would be invalid, so discard T2 */
1228 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1229 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1231 } else if (client
->lease
->t1
&& client
->lease
->t1
< client
->lease
->lifetime
) {
1232 /* only T1 is given, and it is valid */
1233 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1234 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1235 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1236 if (t2_timeout
<= t1_timeout
) {
1237 /* the computed T2 would be invalid, so discard T1 */
1238 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1239 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1242 /* fall back to the default timeouts */
1243 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1244 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1245 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1246 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1249 /* arm lifetime timeout */
1250 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1251 clock_boottime_or_monotonic(),
1252 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1253 client_timeout_expire
, client
);
1257 r
= sd_event_source_set_priority(client
->timeout_expire
,
1258 client
->event_priority
);
1262 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1266 log_dhcp_client(client
, "lease expires in %s",
1267 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1268 lifetime_timeout
- time_now
, 0));
1270 /* don't arm earlier timeouts if this has already expired */
1271 if (lifetime_timeout
<= time_now
)
1274 /* arm T2 timeout */
1275 r
= sd_event_add_time(client
->event
,
1276 &client
->timeout_t2
,
1277 clock_boottime_or_monotonic(),
1280 client_timeout_t2
, client
);
1284 r
= sd_event_source_set_priority(client
->timeout_t2
,
1285 client
->event_priority
);
1289 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1293 log_dhcp_client(client
, "T2 expires in %s",
1294 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1295 t2_timeout
- time_now
, 0));
1297 /* don't arm earlier timeout if this has already expired */
1298 if (t2_timeout
<= time_now
)
1301 /* arm T1 timeout */
1302 r
= sd_event_add_time(client
->event
,
1303 &client
->timeout_t1
,
1304 clock_boottime_or_monotonic(),
1305 t1_timeout
, 10 * USEC_PER_MSEC
,
1306 client_timeout_t1
, client
);
1310 r
= sd_event_source_set_priority(client
->timeout_t1
,
1311 client
->event_priority
);
1315 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1319 log_dhcp_client(client
, "T1 expires in %s",
1320 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1321 t1_timeout
- time_now
, 0));
1326 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
,
1328 DHCP_CLIENT_DONT_DESTROY(client
);
1329 int r
= 0, notify_event
= 0;
1332 assert(client
->event
);
1335 switch (client
->state
) {
1336 case DHCP_STATE_SELECTING
:
1338 r
= client_handle_offer(client
, message
, len
);
1341 client
->timeout_resend
=
1342 sd_event_source_unref(client
->timeout_resend
);
1344 client
->state
= DHCP_STATE_REQUESTING
;
1345 client
->attempt
= 1;
1347 r
= sd_event_add_time(client
->event
,
1348 &client
->timeout_resend
,
1349 clock_boottime_or_monotonic(),
1351 client_timeout_resend
, client
);
1355 r
= sd_event_source_set_priority(client
->timeout_resend
,
1356 client
->event_priority
);
1360 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1363 } else if (r
== -ENOMSG
)
1364 /* invalid message, let's ignore it */
1369 case DHCP_STATE_REBOOTING
:
1370 case DHCP_STATE_REQUESTING
:
1371 case DHCP_STATE_RENEWING
:
1372 case DHCP_STATE_REBINDING
:
1374 r
= client_handle_ack(client
, message
, len
);
1376 client
->timeout_resend
=
1377 sd_event_source_unref(client
->timeout_resend
);
1378 client
->receive_message
=
1379 sd_event_source_unref(client
->receive_message
);
1380 client
->fd
= asynchronous_close(client
->fd
);
1382 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1383 DHCP_STATE_REBOOTING
))
1384 notify_event
= DHCP_EVENT_IP_ACQUIRE
;
1385 else if (r
!= DHCP_EVENT_IP_ACQUIRE
)
1388 client
->state
= DHCP_STATE_BOUND
;
1389 client
->attempt
= 1;
1391 client
->last_addr
= client
->lease
->address
;
1393 r
= client_set_lease_timeouts(client
);
1395 log_dhcp_client(client
, "could not set lease timeouts");
1399 r
= dhcp_network_bind_udp_socket(client
->lease
->address
,
1402 log_dhcp_client(client
, "could not bind UDP socket");
1408 client_initialize_io_events(client
, client_receive_message_udp
);
1411 client_notify(client
, notify_event
);
1412 if (client
->state
== DHCP_STATE_STOPPED
)
1416 } else if (r
== -EADDRNOTAVAIL
) {
1417 /* got a NAK, let's restart the client */
1418 client
->timeout_resend
=
1419 sd_event_source_unref(client
->timeout_resend
);
1421 r
= client_initialize(client
);
1425 r
= client_start(client
);
1429 log_dhcp_client(client
, "REBOOTED");
1432 } else if (r
== -ENOMSG
)
1433 /* invalid message, let's ignore it */
1438 case DHCP_STATE_BOUND
:
1439 r
= client_handle_forcerenew(client
, message
, len
);
1441 r
= client_timeout_t1(NULL
, 0, client
);
1444 } else if (r
== -ENOMSG
)
1445 /* invalid message, let's ignore it */
1450 case DHCP_STATE_INIT
:
1451 case DHCP_STATE_INIT_REBOOT
:
1455 case DHCP_STATE_STOPPED
:
1462 client_stop(client
, r
);
1467 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
1468 uint32_t revents
, void *userdata
) {
1469 sd_dhcp_client
*client
= userdata
;
1470 _cleanup_free_ DHCPMessage
*message
= NULL
;
1471 int buflen
= 0, len
, r
;
1472 const struct ether_addr zero_mac
= { { 0, 0, 0, 0, 0, 0 } };
1473 const struct ether_addr
*expected_chaddr
= NULL
;
1474 uint8_t expected_hlen
= 0;
1479 r
= ioctl(fd
, FIONREAD
, &buflen
);
1484 /* this can't be right */
1487 message
= malloc0(buflen
);
1491 len
= read(fd
, message
, buflen
);
1493 log_dhcp_client(client
, "could not receive message from UDP "
1496 } else if ((size_t)len
< sizeof(DHCPMessage
)) {
1497 log_dhcp_client(client
, "too small to be a DHCP message: ignoring");
1501 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1502 log_dhcp_client(client
, "not a DHCP message: ignoring");
1506 if (message
->op
!= BOOTREPLY
) {
1507 log_dhcp_client(client
, "not a BOOTREPLY message: ignoring");
1511 if (message
->htype
!= client
->arp_type
) {
1512 log_dhcp_client(client
, "packet type does not match client type");
1516 if (client
->arp_type
== ARPHRD_ETHER
) {
1517 expected_hlen
= ETH_ALEN
;
1518 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1520 /* Non-ethernet links expect zero chaddr */
1522 expected_chaddr
= &zero_mac
;
1525 if (message
->hlen
!= expected_hlen
) {
1526 log_dhcp_client(client
, "unexpected packet hlen %d", message
->hlen
);
1530 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1531 log_dhcp_client(client
, "received chaddr does not match "
1532 "expected: ignoring");
1536 if (client
->state
!= DHCP_STATE_BOUND
&&
1537 be32toh(message
->xid
) != client
->xid
) {
1538 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1539 so ignore the xid in this case */
1540 log_dhcp_client(client
, "received xid (%u) does not match "
1541 "expected (%u): ignoring",
1542 be32toh(message
->xid
), client
->xid
);
1546 return client_handle_message(client
, message
, len
);
1549 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
1550 uint32_t revents
, void *userdata
) {
1551 sd_dhcp_client
*client
= userdata
;
1552 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1553 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1554 struct iovec iov
= {};
1555 struct msghdr msg
= {
1558 .msg_control
= cmsgbuf
,
1559 .msg_controllen
= sizeof(cmsgbuf
),
1561 struct cmsghdr
*cmsg
;
1562 bool checksum
= true;
1563 int buflen
= 0, len
, r
;
1568 r
= ioctl(fd
, FIONREAD
, &buflen
);
1573 /* this can't be right */
1576 packet
= malloc0(buflen
);
1580 iov
.iov_base
= packet
;
1581 iov
.iov_len
= buflen
;
1583 len
= recvmsg(fd
, &msg
, 0);
1585 log_dhcp_client(client
, "could not receive message from raw "
1588 } else if ((size_t)len
< sizeof(DHCPPacket
))
1591 CMSG_FOREACH(cmsg
, &msg
) {
1592 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1593 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1594 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1595 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1597 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1602 r
= dhcp_packet_verify_headers(packet
, len
, checksum
);
1606 len
-= DHCP_IP_UDP_SIZE
;
1608 return client_handle_message(client
, &packet
->dhcp
, len
);
1611 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1614 assert_return(client
, -EINVAL
);
1616 r
= client_initialize(client
);
1620 if (client
->last_addr
)
1621 client
->state
= DHCP_STATE_INIT_REBOOT
;
1623 r
= client_start(client
);
1625 log_dhcp_client(client
, "STARTED on ifindex %i", client
->index
);
1630 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1631 DHCP_CLIENT_DONT_DESTROY(client
);
1633 assert_return(client
, -EINVAL
);
1635 client_stop(client
, DHCP_EVENT_STOP
);
1636 client
->state
= DHCP_STATE_STOPPED
;
1641 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
,
1645 assert_return(client
, -EINVAL
);
1646 assert_return(!client
->event
, -EBUSY
);
1649 client
->event
= sd_event_ref(event
);
1651 r
= sd_event_default(&client
->event
);
1656 client
->event_priority
= priority
;
1661 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1662 assert_return(client
, -EINVAL
);
1664 client
->event
= sd_event_unref(client
->event
);
1669 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1673 return client
->event
;
1676 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1678 assert_se(REFCNT_INC(client
->n_ref
) >= 2);
1683 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1684 if (client
&& REFCNT_DEC(client
->n_ref
) == 0) {
1685 log_dhcp_client(client
, "FREE");
1687 client_initialize(client
);
1689 client
->receive_message
=
1690 sd_event_source_unref(client
->receive_message
);
1692 sd_dhcp_client_detach_event(client
);
1694 sd_dhcp_lease_unref(client
->lease
);
1696 free(client
->req_opts
);
1697 free(client
->hostname
);
1698 free(client
->vendor_class_identifier
);
1705 int sd_dhcp_client_new(sd_dhcp_client
**ret
) {
1706 _cleanup_dhcp_client_unref_ sd_dhcp_client
*client
= NULL
;
1708 assert_return(ret
, -EINVAL
);
1710 client
= new0(sd_dhcp_client
, 1);
1714 client
->n_ref
= REFCNT_INIT
;
1715 client
->state
= DHCP_STATE_INIT
;
1718 client
->attempt
= 1;
1719 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1721 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1723 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1724 if (!client
->req_opts
)