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>
30 #include "random-util.h"
33 #include "dhcp-protocol.h"
34 #include "dhcp-internal.h"
35 #include "dhcp-lease-internal.h"
36 #include "dhcp-identifier.h"
37 #include "sd-dhcp-client.h"
39 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
40 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
42 struct sd_dhcp_client
{
48 sd_event_source
*timeout_resend
;
51 union sockaddr_union link
;
52 sd_event_source
*receive_message
;
53 bool request_broadcast
;
55 size_t req_opts_allocated
;
58 uint8_t mac_addr
[MAX_MAC_ADDR_LEN
];
65 /* 0: Generic (non-LL) (RFC 2132) */
66 uint8_t data
[MAX_CLIENT_ID_LEN
];
69 /* 1: Ethernet Link-Layer (RFC 2132) */
70 uint8_t haddr
[ETH_ALEN
];
73 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
77 /* 255: Node-specific (RFC 4361) */
82 uint8_t data
[MAX_CLIENT_ID_LEN
];
88 char *vendor_class_identifier
;
94 sd_event_source
*timeout_t1
;
95 sd_event_source
*timeout_t2
;
96 sd_event_source
*timeout_expire
;
97 sd_dhcp_client_cb_t cb
;
102 static const uint8_t default_req_opts
[] = {
103 DHCP_OPTION_SUBNET_MASK
,
105 DHCP_OPTION_HOST_NAME
,
106 DHCP_OPTION_DOMAIN_NAME
,
107 DHCP_OPTION_DOMAIN_NAME_SERVER
,
110 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
111 uint32_t revents
, void *userdata
);
112 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
113 uint32_t revents
, void *userdata
);
114 static void client_stop(sd_dhcp_client
*client
, int error
);
116 int sd_dhcp_client_set_callback(sd_dhcp_client
*client
, sd_dhcp_client_cb_t cb
,
118 assert_return(client
, -EINVAL
);
121 client
->userdata
= userdata
;
126 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client
*client
, int broadcast
) {
127 assert_return(client
, -EINVAL
);
129 client
->request_broadcast
= !!broadcast
;
134 int sd_dhcp_client_set_request_option(sd_dhcp_client
*client
, uint8_t option
) {
137 assert_return(client
, -EINVAL
);
138 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
139 DHCP_STATE_STOPPED
), -EBUSY
);
142 case DHCP_OPTION_PAD
:
143 case DHCP_OPTION_OVERLOAD
:
144 case DHCP_OPTION_MESSAGE_TYPE
:
145 case DHCP_OPTION_PARAMETER_REQUEST_LIST
:
146 case DHCP_OPTION_END
:
153 for (i
= 0; i
< client
->req_opts_size
; i
++)
154 if (client
->req_opts
[i
] == option
)
157 if (!GREEDY_REALLOC(client
->req_opts
, client
->req_opts_allocated
,
158 client
->req_opts_size
+ 1))
161 client
->req_opts
[client
->req_opts_size
++] = option
;
166 int sd_dhcp_client_set_request_address(sd_dhcp_client
*client
,
167 const struct in_addr
*last_addr
) {
168 assert_return(client
, -EINVAL
);
169 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
170 DHCP_STATE_STOPPED
), -EBUSY
);
173 client
->last_addr
= last_addr
->s_addr
;
175 client
->last_addr
= INADDR_ANY
;
180 int sd_dhcp_client_set_index(sd_dhcp_client
*client
, int interface_index
) {
181 assert_return(client
, -EINVAL
);
182 assert_return (IN_SET(client
->state
, DHCP_STATE_INIT
,
183 DHCP_STATE_STOPPED
), -EBUSY
);
184 assert_return(interface_index
> 0, -EINVAL
);
186 client
->index
= interface_index
;
191 int sd_dhcp_client_set_mac(sd_dhcp_client
*client
, const uint8_t *addr
,
192 size_t addr_len
, uint16_t arp_type
) {
193 DHCP_CLIENT_DONT_DESTROY(client
);
194 bool need_restart
= false;
196 assert_return(client
, -EINVAL
);
197 assert_return(addr
, -EINVAL
);
198 assert_return(addr_len
> 0 && addr_len
<= MAX_MAC_ADDR_LEN
, -EINVAL
);
199 assert_return(arp_type
> 0, -EINVAL
);
201 if (arp_type
== ARPHRD_ETHER
)
202 assert_return(addr_len
== ETH_ALEN
, -EINVAL
);
203 else if (arp_type
== ARPHRD_INFINIBAND
)
204 assert_return(addr_len
== INFINIBAND_ALEN
, -EINVAL
);
208 if (client
->mac_addr_len
== addr_len
&&
209 memcmp(&client
->mac_addr
, addr
, addr_len
) == 0)
212 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
213 log_dhcp_client(client
, "Changing MAC address on running DHCP "
214 "client, restarting");
216 client_stop(client
, DHCP_EVENT_STOP
);
219 memcpy(&client
->mac_addr
, addr
, addr_len
);
220 client
->mac_addr_len
= addr_len
;
221 client
->arp_type
= arp_type
;
223 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
224 sd_dhcp_client_start(client
);
229 int sd_dhcp_client_get_client_id(sd_dhcp_client
*client
, uint8_t *type
,
230 const uint8_t **data
, size_t *data_len
) {
232 assert_return(client
, -EINVAL
);
233 assert_return(type
, -EINVAL
);
234 assert_return(data
, -EINVAL
);
235 assert_return(data_len
, -EINVAL
);
240 if (client
->client_id_len
) {
241 *type
= client
->client_id
.type
;
242 *data
= client
->client_id
.raw
.data
;
243 *data_len
= client
->client_id_len
- sizeof(client
->client_id
.type
);
249 int sd_dhcp_client_set_client_id(sd_dhcp_client
*client
, uint8_t type
,
250 const uint8_t *data
, size_t data_len
) {
251 DHCP_CLIENT_DONT_DESTROY(client
);
252 bool need_restart
= false;
254 assert_return(client
, -EINVAL
);
255 assert_return(data
, -EINVAL
);
256 assert_return(data_len
> 0 && data_len
<= MAX_CLIENT_ID_LEN
, -EINVAL
);
260 if (data_len
!= ETH_ALEN
)
263 case ARPHRD_INFINIBAND
:
264 if (data_len
!= INFINIBAND_ALEN
)
271 if (client
->client_id_len
== data_len
+ sizeof(client
->client_id
.type
) &&
272 client
->client_id
.type
== type
&&
273 memcmp(&client
->client_id
.raw
.data
, data
, data_len
) == 0)
276 if (!IN_SET(client
->state
, DHCP_STATE_INIT
, DHCP_STATE_STOPPED
)) {
277 log_dhcp_client(client
, "Changing client ID on running DHCP "
278 "client, restarting");
280 client_stop(client
, DHCP_EVENT_STOP
);
283 client
->client_id
.type
= type
;
284 memcpy(&client
->client_id
.raw
.data
, data
, data_len
);
285 client
->client_id_len
= data_len
+ sizeof (client
->client_id
.type
);
287 if (need_restart
&& client
->state
!= DHCP_STATE_STOPPED
)
288 sd_dhcp_client_start(client
);
293 int sd_dhcp_client_set_hostname(sd_dhcp_client
*client
,
294 const char *hostname
) {
295 char *new_hostname
= NULL
;
297 assert_return(client
, -EINVAL
);
299 if (streq_ptr(client
->hostname
, hostname
))
303 new_hostname
= strdup(hostname
);
308 free(client
->hostname
);
309 client
->hostname
= new_hostname
;
314 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client
*client
,
316 char *new_vci
= NULL
;
318 assert_return(client
, -EINVAL
);
320 new_vci
= strdup(vci
);
324 free(client
->vendor_class_identifier
);
326 client
->vendor_class_identifier
= new_vci
;
331 int sd_dhcp_client_set_mtu(sd_dhcp_client
*client
, uint32_t mtu
) {
332 assert_return(client
, -EINVAL
);
333 assert_return(mtu
>= DHCP_DEFAULT_MIN_SIZE
, -ERANGE
);
340 int sd_dhcp_client_get_lease(sd_dhcp_client
*client
, sd_dhcp_lease
**ret
) {
341 assert_return(client
, -EINVAL
);
342 assert_return(ret
, -EINVAL
);
344 if (client
->state
!= DHCP_STATE_BOUND
&&
345 client
->state
!= DHCP_STATE_RENEWING
&&
346 client
->state
!= DHCP_STATE_REBINDING
)
347 return -EADDRNOTAVAIL
;
349 *ret
= client
->lease
;
354 static void client_notify(sd_dhcp_client
*client
, int event
) {
356 client
->cb(client
, event
, client
->userdata
);
359 static int client_initialize(sd_dhcp_client
*client
) {
360 assert_return(client
, -EINVAL
);
362 client
->receive_message
=
363 sd_event_source_unref(client
->receive_message
);
365 client
->fd
= asynchronous_close(client
->fd
);
367 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
369 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
370 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
371 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
375 client
->state
= DHCP_STATE_INIT
;
378 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
383 static void client_stop(sd_dhcp_client
*client
, int error
) {
387 log_dhcp_client(client
, "STOPPED: %s", strerror(-error
));
388 else if (error
== DHCP_EVENT_STOP
)
389 log_dhcp_client(client
, "STOPPED");
391 log_dhcp_client(client
, "STOPPED: Unknown event");
393 client_notify(client
, error
);
395 client_initialize(client
);
398 static int client_message_init(sd_dhcp_client
*client
, DHCPPacket
**ret
,
399 uint8_t type
, size_t *_optlen
, size_t *_optoffset
) {
400 _cleanup_free_ DHCPPacket
*packet
;
401 size_t optlen
, optoffset
, size
;
408 assert(client
->start_time
);
412 assert(type
== DHCP_DISCOVER
|| type
== DHCP_REQUEST
);
414 optlen
= DHCP_MIN_OPTIONS_SIZE
;
415 size
= sizeof(DHCPPacket
) + optlen
;
417 packet
= malloc0(size
);
421 r
= dhcp_message_init(&packet
->dhcp
, BOOTREQUEST
, client
->xid
, type
,
422 client
->arp_type
, optlen
, &optoffset
);
426 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
427 refuse to issue an DHCP lease if 'secs' is set to zero */
428 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
431 assert(time_now
>= client
->start_time
);
433 /* seconds between sending first and last DISCOVER
434 * must always be strictly positive to deal with broken servers */
435 secs
= ((time_now
- client
->start_time
) / USEC_PER_SEC
) ? : 1;
436 packet
->dhcp
.secs
= htobe16(secs
);
438 /* RFC2132 section 4.1
439 A client that cannot receive unicast IP datagrams until its protocol
440 software has been configured with an IP address SHOULD set the
441 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
442 DHCPREQUEST messages that client sends. The BROADCAST bit will
443 provide a hint to the DHCP server and BOOTP relay agent to broadcast
444 any messages to the client on the client's subnet.
446 Note: some interfaces needs this to be enabled, but some networks
447 needs this to be disabled as broadcasts are filteretd, so this
448 needs to be configurable */
449 if (client
->request_broadcast
|| client
->arp_type
!= ARPHRD_ETHER
)
450 packet
->dhcp
.flags
= htobe16(0x8000);
452 /* RFC2132 section 4.1.1:
453 The client MUST include its hardware address in the ’chaddr’ field, if
454 necessary for delivery of DHCP reply messages. Non-Ethernet
455 interfaces will leave 'chaddr' empty and use the client identifier
456 instead (eg, RFC 4390 section 2.1).
458 if (client
->arp_type
== ARPHRD_ETHER
)
459 memcpy(&packet
->dhcp
.chaddr
, &client
->mac_addr
, ETH_ALEN
);
461 /* If no client identifier exists, construct an RFC 4361-compliant one */
462 if (client
->client_id_len
== 0) {
465 client
->client_id
.type
= 255;
467 r
= dhcp_identifier_set_iaid(client
->index
, client
->mac_addr
, client
->mac_addr_len
, &client
->client_id
.ns
.iaid
);
471 r
= dhcp_identifier_set_duid_en(&client
->client_id
.ns
.duid
, &duid_len
);
475 client
->client_id_len
= sizeof(client
->client_id
.type
) + sizeof(client
->client_id
.ns
.iaid
) + duid_len
;
478 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
479 Identifier option is not set */
480 if (client
->client_id_len
) {
481 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
482 DHCP_OPTION_CLIENT_IDENTIFIER
,
483 client
->client_id_len
,
489 /* RFC2131 section 3.5:
490 in its initial DHCPDISCOVER or DHCPREQUEST message, a
491 client may provide the server with a list of specific
492 parameters the client is interested in. If the client
493 includes a list of parameters in a DHCPDISCOVER message,
494 it MUST include that list in any subsequent DHCPREQUEST
497 r
= dhcp_option_append(&packet
->dhcp
, optlen
, &optoffset
, 0,
498 DHCP_OPTION_PARAMETER_REQUEST_LIST
,
499 client
->req_opts_size
, client
->req_opts
);
503 /* RFC2131 section 3.5:
504 The client SHOULD include the ’maximum DHCP message size’ option to
505 let the server know how large the server may make its DHCP messages.
507 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
508 than the defined default size unless the Maximum Messge Size option
511 RFC3442 "Requirements to Avoid Sizing Constraints":
512 Because a full routing table can be quite large, the standard 576
513 octet maximum size for a DHCP message may be too short to contain
514 some legitimate Classless Static Route options. Because of this,
515 clients implementing the Classless Static Route option SHOULD send a
516 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
517 stack is capable of receiving larger IP datagrams. In this case, the
518 client SHOULD set the value of this option to at least the MTU of the
519 interface that the client is configuring. The client MAY set the
520 value of this option higher, up to the size of the largest UDP packet
521 it is prepared to accept. (Note that the value specified in the
522 Maximum DHCP Message Size option is the total maximum packet size,
523 including IP and UDP headers.)
525 max_size
= htobe16(size
);
526 r
= dhcp_option_append(&packet
->dhcp
, client
->mtu
, &optoffset
, 0,
527 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
,
533 *_optoffset
= optoffset
;
540 static int dhcp_client_send_raw(sd_dhcp_client
*client
, DHCPPacket
*packet
,
542 dhcp_packet_append_ip_headers(packet
, INADDR_ANY
, DHCP_PORT_CLIENT
,
543 INADDR_BROADCAST
, DHCP_PORT_SERVER
, len
);
545 return dhcp_network_send_raw_socket(client
->fd
, &client
->link
,
549 static int client_send_discover(sd_dhcp_client
*client
) {
550 _cleanup_free_ DHCPPacket
*discover
= NULL
;
551 size_t optoffset
, optlen
;
555 assert(client
->state
== DHCP_STATE_INIT
||
556 client
->state
== DHCP_STATE_SELECTING
);
558 r
= client_message_init(client
, &discover
, DHCP_DISCOVER
,
559 &optlen
, &optoffset
);
563 /* the client may suggest values for the network address
564 and lease time in the DHCPDISCOVER message. The client may include
565 the ’requested IP address’ option to suggest that a particular IP
566 address be assigned, and may include the ’IP address lease time’
567 option to suggest the lease time it would like.
569 if (client
->last_addr
!= INADDR_ANY
) {
570 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
571 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
572 4, &client
->last_addr
);
577 /* it is unclear from RFC 2131 if client should send hostname in
578 DHCPDISCOVER but dhclient does and so we do as well
580 if (client
->hostname
) {
581 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
582 DHCP_OPTION_HOST_NAME
,
583 strlen(client
->hostname
), client
->hostname
);
588 if (client
->vendor_class_identifier
) {
589 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
590 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER
,
591 strlen(client
->vendor_class_identifier
),
592 client
->vendor_class_identifier
);
597 r
= dhcp_option_append(&discover
->dhcp
, optlen
, &optoffset
, 0,
598 DHCP_OPTION_END
, 0, NULL
);
602 /* We currently ignore:
603 The client SHOULD wait a random time between one and ten seconds to
604 desynchronize the use of DHCP at startup.
606 r
= dhcp_client_send_raw(client
, discover
, sizeof(DHCPPacket
) + optoffset
);
610 log_dhcp_client(client
, "DISCOVER");
615 static int client_send_request(sd_dhcp_client
*client
) {
616 _cleanup_free_ DHCPPacket
*request
= NULL
;
617 size_t optoffset
, optlen
;
620 r
= client_message_init(client
, &request
, DHCP_REQUEST
,
621 &optlen
, &optoffset
);
625 switch (client
->state
) {
626 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
627 SELECTING should be REQUESTING)
630 case DHCP_STATE_REQUESTING
:
631 /* Client inserts the address of the selected server in ’server
632 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
633 filled in with the yiaddr value from the chosen DHCPOFFER.
636 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
637 DHCP_OPTION_SERVER_IDENTIFIER
,
638 4, &client
->lease
->server_address
);
642 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
643 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
644 4, &client
->lease
->address
);
650 case DHCP_STATE_INIT_REBOOT
:
651 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
652 option MUST be filled in with client’s notion of its previously
653 assigned address. ’ciaddr’ MUST be zero.
655 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
656 DHCP_OPTION_REQUESTED_IP_ADDRESS
,
657 4, &client
->last_addr
);
662 case DHCP_STATE_RENEWING
:
663 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
664 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
665 client’s IP address.
669 case DHCP_STATE_REBINDING
:
670 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
671 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
672 client’s IP address.
674 This message MUST be broadcast to the 0xffffffff IP broadcast address.
676 request
->dhcp
.ciaddr
= client
->lease
->address
;
680 case DHCP_STATE_INIT
:
681 case DHCP_STATE_SELECTING
:
682 case DHCP_STATE_REBOOTING
:
683 case DHCP_STATE_BOUND
:
684 case DHCP_STATE_STOPPED
:
688 if (client
->hostname
) {
689 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
690 DHCP_OPTION_HOST_NAME
,
691 strlen(client
->hostname
), client
->hostname
);
696 r
= dhcp_option_append(&request
->dhcp
, optlen
, &optoffset
, 0,
697 DHCP_OPTION_END
, 0, NULL
);
701 if (client
->state
== DHCP_STATE_RENEWING
) {
702 r
= dhcp_network_send_udp_socket(client
->fd
,
703 client
->lease
->server_address
,
706 sizeof(DHCPMessage
) + optoffset
);
708 r
= dhcp_client_send_raw(client
, request
, sizeof(DHCPPacket
) + optoffset
);
713 switch (client
->state
) {
714 case DHCP_STATE_REQUESTING
:
715 log_dhcp_client(client
, "REQUEST (requesting)");
717 case DHCP_STATE_INIT_REBOOT
:
718 log_dhcp_client(client
, "REQUEST (init-reboot)");
720 case DHCP_STATE_RENEWING
:
721 log_dhcp_client(client
, "REQUEST (renewing)");
723 case DHCP_STATE_REBINDING
:
724 log_dhcp_client(client
, "REQUEST (rebinding)");
727 log_dhcp_client(client
, "REQUEST (invalid)");
734 static int client_start(sd_dhcp_client
*client
);
736 static int client_timeout_resend(sd_event_source
*s
, uint64_t usec
,
738 sd_dhcp_client
*client
= userdata
;
739 DHCP_CLIENT_DONT_DESTROY(client
);
740 usec_t next_timeout
= 0;
747 assert(client
->event
);
749 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
753 switch (client
->state
) {
754 case DHCP_STATE_RENEWING
:
756 time_left
= (client
->lease
->t2
- client
->lease
->t1
) / 2;
760 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
764 case DHCP_STATE_REBINDING
:
766 time_left
= (client
->lease
->lifetime
- client
->lease
->t2
) / 2;
770 next_timeout
= time_now
+ time_left
* USEC_PER_SEC
;
773 case DHCP_STATE_REBOOTING
:
774 /* start over as we did not receive a timely ack or nak */
775 r
= client_initialize(client
);
779 r
= client_start(client
);
783 log_dhcp_client(client
, "REBOOTED");
787 case DHCP_STATE_INIT
:
788 case DHCP_STATE_INIT_REBOOT
:
789 case DHCP_STATE_SELECTING
:
790 case DHCP_STATE_REQUESTING
:
791 case DHCP_STATE_BOUND
:
793 if (client
->attempt
< 64)
794 client
->attempt
*= 2;
796 next_timeout
= time_now
+ (client
->attempt
- 1) * USEC_PER_SEC
;
800 case DHCP_STATE_STOPPED
:
805 next_timeout
+= (random_u32() & 0x1fffff);
807 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
809 r
= sd_event_add_time(client
->event
,
810 &client
->timeout_resend
,
811 clock_boottime_or_monotonic(),
812 next_timeout
, 10 * USEC_PER_MSEC
,
813 client_timeout_resend
, client
);
817 r
= sd_event_source_set_priority(client
->timeout_resend
,
818 client
->event_priority
);
822 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
826 switch (client
->state
) {
827 case DHCP_STATE_INIT
:
828 r
= client_send_discover(client
);
830 client
->state
= DHCP_STATE_SELECTING
;
833 if (client
->attempt
>= 64)
839 case DHCP_STATE_SELECTING
:
840 r
= client_send_discover(client
);
841 if (r
< 0 && client
->attempt
>= 64)
846 case DHCP_STATE_INIT_REBOOT
:
847 case DHCP_STATE_REQUESTING
:
848 case DHCP_STATE_RENEWING
:
849 case DHCP_STATE_REBINDING
:
850 r
= client_send_request(client
);
851 if (r
< 0 && client
->attempt
>= 64)
854 if (client
->state
== DHCP_STATE_INIT_REBOOT
)
855 client
->state
= DHCP_STATE_REBOOTING
;
857 client
->request_sent
= time_now
;
861 case DHCP_STATE_REBOOTING
:
862 case DHCP_STATE_BOUND
:
866 case DHCP_STATE_STOPPED
:
874 client_stop(client
, r
);
876 /* Errors were dealt with when stopping the client, don't spill
877 errors into the event loop handler */
881 static int client_initialize_io_events(sd_dhcp_client
*client
,
882 sd_event_io_handler_t io_callback
) {
886 assert(client
->event
);
888 r
= sd_event_add_io(client
->event
, &client
->receive_message
,
889 client
->fd
, EPOLLIN
, io_callback
,
894 r
= sd_event_source_set_priority(client
->receive_message
,
895 client
->event_priority
);
899 r
= sd_event_source_set_description(client
->receive_message
, "dhcp4-receive-message");
905 client_stop(client
, r
);
910 static int client_initialize_time_events(sd_dhcp_client
*client
) {
914 assert(client
->event
);
916 client
->timeout_resend
= sd_event_source_unref(client
->timeout_resend
);
918 r
= sd_event_add_time(client
->event
,
919 &client
->timeout_resend
,
920 clock_boottime_or_monotonic(),
922 client_timeout_resend
, client
);
926 r
= sd_event_source_set_priority(client
->timeout_resend
,
927 client
->event_priority
);
931 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
937 client_stop(client
, r
);
943 static int client_initialize_events(sd_dhcp_client
*client
,
944 sd_event_io_handler_t io_callback
) {
945 client_initialize_io_events(client
, io_callback
);
946 client_initialize_time_events(client
);
951 static int client_start(sd_dhcp_client
*client
) {
954 assert_return(client
, -EINVAL
);
955 assert_return(client
->event
, -EINVAL
);
956 assert_return(client
->index
> 0, -EINVAL
);
957 assert_return(client
->fd
< 0, -EBUSY
);
958 assert_return(client
->xid
== 0, -EINVAL
);
959 assert_return(client
->state
== DHCP_STATE_INIT
||
960 client
->state
== DHCP_STATE_INIT_REBOOT
, -EBUSY
);
962 client
->xid
= random_u32();
964 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
965 client
->xid
, client
->mac_addr
,
966 client
->mac_addr_len
, client
->arp_type
);
968 client_stop(client
, r
);
973 if (client
->state
== DHCP_STATE_INIT
|| client
->state
== DHCP_STATE_INIT_REBOOT
)
974 client
->start_time
= now(clock_boottime_or_monotonic());
976 return client_initialize_events(client
, client_receive_message_raw
);
979 static int client_timeout_expire(sd_event_source
*s
, uint64_t usec
,
981 sd_dhcp_client
*client
= userdata
;
982 DHCP_CLIENT_DONT_DESTROY(client
);
984 log_dhcp_client(client
, "EXPIRED");
986 client_notify(client
, DHCP_EVENT_EXPIRED
);
988 /* lease was lost, start over if not freed or stopped in callback */
989 if (client
->state
!= DHCP_STATE_STOPPED
) {
990 client_initialize(client
);
991 client_start(client
);
997 static int client_timeout_t2(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
998 sd_dhcp_client
*client
= userdata
;
999 DHCP_CLIENT_DONT_DESTROY(client
);
1002 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1003 client
->fd
= asynchronous_close(client
->fd
);
1005 client
->state
= DHCP_STATE_REBINDING
;
1006 client
->attempt
= 1;
1008 r
= dhcp_network_bind_raw_socket(client
->index
, &client
->link
,
1009 client
->xid
, client
->mac_addr
,
1010 client
->mac_addr_len
, client
->arp_type
);
1012 client_stop(client
, r
);
1017 return client_initialize_events(client
, client_receive_message_raw
);
1020 static int client_timeout_t1(sd_event_source
*s
, uint64_t usec
,
1022 sd_dhcp_client
*client
= userdata
;
1023 DHCP_CLIENT_DONT_DESTROY(client
);
1025 client
->state
= DHCP_STATE_RENEWING
;
1026 client
->attempt
= 1;
1028 return client_initialize_time_events(client
);
1031 static int client_handle_offer(sd_dhcp_client
*client
, DHCPMessage
*offer
,
1033 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
1036 r
= dhcp_lease_new(&lease
);
1040 if (client
->client_id_len
) {
1041 r
= dhcp_lease_set_client_id(lease
,
1042 (uint8_t *) &client
->client_id
,
1043 client
->client_id_len
);
1048 r
= dhcp_option_parse(offer
, len
, dhcp_lease_parse_options
, lease
);
1049 if (r
!= DHCP_OFFER
) {
1050 log_dhcp_client(client
, "received message was not an OFFER, ignoring");
1054 lease
->next_server
= offer
->siaddr
;
1055 lease
->address
= offer
->yiaddr
;
1057 if (lease
->address
== 0 ||
1058 lease
->server_address
== 0 ||
1059 lease
->lifetime
== 0) {
1060 log_dhcp_client(client
, "received lease lacks address, server address or lease lifetime, ignoring");
1064 if (!lease
->have_subnet_mask
) {
1065 r
= dhcp_lease_set_default_subnet_mask(lease
);
1067 log_dhcp_client(client
, "received lease lacks subnet "
1068 "mask, and a fallback one can not be "
1069 "generated, ignoring");
1074 sd_dhcp_lease_unref(client
->lease
);
1075 client
->lease
= lease
;
1078 log_dhcp_client(client
, "OFFER");
1083 static int client_handle_forcerenew(sd_dhcp_client
*client
, DHCPMessage
*force
,
1087 r
= dhcp_option_parse(force
, len
, NULL
, NULL
);
1088 if (r
!= DHCP_FORCERENEW
)
1091 log_dhcp_client(client
, "FORCERENEW");
1096 static int client_handle_ack(sd_dhcp_client
*client
, DHCPMessage
*ack
,
1098 _cleanup_dhcp_lease_unref_ sd_dhcp_lease
*lease
= NULL
;
1101 r
= dhcp_lease_new(&lease
);
1105 if (client
->client_id_len
) {
1106 r
= dhcp_lease_set_client_id(lease
,
1107 (uint8_t *) &client
->client_id
,
1108 client
->client_id_len
);
1113 r
= dhcp_option_parse(ack
, len
, dhcp_lease_parse_options
, lease
);
1114 if (r
== DHCP_NAK
) {
1115 log_dhcp_client(client
, "NAK");
1116 return -EADDRNOTAVAIL
;
1119 if (r
!= DHCP_ACK
) {
1120 log_dhcp_client(client
, "received message was not an ACK, ignoring");
1124 lease
->next_server
= ack
->siaddr
;
1126 lease
->address
= ack
->yiaddr
;
1128 if (lease
->address
== INADDR_ANY
||
1129 lease
->server_address
== INADDR_ANY
||
1130 lease
->lifetime
== 0) {
1131 log_dhcp_client(client
, "received lease lacks address, server "
1132 "address or lease lifetime, ignoring");
1136 if (lease
->subnet_mask
== INADDR_ANY
) {
1137 r
= dhcp_lease_set_default_subnet_mask(lease
);
1139 log_dhcp_client(client
, "received lease lacks subnet "
1140 "mask, and a fallback one can not be "
1141 "generated, ignoring");
1146 r
= DHCP_EVENT_IP_ACQUIRE
;
1147 if (client
->lease
) {
1148 if (client
->lease
->address
!= lease
->address
||
1149 client
->lease
->subnet_mask
!= lease
->subnet_mask
||
1150 client
->lease
->router
!= lease
->router
) {
1151 r
= DHCP_EVENT_IP_CHANGE
;
1153 r
= DHCP_EVENT_RENEW
;
1155 client
->lease
= sd_dhcp_lease_unref(client
->lease
);
1158 client
->lease
= lease
;
1161 log_dhcp_client(client
, "ACK");
1166 static uint64_t client_compute_timeout(sd_dhcp_client
*client
, uint32_t lifetime
, double factor
) {
1168 assert(client
->request_sent
);
1169 assert(lifetime
> 0);
1176 return client
->request_sent
+ (lifetime
* USEC_PER_SEC
* factor
) +
1177 + (random_u32() & 0x1fffff);
1180 static int client_set_lease_timeouts(sd_dhcp_client
*client
) {
1182 uint64_t lifetime_timeout
;
1183 uint64_t t2_timeout
;
1184 uint64_t t1_timeout
;
1185 char time_string
[FORMAT_TIMESPAN_MAX
];
1189 assert(client
->event
);
1190 assert(client
->lease
);
1191 assert(client
->lease
->lifetime
);
1193 client
->timeout_t1
= sd_event_source_unref(client
->timeout_t1
);
1194 client
->timeout_t2
= sd_event_source_unref(client
->timeout_t2
);
1195 client
->timeout_expire
= sd_event_source_unref(client
->timeout_expire
);
1197 /* don't set timers for infinite leases */
1198 if (client
->lease
->lifetime
== 0xffffffff)
1201 r
= sd_event_now(client
->event
, clock_boottime_or_monotonic(), &time_now
);
1204 assert(client
->request_sent
<= time_now
);
1206 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1207 lifetime_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 1);
1208 if (client
->lease
->t1
> 0 && client
->lease
->t2
> 0) {
1209 /* both T1 and T2 are given */
1210 if (client
->lease
->t1
< client
->lease
->t2
&&
1211 client
->lease
->t2
< client
->lease
->lifetime
) {
1212 /* they are both valid */
1213 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1214 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1217 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1218 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1219 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1220 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1222 } else if (client
->lease
->t2
> 0 && client
->lease
->t2
< client
->lease
->lifetime
) {
1223 /* only T2 is given, and it is valid */
1224 t2_timeout
= client_compute_timeout(client
, client
->lease
->t2
, 1);
1225 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1226 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1227 if (t2_timeout
<= t1_timeout
) {
1228 /* the computed T1 would be invalid, so discard T2 */
1229 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1230 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1232 } else if (client
->lease
->t1
> 0 && client
->lease
->t1
< client
->lease
->lifetime
) {
1233 /* only T1 is given, and it is valid */
1234 t1_timeout
= client_compute_timeout(client
, client
->lease
->t1
, 1);
1235 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1236 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1237 if (t2_timeout
<= t1_timeout
) {
1238 /* the computed T2 would be invalid, so discard T1 */
1239 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1240 client
->lease
->t2
= client
->lease
->lifetime
/ 2;
1243 /* fall back to the default timeouts */
1244 t1_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 0.5);
1245 client
->lease
->t1
= client
->lease
->lifetime
/ 2;
1246 t2_timeout
= client_compute_timeout(client
, client
->lease
->lifetime
, 7.0 / 8.0);
1247 client
->lease
->t2
= (client
->lease
->lifetime
* 7) / 8;
1250 /* arm lifetime timeout */
1251 r
= sd_event_add_time(client
->event
, &client
->timeout_expire
,
1252 clock_boottime_or_monotonic(),
1253 lifetime_timeout
, 10 * USEC_PER_MSEC
,
1254 client_timeout_expire
, client
);
1258 r
= sd_event_source_set_priority(client
->timeout_expire
,
1259 client
->event_priority
);
1263 r
= sd_event_source_set_description(client
->timeout_expire
, "dhcp4-lifetime");
1267 log_dhcp_client(client
, "lease expires in %s",
1268 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1269 lifetime_timeout
- time_now
, 0));
1271 /* don't arm earlier timeouts if this has already expired */
1272 if (lifetime_timeout
<= time_now
)
1275 /* arm T2 timeout */
1276 r
= sd_event_add_time(client
->event
,
1277 &client
->timeout_t2
,
1278 clock_boottime_or_monotonic(),
1281 client_timeout_t2
, client
);
1285 r
= sd_event_source_set_priority(client
->timeout_t2
,
1286 client
->event_priority
);
1290 r
= sd_event_source_set_description(client
->timeout_t2
, "dhcp4-t2-timeout");
1294 log_dhcp_client(client
, "T2 expires in %s",
1295 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1296 t2_timeout
- time_now
, 0));
1298 /* don't arm earlier timeout if this has already expired */
1299 if (t2_timeout
<= time_now
)
1302 /* arm T1 timeout */
1303 r
= sd_event_add_time(client
->event
,
1304 &client
->timeout_t1
,
1305 clock_boottime_or_monotonic(),
1306 t1_timeout
, 10 * USEC_PER_MSEC
,
1307 client_timeout_t1
, client
);
1311 r
= sd_event_source_set_priority(client
->timeout_t1
,
1312 client
->event_priority
);
1316 r
= sd_event_source_set_description(client
->timeout_t1
, "dhcp4-t1-timer");
1320 log_dhcp_client(client
, "T1 expires in %s",
1321 format_timespan(time_string
, FORMAT_TIMESPAN_MAX
,
1322 t1_timeout
- time_now
, 0));
1327 static int client_handle_message(sd_dhcp_client
*client
, DHCPMessage
*message
,
1329 DHCP_CLIENT_DONT_DESTROY(client
);
1330 int r
= 0, notify_event
= 0;
1333 assert(client
->event
);
1336 switch (client
->state
) {
1337 case DHCP_STATE_SELECTING
:
1339 r
= client_handle_offer(client
, message
, len
);
1342 client
->timeout_resend
=
1343 sd_event_source_unref(client
->timeout_resend
);
1345 client
->state
= DHCP_STATE_REQUESTING
;
1346 client
->attempt
= 1;
1348 r
= sd_event_add_time(client
->event
,
1349 &client
->timeout_resend
,
1350 clock_boottime_or_monotonic(),
1352 client_timeout_resend
, client
);
1356 r
= sd_event_source_set_priority(client
->timeout_resend
,
1357 client
->event_priority
);
1361 r
= sd_event_source_set_description(client
->timeout_resend
, "dhcp4-resend-timer");
1364 } else if (r
== -ENOMSG
)
1365 /* invalid message, let's ignore it */
1370 case DHCP_STATE_REBOOTING
:
1371 case DHCP_STATE_REQUESTING
:
1372 case DHCP_STATE_RENEWING
:
1373 case DHCP_STATE_REBINDING
:
1375 r
= client_handle_ack(client
, message
, len
);
1377 client
->timeout_resend
=
1378 sd_event_source_unref(client
->timeout_resend
);
1379 client
->receive_message
=
1380 sd_event_source_unref(client
->receive_message
);
1381 client
->fd
= asynchronous_close(client
->fd
);
1383 if (IN_SET(client
->state
, DHCP_STATE_REQUESTING
,
1384 DHCP_STATE_REBOOTING
))
1385 notify_event
= DHCP_EVENT_IP_ACQUIRE
;
1386 else if (r
!= DHCP_EVENT_IP_ACQUIRE
)
1389 client
->state
= DHCP_STATE_BOUND
;
1390 client
->attempt
= 1;
1392 client
->last_addr
= client
->lease
->address
;
1394 r
= client_set_lease_timeouts(client
);
1396 log_dhcp_client(client
, "could not set lease timeouts");
1400 r
= dhcp_network_bind_udp_socket(client
->lease
->address
,
1403 log_dhcp_client(client
, "could not bind UDP socket");
1409 client_initialize_io_events(client
, client_receive_message_udp
);
1412 client_notify(client
, notify_event
);
1413 if (client
->state
== DHCP_STATE_STOPPED
)
1417 } else if (r
== -EADDRNOTAVAIL
) {
1418 /* got a NAK, let's restart the client */
1419 client
->timeout_resend
=
1420 sd_event_source_unref(client
->timeout_resend
);
1422 r
= client_initialize(client
);
1426 r
= client_start(client
);
1430 log_dhcp_client(client
, "REBOOTED");
1433 } else if (r
== -ENOMSG
)
1434 /* invalid message, let's ignore it */
1439 case DHCP_STATE_BOUND
:
1440 r
= client_handle_forcerenew(client
, message
, len
);
1442 r
= client_timeout_t1(NULL
, 0, client
);
1445 } else if (r
== -ENOMSG
)
1446 /* invalid message, let's ignore it */
1451 case DHCP_STATE_INIT
:
1452 case DHCP_STATE_INIT_REBOOT
:
1456 case DHCP_STATE_STOPPED
:
1463 client_stop(client
, r
);
1468 static int client_receive_message_udp(sd_event_source
*s
, int fd
,
1469 uint32_t revents
, void *userdata
) {
1470 sd_dhcp_client
*client
= userdata
;
1471 _cleanup_free_ DHCPMessage
*message
= NULL
;
1472 int buflen
= 0, len
, r
;
1473 const struct ether_addr zero_mac
= { { 0, 0, 0, 0, 0, 0 } };
1474 const struct ether_addr
*expected_chaddr
= NULL
;
1475 uint8_t expected_hlen
= 0;
1480 r
= ioctl(fd
, FIONREAD
, &buflen
);
1485 /* this can't be right */
1488 message
= malloc0(buflen
);
1492 len
= read(fd
, message
, buflen
);
1494 log_dhcp_client(client
, "could not receive message from UDP "
1497 } else if ((size_t)len
< sizeof(DHCPMessage
)) {
1498 log_dhcp_client(client
, "too small to be a DHCP message: ignoring");
1502 if (be32toh(message
->magic
) != DHCP_MAGIC_COOKIE
) {
1503 log_dhcp_client(client
, "not a DHCP message: ignoring");
1507 if (message
->op
!= BOOTREPLY
) {
1508 log_dhcp_client(client
, "not a BOOTREPLY message: ignoring");
1512 if (message
->htype
!= client
->arp_type
) {
1513 log_dhcp_client(client
, "packet type does not match client type");
1517 if (client
->arp_type
== ARPHRD_ETHER
) {
1518 expected_hlen
= ETH_ALEN
;
1519 expected_chaddr
= (const struct ether_addr
*) &client
->mac_addr
;
1521 /* Non-ethernet links expect zero chaddr */
1523 expected_chaddr
= &zero_mac
;
1526 if (message
->hlen
!= expected_hlen
) {
1527 log_dhcp_client(client
, "unexpected packet hlen %d", message
->hlen
);
1531 if (memcmp(&message
->chaddr
[0], expected_chaddr
, ETH_ALEN
)) {
1532 log_dhcp_client(client
, "received chaddr does not match "
1533 "expected: ignoring");
1537 if (client
->state
!= DHCP_STATE_BOUND
&&
1538 be32toh(message
->xid
) != client
->xid
) {
1539 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1540 so ignore the xid in this case */
1541 log_dhcp_client(client
, "received xid (%u) does not match "
1542 "expected (%u): ignoring",
1543 be32toh(message
->xid
), client
->xid
);
1547 return client_handle_message(client
, message
, len
);
1550 static int client_receive_message_raw(sd_event_source
*s
, int fd
,
1551 uint32_t revents
, void *userdata
) {
1552 sd_dhcp_client
*client
= userdata
;
1553 _cleanup_free_ DHCPPacket
*packet
= NULL
;
1554 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct tpacket_auxdata
))];
1555 struct iovec iov
= {};
1556 struct msghdr msg
= {
1559 .msg_control
= cmsgbuf
,
1560 .msg_controllen
= sizeof(cmsgbuf
),
1562 struct cmsghdr
*cmsg
;
1563 bool checksum
= true;
1564 int buflen
= 0, len
, r
;
1569 r
= ioctl(fd
, FIONREAD
, &buflen
);
1574 /* this can't be right */
1577 packet
= malloc0(buflen
);
1581 iov
.iov_base
= packet
;
1582 iov
.iov_len
= buflen
;
1584 len
= recvmsg(fd
, &msg
, 0);
1586 log_dhcp_client(client
, "could not receive message from raw "
1589 } else if ((size_t)len
< sizeof(DHCPPacket
))
1592 CMSG_FOREACH(cmsg
, &msg
) {
1593 if (cmsg
->cmsg_level
== SOL_PACKET
&&
1594 cmsg
->cmsg_type
== PACKET_AUXDATA
&&
1595 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct tpacket_auxdata
))) {
1596 struct tpacket_auxdata
*aux
= (struct tpacket_auxdata
*)CMSG_DATA(cmsg
);
1598 checksum
= !(aux
->tp_status
& TP_STATUS_CSUMNOTREADY
);
1603 r
= dhcp_packet_verify_headers(packet
, len
, checksum
);
1607 len
-= DHCP_IP_UDP_SIZE
;
1609 return client_handle_message(client
, &packet
->dhcp
, len
);
1612 int sd_dhcp_client_start(sd_dhcp_client
*client
) {
1615 assert_return(client
, -EINVAL
);
1617 r
= client_initialize(client
);
1621 if (client
->last_addr
)
1622 client
->state
= DHCP_STATE_INIT_REBOOT
;
1624 r
= client_start(client
);
1626 log_dhcp_client(client
, "STARTED on ifindex %i", client
->index
);
1631 int sd_dhcp_client_stop(sd_dhcp_client
*client
) {
1632 DHCP_CLIENT_DONT_DESTROY(client
);
1634 assert_return(client
, -EINVAL
);
1636 client_stop(client
, DHCP_EVENT_STOP
);
1637 client
->state
= DHCP_STATE_STOPPED
;
1642 int sd_dhcp_client_attach_event(sd_dhcp_client
*client
, sd_event
*event
,
1646 assert_return(client
, -EINVAL
);
1647 assert_return(!client
->event
, -EBUSY
);
1650 client
->event
= sd_event_ref(event
);
1652 r
= sd_event_default(&client
->event
);
1657 client
->event_priority
= priority
;
1662 int sd_dhcp_client_detach_event(sd_dhcp_client
*client
) {
1663 assert_return(client
, -EINVAL
);
1665 client
->event
= sd_event_unref(client
->event
);
1670 sd_event
*sd_dhcp_client_get_event(sd_dhcp_client
*client
) {
1674 return client
->event
;
1677 sd_dhcp_client
*sd_dhcp_client_ref(sd_dhcp_client
*client
) {
1682 assert(client
->n_ref
>= 1);
1688 sd_dhcp_client
*sd_dhcp_client_unref(sd_dhcp_client
*client
) {
1693 assert(client
->n_ref
>= 1);
1696 if (client
->n_ref
> 0)
1699 log_dhcp_client(client
, "FREE");
1701 client_initialize(client
);
1703 client
->receive_message
= sd_event_source_unref(client
->receive_message
);
1705 sd_dhcp_client_detach_event(client
);
1707 sd_dhcp_lease_unref(client
->lease
);
1709 free(client
->req_opts
);
1710 free(client
->hostname
);
1711 free(client
->vendor_class_identifier
);
1717 int sd_dhcp_client_new(sd_dhcp_client
**ret
) {
1718 _cleanup_dhcp_client_unref_ sd_dhcp_client
*client
= NULL
;
1720 assert_return(ret
, -EINVAL
);
1722 client
= new0(sd_dhcp_client
, 1);
1727 client
->state
= DHCP_STATE_INIT
;
1730 client
->attempt
= 1;
1731 client
->mtu
= DHCP_DEFAULT_MIN_SIZE
;
1733 client
->req_opts_size
= ELEMENTSOF(default_req_opts
);
1735 client
->req_opts
= memdup(default_req_opts
, client
->req_opts_size
);
1736 if (!client
->req_opts
)