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 <netinet/ether.h>
28 #include <sys/param.h>
29 #include <sys/ioctl.h>
36 #include "dhcp-protocol.h"
37 #include "dhcp-internal.h"
38 #include "dhcp-lease-internal.h"
39 #include "sd-dhcp-client.h"
41 #define MAX_CLIENT_ID_LEN 64 /* Arbitrary limit */
42 #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
44 struct sd_dhcp_client {
50 sd_event_source *timeout_resend;
53 union sockaddr_union link;
54 sd_event_source *receive_message;
55 bool request_broadcast;
57 size_t req_opts_allocated;
60 uint8_t mac_addr[MAX_MAC_ADDR_LEN];
65 uint8_t type; /* 0: Generic (non-LL) (RFC 2132) */
66 uint8_t data[MAX_CLIENT_ID_LEN];
69 uint8_t type; /* 1: Ethernet Link-Layer (RFC 2132) */
70 uint8_t haddr[ETH_ALEN];
73 uint8_t type; /* 2 - 254: ARP/Link-Layer (RFC 2132) */
77 uint8_t type; /* 255: Node-specific (RFC 4361) */
79 uint8_t duid[MAX_CLIENT_ID_LEN - 4];
83 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,
108 DHCP_OPTION_NTP_SERVER,
111 static int client_receive_message_raw(sd_event_source *s, int fd,
112 uint32_t revents, void *userdata);
113 static int client_receive_message_udp(sd_event_source *s, int fd,
114 uint32_t revents, void *userdata);
115 static void client_stop(sd_dhcp_client *client, int error);
117 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
119 assert_return(client, -EINVAL);
122 client->userdata = userdata;
127 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
128 assert_return(client, -EINVAL);
130 client->request_broadcast = !!broadcast;
135 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
138 assert_return(client, -EINVAL);
139 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
140 DHCP_STATE_STOPPED), -EBUSY);
143 case DHCP_OPTION_PAD:
144 case DHCP_OPTION_OVERLOAD:
145 case DHCP_OPTION_MESSAGE_TYPE:
146 case DHCP_OPTION_PARAMETER_REQUEST_LIST:
147 case DHCP_OPTION_END:
154 for (i = 0; i < client->req_opts_size; i++)
155 if (client->req_opts[i] == option)
158 if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
159 client->req_opts_size + 1))
162 client->req_opts[client->req_opts_size++] = option;
167 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
168 const struct in_addr *last_addr) {
169 assert_return(client, -EINVAL);
170 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
171 DHCP_STATE_STOPPED), -EBUSY);
174 client->last_addr = last_addr->s_addr;
176 client->last_addr = INADDR_ANY;
181 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
182 assert_return(client, -EINVAL);
183 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
184 DHCP_STATE_STOPPED), -EBUSY);
185 assert_return(interface_index > 0, -EINVAL);
187 client->index = interface_index;
192 int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
193 size_t addr_len, uint16_t arp_type) {
194 DHCP_CLIENT_DONT_DESTROY(client);
195 bool need_restart = false;
197 assert_return(client, -EINVAL);
198 assert_return(addr, -EINVAL);
199 assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
200 assert_return(arp_type > 0, -EINVAL);
202 if (arp_type == ARPHRD_ETHER)
203 assert_return(addr_len == ETH_ALEN, -EINVAL);
204 else if (arp_type == ARPHRD_INFINIBAND)
205 assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
209 if (client->mac_addr_len == addr_len &&
210 memcmp(&client->mac_addr, addr, addr_len) == 0)
213 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
214 log_dhcp_client(client, "Changing MAC address on running DHCP "
215 "client, restarting");
217 client_stop(client, DHCP_EVENT_STOP);
220 memcpy(&client->mac_addr, addr, addr_len);
221 client->mac_addr_len = addr_len;
222 client->arp_type = arp_type;
224 if (need_restart && client->state != DHCP_STATE_STOPPED)
225 sd_dhcp_client_start(client);
230 int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
231 const uint8_t **data, size_t *data_len) {
233 assert_return(client, -EINVAL);
234 assert_return(type, -EINVAL);
235 assert_return(data, -EINVAL);
236 assert_return(data_len, -EINVAL);
241 if (client->client_id_len) {
242 *type = client->client_id.raw.type;
243 *data = client->client_id.raw.data;
244 *data_len = client->client_id_len -
245 sizeof (client->client_id.raw.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.raw.type) &&
274 client->client_id.raw.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.raw.type = type;
286 memcpy(&client->client_id.raw.data, data, data_len);
287 client->client_id_len = data_len + sizeof (client->client_id.raw.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 one from an ethernet
465 address if present */
466 if (client->client_id_len == 0 && client->arp_type == ARPHRD_ETHER) {
467 client->client_id.eth.type = ARPHRD_ETHER;
468 memcpy(&client->client_id.eth.haddr, &client->mac_addr, ETH_ALEN);
469 client->client_id_len = sizeof (client->client_id.eth);
472 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
473 Identifier option is not set */
474 if (client->client_id_len) {
475 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
476 DHCP_OPTION_CLIENT_IDENTIFIER,
477 client->client_id_len,
478 &client->client_id.raw);
483 /* RFC2131 section 3.5:
484 in its initial DHCPDISCOVER or DHCPREQUEST message, a
485 client may provide the server with a list of specific
486 parameters the client is interested in. If the client
487 includes a list of parameters in a DHCPDISCOVER message,
488 it MUST include that list in any subsequent DHCPREQUEST
491 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
492 DHCP_OPTION_PARAMETER_REQUEST_LIST,
493 client->req_opts_size, client->req_opts);
497 /* RFC2131 section 3.5:
498 The client SHOULD include the ’maximum DHCP message size’ option to
499 let the server know how large the server may make its DHCP messages.
501 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
502 than the defined default size unless the Maximum Messge Size option
505 RFC3442 "Requirements to Avoid Sizing Constraints":
506 Because a full routing table can be quite large, the standard 576
507 octet maximum size for a DHCP message may be too short to contain
508 some legitimate Classless Static Route options. Because of this,
509 clients implementing the Classless Static Route option SHOULD send a
510 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
511 stack is capable of receiving larger IP datagrams. In this case, the
512 client SHOULD set the value of this option to at least the MTU of the
513 interface that the client is configuring. The client MAY set the
514 value of this option higher, up to the size of the largest UDP packet
515 it is prepared to accept. (Note that the value specified in the
516 Maximum DHCP Message Size option is the total maximum packet size,
517 including IP and UDP headers.)
519 max_size = htobe16(size);
520 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
521 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
527 *_optoffset = optoffset;
534 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
536 dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
537 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
539 return dhcp_network_send_raw_socket(client->fd, &client->link,
543 static int client_send_discover(sd_dhcp_client *client) {
544 _cleanup_free_ DHCPPacket *discover = NULL;
545 size_t optoffset, optlen;
549 assert(client->state == DHCP_STATE_INIT ||
550 client->state == DHCP_STATE_SELECTING);
552 r = client_message_init(client, &discover, DHCP_DISCOVER,
553 &optlen, &optoffset);
557 /* the client may suggest values for the network address
558 and lease time in the DHCPDISCOVER message. The client may include
559 the ’requested IP address’ option to suggest that a particular IP
560 address be assigned, and may include the ’IP address lease time’
561 option to suggest the lease time it would like.
563 if (client->last_addr != INADDR_ANY) {
564 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
565 DHCP_OPTION_REQUESTED_IP_ADDRESS,
566 4, &client->last_addr);
571 /* it is unclear from RFC 2131 if client should send hostname in
572 DHCPDISCOVER but dhclient does and so we do as well
574 if (client->hostname) {
575 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
576 DHCP_OPTION_HOST_NAME,
577 strlen(client->hostname), client->hostname);
582 if (client->vendor_class_identifier) {
583 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
584 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
585 strlen(client->vendor_class_identifier),
586 client->vendor_class_identifier);
591 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
592 DHCP_OPTION_END, 0, NULL);
596 /* We currently ignore:
597 The client SHOULD wait a random time between one and ten seconds to
598 desynchronize the use of DHCP at startup.
600 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
604 log_dhcp_client(client, "DISCOVER");
609 static int client_send_request(sd_dhcp_client *client) {
610 _cleanup_free_ DHCPPacket *request = NULL;
611 size_t optoffset, optlen;
614 r = client_message_init(client, &request, DHCP_REQUEST,
615 &optlen, &optoffset);
619 switch (client->state) {
620 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
621 SELECTING should be REQUESTING)
624 case DHCP_STATE_REQUESTING:
625 /* Client inserts the address of the selected server in ’server
626 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
627 filled in with the yiaddr value from the chosen DHCPOFFER.
630 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
631 DHCP_OPTION_SERVER_IDENTIFIER,
632 4, &client->lease->server_address);
636 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
637 DHCP_OPTION_REQUESTED_IP_ADDRESS,
638 4, &client->lease->address);
644 case DHCP_STATE_INIT_REBOOT:
645 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
646 option MUST be filled in with client’s notion of its previously
647 assigned address. ’ciaddr’ MUST be zero.
649 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
650 DHCP_OPTION_REQUESTED_IP_ADDRESS,
651 4, &client->last_addr);
656 case DHCP_STATE_RENEWING:
657 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
658 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
659 client’s IP address.
663 case DHCP_STATE_REBINDING:
664 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
665 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
666 client’s IP address.
668 This message MUST be broadcast to the 0xffffffff IP broadcast address.
670 request->dhcp.ciaddr = client->lease->address;
674 case DHCP_STATE_INIT:
675 case DHCP_STATE_SELECTING:
676 case DHCP_STATE_REBOOTING:
677 case DHCP_STATE_BOUND:
678 case DHCP_STATE_STOPPED:
682 if (client->hostname) {
683 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
684 DHCP_OPTION_HOST_NAME,
685 strlen(client->hostname), client->hostname);
690 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
691 DHCP_OPTION_END, 0, NULL);
695 if (client->state == DHCP_STATE_RENEWING) {
696 r = dhcp_network_send_udp_socket(client->fd,
697 client->lease->server_address,
700 sizeof(DHCPMessage) + optoffset);
702 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
707 switch (client->state) {
708 case DHCP_STATE_REQUESTING:
709 log_dhcp_client(client, "REQUEST (requesting)");
711 case DHCP_STATE_INIT_REBOOT:
712 log_dhcp_client(client, "REQUEST (init-reboot)");
714 case DHCP_STATE_RENEWING:
715 log_dhcp_client(client, "REQUEST (renewing)");
717 case DHCP_STATE_REBINDING:
718 log_dhcp_client(client, "REQUEST (rebinding)");
721 log_dhcp_client(client, "REQUEST (invalid)");
728 static int client_start(sd_dhcp_client *client);
730 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
732 sd_dhcp_client *client = userdata;
733 DHCP_CLIENT_DONT_DESTROY(client);
734 usec_t next_timeout = 0;
741 assert(client->event);
743 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
747 switch (client->state) {
748 case DHCP_STATE_RENEWING:
750 time_left = (client->lease->t2 - client->lease->t1) / 2;
754 next_timeout = time_now + time_left * USEC_PER_SEC;
758 case DHCP_STATE_REBINDING:
760 time_left = (client->lease->lifetime - client->lease->t2) / 2;
764 next_timeout = time_now + time_left * USEC_PER_SEC;
767 case DHCP_STATE_REBOOTING:
768 /* start over as we did not receive a timely ack or nak */
769 r = client_initialize(client);
773 r = client_start(client);
777 log_dhcp_client(client, "REBOOTED");
781 case DHCP_STATE_INIT:
782 case DHCP_STATE_INIT_REBOOT:
783 case DHCP_STATE_SELECTING:
784 case DHCP_STATE_REQUESTING:
785 case DHCP_STATE_BOUND:
787 if (client->attempt < 64)
788 client->attempt *= 2;
790 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
794 case DHCP_STATE_STOPPED:
799 next_timeout += (random_u32() & 0x1fffff);
801 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
803 r = sd_event_add_time(client->event,
804 &client->timeout_resend,
805 clock_boottime_or_monotonic(),
806 next_timeout, 10 * USEC_PER_MSEC,
807 client_timeout_resend, client);
811 r = sd_event_source_set_priority(client->timeout_resend,
812 client->event_priority);
816 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
820 switch (client->state) {
821 case DHCP_STATE_INIT:
822 r = client_send_discover(client);
824 client->state = DHCP_STATE_SELECTING;
827 if (client->attempt >= 64)
833 case DHCP_STATE_SELECTING:
834 r = client_send_discover(client);
835 if (r < 0 && client->attempt >= 64)
840 case DHCP_STATE_INIT_REBOOT:
841 case DHCP_STATE_REQUESTING:
842 case DHCP_STATE_RENEWING:
843 case DHCP_STATE_REBINDING:
844 r = client_send_request(client);
845 if (r < 0 && client->attempt >= 64)
848 if (client->state == DHCP_STATE_INIT_REBOOT)
849 client->state = DHCP_STATE_REBOOTING;
851 client->request_sent = time_now;
855 case DHCP_STATE_REBOOTING:
856 case DHCP_STATE_BOUND:
860 case DHCP_STATE_STOPPED:
868 client_stop(client, r);
870 /* Errors were dealt with when stopping the client, don't spill
871 errors into the event loop handler */
875 static int client_initialize_io_events(sd_dhcp_client *client,
876 sd_event_io_handler_t io_callback) {
880 assert(client->event);
882 r = sd_event_add_io(client->event, &client->receive_message,
883 client->fd, EPOLLIN, io_callback,
888 r = sd_event_source_set_priority(client->receive_message,
889 client->event_priority);
893 r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
899 client_stop(client, r);
904 static int client_initialize_time_events(sd_dhcp_client *client) {
908 assert(client->event);
910 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
912 r = sd_event_add_time(client->event,
913 &client->timeout_resend,
914 clock_boottime_or_monotonic(),
916 client_timeout_resend, client);
920 r = sd_event_source_set_priority(client->timeout_resend,
921 client->event_priority);
923 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
929 client_stop(client, r);
935 static int client_initialize_events(sd_dhcp_client *client,
936 sd_event_io_handler_t io_callback) {
937 client_initialize_io_events(client, io_callback);
938 client_initialize_time_events(client);
943 static int client_start(sd_dhcp_client *client) {
946 assert_return(client, -EINVAL);
947 assert_return(client->event, -EINVAL);
948 assert_return(client->index > 0, -EINVAL);
949 assert_return(client->fd < 0, -EBUSY);
950 assert_return(client->xid == 0, -EINVAL);
951 assert_return(client->state == DHCP_STATE_INIT ||
952 client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
954 client->xid = random_u32();
956 r = dhcp_network_bind_raw_socket(client->index, &client->link,
957 client->xid, client->mac_addr,
958 client->mac_addr_len, client->arp_type);
960 client_stop(client, r);
965 if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
966 client->start_time = now(clock_boottime_or_monotonic());
968 return client_initialize_events(client, client_receive_message_raw);
971 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
973 sd_dhcp_client *client = userdata;
974 DHCP_CLIENT_DONT_DESTROY(client);
976 log_dhcp_client(client, "EXPIRED");
978 client_notify(client, DHCP_EVENT_EXPIRED);
980 /* lease was lost, start over if not freed or stopped in callback */
981 if (client->state != DHCP_STATE_STOPPED) {
982 client_initialize(client);
983 client_start(client);
989 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
990 sd_dhcp_client *client = userdata;
991 DHCP_CLIENT_DONT_DESTROY(client);
994 client->receive_message = sd_event_source_unref(client->receive_message);
995 client->fd = asynchronous_close(client->fd);
997 client->state = DHCP_STATE_REBINDING;
1000 r = dhcp_network_bind_raw_socket(client->index, &client->link,
1001 client->xid, client->mac_addr,
1002 client->mac_addr_len, client->arp_type);
1004 client_stop(client, r);
1009 return client_initialize_events(client, client_receive_message_raw);
1012 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
1014 sd_dhcp_client *client = userdata;
1015 DHCP_CLIENT_DONT_DESTROY(client);
1017 client->state = DHCP_STATE_RENEWING;
1018 client->attempt = 1;
1020 return client_initialize_time_events(client);
1023 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
1025 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
1028 r = dhcp_lease_new(&lease);
1032 if (client->client_id_len) {
1033 r = dhcp_lease_set_client_id(lease,
1034 (uint8_t *) &client->client_id.raw,
1035 client->client_id_len);
1040 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
1041 if (r != DHCP_OFFER) {
1042 log_dhcp_client(client, "received message was not an OFFER, ignoring");
1046 lease->next_server = offer->siaddr;
1048 lease->address = offer->yiaddr;
1050 if (lease->address == INADDR_ANY ||
1051 lease->server_address == INADDR_ANY ||
1052 lease->lifetime == 0) {
1053 log_dhcp_client(client, "received lease lacks address, server "
1054 "address or lease lifetime, ignoring");
1058 if (lease->subnet_mask == INADDR_ANY) {
1059 r = dhcp_lease_set_default_subnet_mask(lease);
1061 log_dhcp_client(client, "received lease lacks subnet "
1062 "mask, and a fallback one can not be "
1063 "generated, ignoring");
1068 sd_dhcp_lease_unref(client->lease);
1069 client->lease = lease;
1072 log_dhcp_client(client, "OFFER");
1077 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
1081 r = dhcp_option_parse(force, len, NULL, NULL);
1082 if (r != DHCP_FORCERENEW)
1085 log_dhcp_client(client, "FORCERENEW");
1090 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
1092 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
1095 r = dhcp_lease_new(&lease);
1099 if (client->client_id_len) {
1100 r = dhcp_lease_set_client_id(lease,
1101 (uint8_t *) &client->client_id.raw,
1102 client->client_id_len);
1107 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
1108 if (r == DHCP_NAK) {
1109 log_dhcp_client(client, "NAK");
1110 return -EADDRNOTAVAIL;
1113 if (r != DHCP_ACK) {
1114 log_dhcp_client(client, "received message was not an ACK, ignoring");
1118 lease->next_server = ack->siaddr;
1120 lease->address = ack->yiaddr;
1122 if (lease->address == INADDR_ANY ||
1123 lease->server_address == INADDR_ANY ||
1124 lease->lifetime == 0) {
1125 log_dhcp_client(client, "received lease lacks address, server "
1126 "address or lease lifetime, ignoring");
1130 if (lease->subnet_mask == INADDR_ANY) {
1131 r = dhcp_lease_set_default_subnet_mask(lease);
1133 log_dhcp_client(client, "received lease lacks subnet "
1134 "mask, and a fallback one can not be "
1135 "generated, ignoring");
1140 r = DHCP_EVENT_IP_ACQUIRE;
1141 if (client->lease) {
1142 if (client->lease->address != lease->address ||
1143 client->lease->subnet_mask != lease->subnet_mask ||
1144 client->lease->router != lease->router) {
1145 r = DHCP_EVENT_IP_CHANGE;
1147 r = DHCP_EVENT_RENEW;
1149 client->lease = sd_dhcp_lease_unref(client->lease);
1152 client->lease = lease;
1155 log_dhcp_client(client, "ACK");
1160 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1161 uint32_t lifetime, double factor) {
1163 assert(client->request_sent);
1166 return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1167 + (random_u32() & 0x1fffff);
1170 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1172 uint64_t lifetime_timeout;
1173 uint64_t t2_timeout;
1174 uint64_t t1_timeout;
1175 char time_string[FORMAT_TIMESPAN_MAX];
1179 assert(client->event);
1180 assert(client->lease);
1181 assert(client->lease->lifetime);
1183 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1184 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1185 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1187 /* don't set timers for infinite leases */
1188 if (client->lease->lifetime == 0xffffffff)
1191 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1194 assert(client->request_sent <= time_now);
1196 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1197 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1198 if (client->lease->t1 && client->lease->t2) {
1199 /* both T1 and T2 are given */
1200 if (client->lease->t1 < client->lease->t2 &&
1201 client->lease->t2 < client->lease->lifetime) {
1202 /* they are both valid */
1203 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1204 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1207 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1208 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1209 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1210 client->lease->t1 = client->lease->lifetime / 2;
1212 } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1213 /* only T2 is given, and it is valid */
1214 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1215 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1216 client->lease->t1 = client->lease->lifetime / 2;
1217 if (t2_timeout <= t1_timeout) {
1218 /* the computed T1 would be invalid, so discard T2 */
1219 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1220 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1222 } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1223 /* only T1 is given, and it is valid */
1224 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1225 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1226 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1227 if (t2_timeout <= t1_timeout) {
1228 /* the computed T2 would be invalid, so discard T1 */
1229 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1230 client->lease->t2 = client->lease->lifetime / 2;
1233 /* fall back to the default timeouts */
1234 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1235 client->lease->t1 = client->lease->lifetime / 2;
1236 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1237 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1240 /* arm lifetime timeout */
1241 r = sd_event_add_time(client->event, &client->timeout_expire,
1242 clock_boottime_or_monotonic(),
1243 lifetime_timeout, 10 * USEC_PER_MSEC,
1244 client_timeout_expire, client);
1248 r = sd_event_source_set_priority(client->timeout_expire,
1249 client->event_priority);
1253 r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
1257 log_dhcp_client(client, "lease expires in %s",
1258 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1259 lifetime_timeout - time_now, 0));
1261 /* don't arm earlier timeouts if this has already expired */
1262 if (lifetime_timeout <= time_now)
1265 /* arm T2 timeout */
1266 r = sd_event_add_time(client->event,
1267 &client->timeout_t2,
1268 clock_boottime_or_monotonic(),
1271 client_timeout_t2, client);
1275 r = sd_event_source_set_priority(client->timeout_t2,
1276 client->event_priority);
1280 r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
1284 log_dhcp_client(client, "T2 expires in %s",
1285 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1286 t2_timeout - time_now, 0));
1288 /* don't arm earlier timeout if this has already expired */
1289 if (t2_timeout <= time_now)
1292 /* arm T1 timeout */
1293 r = sd_event_add_time(client->event,
1294 &client->timeout_t1,
1295 clock_boottime_or_monotonic(),
1296 t1_timeout, 10 * USEC_PER_MSEC,
1297 client_timeout_t1, client);
1301 r = sd_event_source_set_priority(client->timeout_t1,
1302 client->event_priority);
1306 r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
1310 log_dhcp_client(client, "T1 expires in %s",
1311 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1312 t1_timeout - time_now, 0));
1317 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1319 DHCP_CLIENT_DONT_DESTROY(client);
1320 int r = 0, notify_event = 0;
1323 assert(client->event);
1326 switch (client->state) {
1327 case DHCP_STATE_SELECTING:
1329 r = client_handle_offer(client, message, len);
1332 client->timeout_resend =
1333 sd_event_source_unref(client->timeout_resend);
1335 client->state = DHCP_STATE_REQUESTING;
1336 client->attempt = 1;
1338 r = sd_event_add_time(client->event,
1339 &client->timeout_resend,
1340 clock_boottime_or_monotonic(),
1342 client_timeout_resend, client);
1346 r = sd_event_source_set_priority(client->timeout_resend,
1347 client->event_priority);
1351 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
1354 } else if (r == -ENOMSG)
1355 /* invalid message, let's ignore it */
1360 case DHCP_STATE_REBOOTING:
1361 case DHCP_STATE_REQUESTING:
1362 case DHCP_STATE_RENEWING:
1363 case DHCP_STATE_REBINDING:
1365 r = client_handle_ack(client, message, len);
1367 client->timeout_resend =
1368 sd_event_source_unref(client->timeout_resend);
1369 client->receive_message =
1370 sd_event_source_unref(client->receive_message);
1371 client->fd = asynchronous_close(client->fd);
1373 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1374 DHCP_STATE_REBOOTING))
1375 notify_event = DHCP_EVENT_IP_ACQUIRE;
1376 else if (r != DHCP_EVENT_IP_ACQUIRE)
1379 client->state = DHCP_STATE_BOUND;
1380 client->attempt = 1;
1382 client->last_addr = client->lease->address;
1384 r = client_set_lease_timeouts(client);
1388 r = dhcp_network_bind_udp_socket(client->lease->address,
1391 log_dhcp_client(client, "could not bind UDP socket");
1397 client_initialize_io_events(client, client_receive_message_udp);
1400 client_notify(client, notify_event);
1401 if (client->state == DHCP_STATE_STOPPED)
1405 } else if (r == -EADDRNOTAVAIL) {
1406 /* got a NAK, let's restart the client */
1407 client->timeout_resend =
1408 sd_event_source_unref(client->timeout_resend);
1410 r = client_initialize(client);
1414 r = client_start(client);
1418 log_dhcp_client(client, "REBOOTED");
1421 } else if (r == -ENOMSG)
1422 /* invalid message, let's ignore it */
1427 case DHCP_STATE_BOUND:
1428 r = client_handle_forcerenew(client, message, len);
1430 r = client_timeout_t1(NULL, 0, client);
1433 } else if (r == -ENOMSG)
1434 /* invalid message, let's ignore it */
1439 case DHCP_STATE_INIT:
1440 case DHCP_STATE_INIT_REBOOT:
1444 case DHCP_STATE_STOPPED:
1451 client_stop(client, r);
1456 static int client_receive_message_udp(sd_event_source *s, int fd,
1457 uint32_t revents, void *userdata) {
1458 sd_dhcp_client *client = userdata;
1459 _cleanup_free_ DHCPMessage *message = NULL;
1460 int buflen = 0, len, r;
1461 const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1462 const struct ether_addr *expected_chaddr = NULL;
1463 uint8_t expected_hlen = 0;
1468 r = ioctl(fd, FIONREAD, &buflen);
1473 /* this can't be right */
1476 message = malloc0(buflen);
1480 len = read(fd, message, buflen);
1482 log_dhcp_client(client, "could not receive message from UDP "
1485 } else if ((size_t)len < sizeof(DHCPMessage)) {
1486 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1490 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1491 log_dhcp_client(client, "not a DHCP message: ignoring");
1495 if (message->op != BOOTREPLY) {
1496 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1500 if (message->htype != client->arp_type) {
1501 log_dhcp_client(client, "packet type does not match client type");
1505 if (client->arp_type == ARPHRD_ETHER) {
1506 expected_hlen = ETH_ALEN;
1507 expected_chaddr = (const struct ether_addr *) &client->mac_addr;
1509 /* Non-ethernet links expect zero chaddr */
1511 expected_chaddr = &zero_mac;
1514 if (message->hlen != expected_hlen) {
1515 log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
1519 if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
1520 log_dhcp_client(client, "received chaddr does not match "
1521 "expected: ignoring");
1525 if (client->state != DHCP_STATE_BOUND &&
1526 be32toh(message->xid) != client->xid) {
1527 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1528 so ignore the xid in this case */
1529 log_dhcp_client(client, "received xid (%u) does not match "
1530 "expected (%u): ignoring",
1531 be32toh(message->xid), client->xid);
1535 return client_handle_message(client, message, len);
1538 static int client_receive_message_raw(sd_event_source *s, int fd,
1539 uint32_t revents, void *userdata) {
1540 sd_dhcp_client *client = userdata;
1541 _cleanup_free_ DHCPPacket *packet = NULL;
1542 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1543 struct iovec iov = {};
1544 struct msghdr msg = {
1547 .msg_control = cmsgbuf,
1548 .msg_controllen = sizeof(cmsgbuf),
1550 struct cmsghdr *cmsg;
1551 bool checksum = true;
1552 int buflen = 0, len, r;
1557 r = ioctl(fd, FIONREAD, &buflen);
1562 /* this can't be right */
1565 packet = malloc0(buflen);
1569 iov.iov_base = packet;
1570 iov.iov_len = buflen;
1572 len = recvmsg(fd, &msg, 0);
1574 log_dhcp_client(client, "could not receive message from raw "
1577 } else if ((size_t)len < sizeof(DHCPPacket))
1580 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1581 if (cmsg->cmsg_level == SOL_PACKET &&
1582 cmsg->cmsg_type == PACKET_AUXDATA &&
1583 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1584 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1586 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1591 r = dhcp_packet_verify_headers(packet, len, checksum);
1595 len -= DHCP_IP_UDP_SIZE;
1597 return client_handle_message(client, &packet->dhcp, len);
1600 int sd_dhcp_client_start(sd_dhcp_client *client) {
1603 assert_return(client, -EINVAL);
1605 r = client_initialize(client);
1609 if (client->last_addr)
1610 client->state = DHCP_STATE_INIT_REBOOT;
1612 r = client_start(client);
1614 log_dhcp_client(client, "STARTED on ifindex %u", client->index);
1619 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1620 DHCP_CLIENT_DONT_DESTROY(client);
1622 assert_return(client, -EINVAL);
1624 client_stop(client, DHCP_EVENT_STOP);
1625 client->state = DHCP_STATE_STOPPED;
1630 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1634 assert_return(client, -EINVAL);
1635 assert_return(!client->event, -EBUSY);
1638 client->event = sd_event_ref(event);
1640 r = sd_event_default(&client->event);
1645 client->event_priority = priority;
1650 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1651 assert_return(client, -EINVAL);
1653 client->event = sd_event_unref(client->event);
1658 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1662 return client->event;
1665 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1667 assert_se(REFCNT_INC(client->n_ref) >= 2);
1672 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1673 if (client && REFCNT_DEC(client->n_ref) <= 0) {
1674 log_dhcp_client(client, "FREE");
1676 client_initialize(client);
1678 client->receive_message =
1679 sd_event_source_unref(client->receive_message);
1681 sd_dhcp_client_detach_event(client);
1683 sd_dhcp_lease_unref(client->lease);
1685 free(client->req_opts);
1686 free(client->hostname);
1687 free(client->vendor_class_identifier);
1694 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1695 _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1697 assert_return(ret, -EINVAL);
1699 client = new0(sd_dhcp_client, 1);
1703 client->n_ref = REFCNT_INIT;
1704 client->state = DHCP_STATE_INIT;
1707 client->attempt = 1;
1708 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1710 client->req_opts_size = ELEMENTSOF(default_req_opts);
1712 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1713 if (!client->req_opts)