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 "dhcp-identifier.h"
40 #include "sd-dhcp-client.h"
42 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
43 #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
45 struct sd_dhcp_client {
51 sd_event_source *timeout_resend;
54 union sockaddr_union link;
55 sd_event_source *receive_message;
56 bool request_broadcast;
58 size_t req_opts_allocated;
61 uint8_t mac_addr[MAX_MAC_ADDR_LEN];
68 /* 0: Generic (non-LL) (RFC 2132) */
69 uint8_t data[MAX_CLIENT_ID_LEN];
72 /* 1: Ethernet Link-Layer (RFC 2132) */
73 uint8_t haddr[ETH_ALEN];
76 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
80 /* 255: Node-specific (RFC 4361) */
85 uint8_t data[MAX_CLIENT_ID_LEN];
91 char *vendor_class_identifier;
97 sd_event_source *timeout_t1;
98 sd_event_source *timeout_t2;
99 sd_event_source *timeout_expire;
100 sd_dhcp_client_cb_t cb;
102 sd_dhcp_lease *lease;
105 static const uint8_t default_req_opts[] = {
106 DHCP_OPTION_SUBNET_MASK,
108 DHCP_OPTION_HOST_NAME,
109 DHCP_OPTION_DOMAIN_NAME,
110 DHCP_OPTION_DOMAIN_NAME_SERVER,
111 DHCP_OPTION_NTP_SERVER,
114 static int client_receive_message_raw(sd_event_source *s, int fd,
115 uint32_t revents, void *userdata);
116 static int client_receive_message_udp(sd_event_source *s, int fd,
117 uint32_t revents, void *userdata);
118 static void client_stop(sd_dhcp_client *client, int error);
120 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
122 assert_return(client, -EINVAL);
125 client->userdata = userdata;
130 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
131 assert_return(client, -EINVAL);
133 client->request_broadcast = !!broadcast;
138 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
141 assert_return(client, -EINVAL);
142 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
143 DHCP_STATE_STOPPED), -EBUSY);
146 case DHCP_OPTION_PAD:
147 case DHCP_OPTION_OVERLOAD:
148 case DHCP_OPTION_MESSAGE_TYPE:
149 case DHCP_OPTION_PARAMETER_REQUEST_LIST:
150 case DHCP_OPTION_END:
157 for (i = 0; i < client->req_opts_size; i++)
158 if (client->req_opts[i] == option)
161 if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
162 client->req_opts_size + 1))
165 client->req_opts[client->req_opts_size++] = option;
170 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
171 const struct in_addr *last_addr) {
172 assert_return(client, -EINVAL);
173 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
174 DHCP_STATE_STOPPED), -EBUSY);
177 client->last_addr = last_addr->s_addr;
179 client->last_addr = INADDR_ANY;
184 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
185 assert_return(client, -EINVAL);
186 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
187 DHCP_STATE_STOPPED), -EBUSY);
188 assert_return(interface_index > 0, -EINVAL);
190 client->index = interface_index;
195 int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
196 size_t addr_len, uint16_t arp_type) {
197 DHCP_CLIENT_DONT_DESTROY(client);
198 bool need_restart = false;
200 assert_return(client, -EINVAL);
201 assert_return(addr, -EINVAL);
202 assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
203 assert_return(arp_type > 0, -EINVAL);
205 if (arp_type == ARPHRD_ETHER)
206 assert_return(addr_len == ETH_ALEN, -EINVAL);
207 else if (arp_type == ARPHRD_INFINIBAND)
208 assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
212 if (client->mac_addr_len == addr_len &&
213 memcmp(&client->mac_addr, addr, addr_len) == 0)
216 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
217 log_dhcp_client(client, "Changing MAC address on running DHCP "
218 "client, restarting");
220 client_stop(client, DHCP_EVENT_STOP);
223 memcpy(&client->mac_addr, addr, addr_len);
224 client->mac_addr_len = addr_len;
225 client->arp_type = arp_type;
227 if (need_restart && client->state != DHCP_STATE_STOPPED)
228 sd_dhcp_client_start(client);
233 int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
234 const uint8_t **data, size_t *data_len) {
236 assert_return(client, -EINVAL);
237 assert_return(type, -EINVAL);
238 assert_return(data, -EINVAL);
239 assert_return(data_len, -EINVAL);
244 if (client->client_id_len) {
245 *type = client->client_id.type;
246 *data = client->client_id.raw.data;
247 *data_len = client->client_id_len - sizeof(client->client_id.type);
253 int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
254 const uint8_t *data, size_t data_len) {
255 DHCP_CLIENT_DONT_DESTROY(client);
256 bool need_restart = false;
258 assert_return(client, -EINVAL);
259 assert_return(data, -EINVAL);
260 assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
264 if (data_len != ETH_ALEN)
267 case ARPHRD_INFINIBAND:
268 if (data_len != INFINIBAND_ALEN)
275 if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
276 client->client_id.type == type &&
277 memcmp(&client->client_id.raw.data, data, data_len) == 0)
280 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
281 log_dhcp_client(client, "Changing client ID on running DHCP "
282 "client, restarting");
284 client_stop(client, DHCP_EVENT_STOP);
287 client->client_id.type = type;
288 memcpy(&client->client_id.raw.data, data, data_len);
289 client->client_id_len = data_len + sizeof (client->client_id.type);
291 if (need_restart && client->state != DHCP_STATE_STOPPED)
292 sd_dhcp_client_start(client);
297 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
298 const char *hostname) {
299 char *new_hostname = NULL;
301 assert_return(client, -EINVAL);
303 if (streq_ptr(client->hostname, hostname))
307 new_hostname = strdup(hostname);
312 free(client->hostname);
313 client->hostname = new_hostname;
318 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
320 char *new_vci = NULL;
322 assert_return(client, -EINVAL);
324 new_vci = strdup(vci);
328 free(client->vendor_class_identifier);
330 client->vendor_class_identifier = new_vci;
335 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
336 assert_return(client, -EINVAL);
337 assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
344 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
345 assert_return(client, -EINVAL);
346 assert_return(ret, -EINVAL);
348 if (client->state != DHCP_STATE_BOUND &&
349 client->state != DHCP_STATE_RENEWING &&
350 client->state != DHCP_STATE_REBINDING)
351 return -EADDRNOTAVAIL;
353 *ret = sd_dhcp_lease_ref(client->lease);
358 static void client_notify(sd_dhcp_client *client, int event) {
360 client->cb(client, event, client->userdata);
363 static int client_initialize(sd_dhcp_client *client) {
364 assert_return(client, -EINVAL);
366 client->receive_message =
367 sd_event_source_unref(client->receive_message);
369 client->fd = asynchronous_close(client->fd);
371 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
373 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
374 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
375 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
379 client->state = DHCP_STATE_INIT;
383 client->lease = sd_dhcp_lease_unref(client->lease);
388 static void client_stop(sd_dhcp_client *client, int error) {
392 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
393 else if (error == DHCP_EVENT_STOP)
394 log_dhcp_client(client, "STOPPED");
396 log_dhcp_client(client, "STOPPED: Unknown event");
398 client_notify(client, error);
400 client_initialize(client);
403 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
404 uint8_t type, size_t *_optlen, size_t *_optoffset) {
405 _cleanup_free_ DHCPPacket *packet;
406 size_t optlen, optoffset, size;
413 assert(client->start_time);
417 assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
419 optlen = DHCP_MIN_OPTIONS_SIZE;
420 size = sizeof(DHCPPacket) + optlen;
422 packet = malloc0(size);
426 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
427 client->arp_type, optlen, &optoffset);
431 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
432 refuse to issue an DHCP lease if 'secs' is set to zero */
433 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
436 assert(time_now >= client->start_time);
438 /* seconds between sending first and last DISCOVER
439 * must always be strictly positive to deal with broken servers */
440 secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
441 packet->dhcp.secs = htobe16(secs);
443 /* RFC2132 section 4.1
444 A client that cannot receive unicast IP datagrams until its protocol
445 software has been configured with an IP address SHOULD set the
446 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
447 DHCPREQUEST messages that client sends. The BROADCAST bit will
448 provide a hint to the DHCP server and BOOTP relay agent to broadcast
449 any messages to the client on the client's subnet.
451 Note: some interfaces needs this to be enabled, but some networks
452 needs this to be disabled as broadcasts are filteretd, so this
453 needs to be configurable */
454 if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
455 packet->dhcp.flags = htobe16(0x8000);
457 /* RFC2132 section 4.1.1:
458 The client MUST include its hardware address in the ’chaddr’ field, if
459 necessary for delivery of DHCP reply messages. Non-Ethernet
460 interfaces will leave 'chaddr' empty and use the client identifier
461 instead (eg, RFC 4390 section 2.1).
463 if (client->arp_type == ARPHRD_ETHER)
464 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
466 /* If no client identifier exists, construct an RFC 4361-compliant one */
467 if (client->client_id_len == 0) {
470 client->client_id.type = 255;
472 r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
476 r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len);
480 client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
483 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
484 Identifier option is not set */
485 if (client->client_id_len) {
486 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
487 DHCP_OPTION_CLIENT_IDENTIFIER,
488 client->client_id_len,
494 /* RFC2131 section 3.5:
495 in its initial DHCPDISCOVER or DHCPREQUEST message, a
496 client may provide the server with a list of specific
497 parameters the client is interested in. If the client
498 includes a list of parameters in a DHCPDISCOVER message,
499 it MUST include that list in any subsequent DHCPREQUEST
502 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
503 DHCP_OPTION_PARAMETER_REQUEST_LIST,
504 client->req_opts_size, client->req_opts);
508 /* RFC2131 section 3.5:
509 The client SHOULD include the ’maximum DHCP message size’ option to
510 let the server know how large the server may make its DHCP messages.
512 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
513 than the defined default size unless the Maximum Messge Size option
516 RFC3442 "Requirements to Avoid Sizing Constraints":
517 Because a full routing table can be quite large, the standard 576
518 octet maximum size for a DHCP message may be too short to contain
519 some legitimate Classless Static Route options. Because of this,
520 clients implementing the Classless Static Route option SHOULD send a
521 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
522 stack is capable of receiving larger IP datagrams. In this case, the
523 client SHOULD set the value of this option to at least the MTU of the
524 interface that the client is configuring. The client MAY set the
525 value of this option higher, up to the size of the largest UDP packet
526 it is prepared to accept. (Note that the value specified in the
527 Maximum DHCP Message Size option is the total maximum packet size,
528 including IP and UDP headers.)
530 max_size = htobe16(size);
531 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
532 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
538 *_optoffset = optoffset;
545 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
547 dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
548 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
550 return dhcp_network_send_raw_socket(client->fd, &client->link,
554 static int client_send_discover(sd_dhcp_client *client) {
555 _cleanup_free_ DHCPPacket *discover = NULL;
556 size_t optoffset, optlen;
560 assert(client->state == DHCP_STATE_INIT ||
561 client->state == DHCP_STATE_SELECTING);
563 r = client_message_init(client, &discover, DHCP_DISCOVER,
564 &optlen, &optoffset);
568 /* the client may suggest values for the network address
569 and lease time in the DHCPDISCOVER message. The client may include
570 the ’requested IP address’ option to suggest that a particular IP
571 address be assigned, and may include the ’IP address lease time’
572 option to suggest the lease time it would like.
574 if (client->last_addr != INADDR_ANY) {
575 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
576 DHCP_OPTION_REQUESTED_IP_ADDRESS,
577 4, &client->last_addr);
582 /* it is unclear from RFC 2131 if client should send hostname in
583 DHCPDISCOVER but dhclient does and so we do as well
585 if (client->hostname) {
586 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
587 DHCP_OPTION_HOST_NAME,
588 strlen(client->hostname), client->hostname);
593 if (client->vendor_class_identifier) {
594 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
595 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
596 strlen(client->vendor_class_identifier),
597 client->vendor_class_identifier);
602 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
603 DHCP_OPTION_END, 0, NULL);
607 /* We currently ignore:
608 The client SHOULD wait a random time between one and ten seconds to
609 desynchronize the use of DHCP at startup.
611 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
615 log_dhcp_client(client, "DISCOVER");
620 static int client_send_request(sd_dhcp_client *client) {
621 _cleanup_free_ DHCPPacket *request = NULL;
622 size_t optoffset, optlen;
625 r = client_message_init(client, &request, DHCP_REQUEST,
626 &optlen, &optoffset);
630 switch (client->state) {
631 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
632 SELECTING should be REQUESTING)
635 case DHCP_STATE_REQUESTING:
636 /* Client inserts the address of the selected server in ’server
637 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
638 filled in with the yiaddr value from the chosen DHCPOFFER.
641 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
642 DHCP_OPTION_SERVER_IDENTIFIER,
643 4, &client->lease->server_address);
647 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
648 DHCP_OPTION_REQUESTED_IP_ADDRESS,
649 4, &client->lease->address);
655 case DHCP_STATE_INIT_REBOOT:
656 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
657 option MUST be filled in with client’s notion of its previously
658 assigned address. ’ciaddr’ MUST be zero.
660 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
661 DHCP_OPTION_REQUESTED_IP_ADDRESS,
662 4, &client->last_addr);
667 case DHCP_STATE_RENEWING:
668 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
669 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
670 client’s IP address.
674 case DHCP_STATE_REBINDING:
675 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
676 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
677 client’s IP address.
679 This message MUST be broadcast to the 0xffffffff IP broadcast address.
681 request->dhcp.ciaddr = client->lease->address;
685 case DHCP_STATE_INIT:
686 case DHCP_STATE_SELECTING:
687 case DHCP_STATE_REBOOTING:
688 case DHCP_STATE_BOUND:
689 case DHCP_STATE_STOPPED:
693 if (client->hostname) {
694 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
695 DHCP_OPTION_HOST_NAME,
696 strlen(client->hostname), client->hostname);
701 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
702 DHCP_OPTION_END, 0, NULL);
706 if (client->state == DHCP_STATE_RENEWING) {
707 r = dhcp_network_send_udp_socket(client->fd,
708 client->lease->server_address,
711 sizeof(DHCPMessage) + optoffset);
713 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
718 switch (client->state) {
719 case DHCP_STATE_REQUESTING:
720 log_dhcp_client(client, "REQUEST (requesting)");
722 case DHCP_STATE_INIT_REBOOT:
723 log_dhcp_client(client, "REQUEST (init-reboot)");
725 case DHCP_STATE_RENEWING:
726 log_dhcp_client(client, "REQUEST (renewing)");
728 case DHCP_STATE_REBINDING:
729 log_dhcp_client(client, "REQUEST (rebinding)");
732 log_dhcp_client(client, "REQUEST (invalid)");
739 static int client_start(sd_dhcp_client *client);
741 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
743 sd_dhcp_client *client = userdata;
744 DHCP_CLIENT_DONT_DESTROY(client);
745 usec_t next_timeout = 0;
752 assert(client->event);
754 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
758 switch (client->state) {
759 case DHCP_STATE_RENEWING:
761 time_left = (client->lease->t2 - client->lease->t1) / 2;
765 next_timeout = time_now + time_left * USEC_PER_SEC;
769 case DHCP_STATE_REBINDING:
771 time_left = (client->lease->lifetime - client->lease->t2) / 2;
775 next_timeout = time_now + time_left * USEC_PER_SEC;
778 case DHCP_STATE_REBOOTING:
779 /* start over as we did not receive a timely ack or nak */
780 r = client_initialize(client);
784 r = client_start(client);
788 log_dhcp_client(client, "REBOOTED");
792 case DHCP_STATE_INIT:
793 case DHCP_STATE_INIT_REBOOT:
794 case DHCP_STATE_SELECTING:
795 case DHCP_STATE_REQUESTING:
796 case DHCP_STATE_BOUND:
798 if (client->attempt < 64)
799 client->attempt *= 2;
801 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
805 case DHCP_STATE_STOPPED:
810 next_timeout += (random_u32() & 0x1fffff);
812 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
814 r = sd_event_add_time(client->event,
815 &client->timeout_resend,
816 clock_boottime_or_monotonic(),
817 next_timeout, 10 * USEC_PER_MSEC,
818 client_timeout_resend, client);
822 r = sd_event_source_set_priority(client->timeout_resend,
823 client->event_priority);
827 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
831 switch (client->state) {
832 case DHCP_STATE_INIT:
833 r = client_send_discover(client);
835 client->state = DHCP_STATE_SELECTING;
838 if (client->attempt >= 64)
844 case DHCP_STATE_SELECTING:
845 r = client_send_discover(client);
846 if (r < 0 && client->attempt >= 64)
851 case DHCP_STATE_INIT_REBOOT:
852 case DHCP_STATE_REQUESTING:
853 case DHCP_STATE_RENEWING:
854 case DHCP_STATE_REBINDING:
855 r = client_send_request(client);
856 if (r < 0 && client->attempt >= 64)
859 if (client->state == DHCP_STATE_INIT_REBOOT)
860 client->state = DHCP_STATE_REBOOTING;
862 client->request_sent = time_now;
866 case DHCP_STATE_REBOOTING:
867 case DHCP_STATE_BOUND:
871 case DHCP_STATE_STOPPED:
879 client_stop(client, r);
881 /* Errors were dealt with when stopping the client, don't spill
882 errors into the event loop handler */
886 static int client_initialize_io_events(sd_dhcp_client *client,
887 sd_event_io_handler_t io_callback) {
891 assert(client->event);
893 r = sd_event_add_io(client->event, &client->receive_message,
894 client->fd, EPOLLIN, io_callback,
899 r = sd_event_source_set_priority(client->receive_message,
900 client->event_priority);
904 r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
910 client_stop(client, r);
915 static int client_initialize_time_events(sd_dhcp_client *client) {
919 assert(client->event);
921 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
923 r = sd_event_add_time(client->event,
924 &client->timeout_resend,
925 clock_boottime_or_monotonic(),
927 client_timeout_resend, client);
931 r = sd_event_source_set_priority(client->timeout_resend,
932 client->event_priority);
934 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
940 client_stop(client, r);
946 static int client_initialize_events(sd_dhcp_client *client,
947 sd_event_io_handler_t io_callback) {
948 client_initialize_io_events(client, io_callback);
949 client_initialize_time_events(client);
954 static int client_start(sd_dhcp_client *client) {
957 assert_return(client, -EINVAL);
958 assert_return(client->event, -EINVAL);
959 assert_return(client->index > 0, -EINVAL);
960 assert_return(client->fd < 0, -EBUSY);
961 assert_return(client->xid == 0, -EINVAL);
962 assert_return(client->state == DHCP_STATE_INIT ||
963 client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
965 client->xid = random_u32();
967 r = dhcp_network_bind_raw_socket(client->index, &client->link,
968 client->xid, client->mac_addr,
969 client->mac_addr_len, client->arp_type);
971 client_stop(client, r);
976 if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
977 client->start_time = now(clock_boottime_or_monotonic());
979 return client_initialize_events(client, client_receive_message_raw);
982 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
984 sd_dhcp_client *client = userdata;
985 DHCP_CLIENT_DONT_DESTROY(client);
987 log_dhcp_client(client, "EXPIRED");
989 client_notify(client, DHCP_EVENT_EXPIRED);
991 /* lease was lost, start over if not freed or stopped in callback */
992 if (client->state != DHCP_STATE_STOPPED) {
993 client_initialize(client);
994 client_start(client);
1000 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
1001 sd_dhcp_client *client = userdata;
1002 DHCP_CLIENT_DONT_DESTROY(client);
1005 client->receive_message = sd_event_source_unref(client->receive_message);
1006 client->fd = asynchronous_close(client->fd);
1008 client->state = DHCP_STATE_REBINDING;
1009 client->attempt = 1;
1011 r = dhcp_network_bind_raw_socket(client->index, &client->link,
1012 client->xid, client->mac_addr,
1013 client->mac_addr_len, client->arp_type);
1015 client_stop(client, r);
1020 return client_initialize_events(client, client_receive_message_raw);
1023 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
1025 sd_dhcp_client *client = userdata;
1026 DHCP_CLIENT_DONT_DESTROY(client);
1028 client->state = DHCP_STATE_RENEWING;
1029 client->attempt = 1;
1031 return client_initialize_time_events(client);
1034 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
1036 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
1039 r = dhcp_lease_new(&lease);
1043 if (client->client_id_len) {
1044 r = dhcp_lease_set_client_id(lease,
1045 (uint8_t *) &client->client_id,
1046 client->client_id_len);
1051 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
1052 if (r != DHCP_OFFER) {
1053 log_dhcp_client(client, "received message was not an OFFER, ignoring");
1057 lease->next_server = offer->siaddr;
1059 lease->address = offer->yiaddr;
1061 if (lease->address == INADDR_ANY ||
1062 lease->server_address == INADDR_ANY ||
1063 lease->lifetime == 0) {
1064 log_dhcp_client(client, "received lease lacks address, server "
1065 "address or lease lifetime, ignoring");
1069 if (lease->subnet_mask == INADDR_ANY) {
1070 r = dhcp_lease_set_default_subnet_mask(lease);
1072 log_dhcp_client(client, "received lease lacks subnet "
1073 "mask, and a fallback one can not be "
1074 "generated, ignoring");
1079 sd_dhcp_lease_unref(client->lease);
1080 client->lease = lease;
1083 log_dhcp_client(client, "OFFER");
1088 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
1092 r = dhcp_option_parse(force, len, NULL, NULL);
1093 if (r != DHCP_FORCERENEW)
1096 log_dhcp_client(client, "FORCERENEW");
1101 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
1103 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
1106 r = dhcp_lease_new(&lease);
1110 if (client->client_id_len) {
1111 r = dhcp_lease_set_client_id(lease,
1112 (uint8_t *) &client->client_id,
1113 client->client_id_len);
1118 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
1119 if (r == DHCP_NAK) {
1120 log_dhcp_client(client, "NAK");
1121 return -EADDRNOTAVAIL;
1124 if (r != DHCP_ACK) {
1125 log_dhcp_client(client, "received message was not an ACK, ignoring");
1129 lease->next_server = ack->siaddr;
1131 lease->address = ack->yiaddr;
1133 if (lease->address == INADDR_ANY ||
1134 lease->server_address == INADDR_ANY ||
1135 lease->lifetime == 0) {
1136 log_dhcp_client(client, "received lease lacks address, server "
1137 "address or lease lifetime, ignoring");
1141 if (lease->subnet_mask == INADDR_ANY) {
1142 r = dhcp_lease_set_default_subnet_mask(lease);
1144 log_dhcp_client(client, "received lease lacks subnet "
1145 "mask, and a fallback one can not be "
1146 "generated, ignoring");
1151 r = DHCP_EVENT_IP_ACQUIRE;
1152 if (client->lease) {
1153 if (client->lease->address != lease->address ||
1154 client->lease->subnet_mask != lease->subnet_mask ||
1155 client->lease->router != lease->router) {
1156 r = DHCP_EVENT_IP_CHANGE;
1158 r = DHCP_EVENT_RENEW;
1160 client->lease = sd_dhcp_lease_unref(client->lease);
1163 client->lease = lease;
1166 log_dhcp_client(client, "ACK");
1171 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1172 uint32_t lifetime, double factor) {
1174 assert(client->request_sent);
1177 return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1178 + (random_u32() & 0x1fffff);
1181 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1183 uint64_t lifetime_timeout;
1184 uint64_t t2_timeout;
1185 uint64_t t1_timeout;
1186 char time_string[FORMAT_TIMESPAN_MAX];
1190 assert(client->event);
1191 assert(client->lease);
1192 assert(client->lease->lifetime);
1194 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1195 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1196 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1198 /* don't set timers for infinite leases */
1199 if (client->lease->lifetime == 0xffffffff)
1202 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1205 assert(client->request_sent <= time_now);
1207 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1208 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1209 if (client->lease->t1 && client->lease->t2) {
1210 /* both T1 and T2 are given */
1211 if (client->lease->t1 < client->lease->t2 &&
1212 client->lease->t2 < client->lease->lifetime) {
1213 /* they are both valid */
1214 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1215 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1218 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1219 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1220 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1221 client->lease->t1 = client->lease->lifetime / 2;
1223 } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1224 /* only T2 is given, and it is valid */
1225 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1226 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1227 client->lease->t1 = client->lease->lifetime / 2;
1228 if (t2_timeout <= t1_timeout) {
1229 /* the computed T1 would be invalid, so discard T2 */
1230 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1231 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1233 } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1234 /* only T1 is given, and it is valid */
1235 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1236 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1237 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1238 if (t2_timeout <= t1_timeout) {
1239 /* the computed T2 would be invalid, so discard T1 */
1240 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1241 client->lease->t2 = client->lease->lifetime / 2;
1244 /* fall back to the default timeouts */
1245 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1246 client->lease->t1 = client->lease->lifetime / 2;
1247 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1248 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1251 /* arm lifetime timeout */
1252 r = sd_event_add_time(client->event, &client->timeout_expire,
1253 clock_boottime_or_monotonic(),
1254 lifetime_timeout, 10 * USEC_PER_MSEC,
1255 client_timeout_expire, client);
1259 r = sd_event_source_set_priority(client->timeout_expire,
1260 client->event_priority);
1264 r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
1268 log_dhcp_client(client, "lease expires in %s",
1269 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1270 lifetime_timeout - time_now, 0));
1272 /* don't arm earlier timeouts if this has already expired */
1273 if (lifetime_timeout <= time_now)
1276 /* arm T2 timeout */
1277 r = sd_event_add_time(client->event,
1278 &client->timeout_t2,
1279 clock_boottime_or_monotonic(),
1282 client_timeout_t2, client);
1286 r = sd_event_source_set_priority(client->timeout_t2,
1287 client->event_priority);
1291 r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
1295 log_dhcp_client(client, "T2 expires in %s",
1296 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1297 t2_timeout - time_now, 0));
1299 /* don't arm earlier timeout if this has already expired */
1300 if (t2_timeout <= time_now)
1303 /* arm T1 timeout */
1304 r = sd_event_add_time(client->event,
1305 &client->timeout_t1,
1306 clock_boottime_or_monotonic(),
1307 t1_timeout, 10 * USEC_PER_MSEC,
1308 client_timeout_t1, client);
1312 r = sd_event_source_set_priority(client->timeout_t1,
1313 client->event_priority);
1317 r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
1321 log_dhcp_client(client, "T1 expires in %s",
1322 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1323 t1_timeout - time_now, 0));
1328 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1330 DHCP_CLIENT_DONT_DESTROY(client);
1331 int r = 0, notify_event = 0;
1334 assert(client->event);
1337 switch (client->state) {
1338 case DHCP_STATE_SELECTING:
1340 r = client_handle_offer(client, message, len);
1343 client->timeout_resend =
1344 sd_event_source_unref(client->timeout_resend);
1346 client->state = DHCP_STATE_REQUESTING;
1347 client->attempt = 1;
1349 r = sd_event_add_time(client->event,
1350 &client->timeout_resend,
1351 clock_boottime_or_monotonic(),
1353 client_timeout_resend, client);
1357 r = sd_event_source_set_priority(client->timeout_resend,
1358 client->event_priority);
1362 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
1365 } else if (r == -ENOMSG)
1366 /* invalid message, let's ignore it */
1371 case DHCP_STATE_REBOOTING:
1372 case DHCP_STATE_REQUESTING:
1373 case DHCP_STATE_RENEWING:
1374 case DHCP_STATE_REBINDING:
1376 r = client_handle_ack(client, message, len);
1378 client->timeout_resend =
1379 sd_event_source_unref(client->timeout_resend);
1380 client->receive_message =
1381 sd_event_source_unref(client->receive_message);
1382 client->fd = asynchronous_close(client->fd);
1384 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1385 DHCP_STATE_REBOOTING))
1386 notify_event = DHCP_EVENT_IP_ACQUIRE;
1387 else if (r != DHCP_EVENT_IP_ACQUIRE)
1390 client->state = DHCP_STATE_BOUND;
1391 client->attempt = 1;
1393 client->last_addr = client->lease->address;
1395 r = client_set_lease_timeouts(client);
1397 log_dhcp_client(client, "could not set lease timeouts");
1401 r = dhcp_network_bind_udp_socket(client->lease->address,
1404 log_dhcp_client(client, "could not bind UDP socket");
1410 client_initialize_io_events(client, client_receive_message_udp);
1413 client_notify(client, notify_event);
1414 if (client->state == DHCP_STATE_STOPPED)
1418 } else if (r == -EADDRNOTAVAIL) {
1419 /* got a NAK, let's restart the client */
1420 client->timeout_resend =
1421 sd_event_source_unref(client->timeout_resend);
1423 r = client_initialize(client);
1427 r = client_start(client);
1431 log_dhcp_client(client, "REBOOTED");
1434 } else if (r == -ENOMSG)
1435 /* invalid message, let's ignore it */
1440 case DHCP_STATE_BOUND:
1441 r = client_handle_forcerenew(client, message, len);
1443 r = client_timeout_t1(NULL, 0, client);
1446 } else if (r == -ENOMSG)
1447 /* invalid message, let's ignore it */
1452 case DHCP_STATE_INIT:
1453 case DHCP_STATE_INIT_REBOOT:
1457 case DHCP_STATE_STOPPED:
1464 client_stop(client, r);
1469 static int client_receive_message_udp(sd_event_source *s, int fd,
1470 uint32_t revents, void *userdata) {
1471 sd_dhcp_client *client = userdata;
1472 _cleanup_free_ DHCPMessage *message = NULL;
1473 int buflen = 0, len, r;
1474 const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1475 const struct ether_addr *expected_chaddr = NULL;
1476 uint8_t expected_hlen = 0;
1481 r = ioctl(fd, FIONREAD, &buflen);
1486 /* this can't be right */
1489 message = malloc0(buflen);
1493 len = read(fd, message, buflen);
1495 log_dhcp_client(client, "could not receive message from UDP "
1498 } else if ((size_t)len < sizeof(DHCPMessage)) {
1499 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1503 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1504 log_dhcp_client(client, "not a DHCP message: ignoring");
1508 if (message->op != BOOTREPLY) {
1509 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1513 if (message->htype != client->arp_type) {
1514 log_dhcp_client(client, "packet type does not match client type");
1518 if (client->arp_type == ARPHRD_ETHER) {
1519 expected_hlen = ETH_ALEN;
1520 expected_chaddr = (const struct ether_addr *) &client->mac_addr;
1522 /* Non-ethernet links expect zero chaddr */
1524 expected_chaddr = &zero_mac;
1527 if (message->hlen != expected_hlen) {
1528 log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
1532 if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
1533 log_dhcp_client(client, "received chaddr does not match "
1534 "expected: ignoring");
1538 if (client->state != DHCP_STATE_BOUND &&
1539 be32toh(message->xid) != client->xid) {
1540 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1541 so ignore the xid in this case */
1542 log_dhcp_client(client, "received xid (%u) does not match "
1543 "expected (%u): ignoring",
1544 be32toh(message->xid), client->xid);
1548 return client_handle_message(client, message, len);
1551 static int client_receive_message_raw(sd_event_source *s, int fd,
1552 uint32_t revents, void *userdata) {
1553 sd_dhcp_client *client = userdata;
1554 _cleanup_free_ DHCPPacket *packet = NULL;
1555 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1556 struct iovec iov = {};
1557 struct msghdr msg = {
1560 .msg_control = cmsgbuf,
1561 .msg_controllen = sizeof(cmsgbuf),
1563 struct cmsghdr *cmsg;
1564 bool checksum = true;
1565 int buflen = 0, len, r;
1570 r = ioctl(fd, FIONREAD, &buflen);
1575 /* this can't be right */
1578 packet = malloc0(buflen);
1582 iov.iov_base = packet;
1583 iov.iov_len = buflen;
1585 len = recvmsg(fd, &msg, 0);
1587 log_dhcp_client(client, "could not receive message from raw "
1590 } else if ((size_t)len < sizeof(DHCPPacket))
1593 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1594 if (cmsg->cmsg_level == SOL_PACKET &&
1595 cmsg->cmsg_type == PACKET_AUXDATA &&
1596 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1597 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1599 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1604 r = dhcp_packet_verify_headers(packet, len, checksum);
1608 len -= DHCP_IP_UDP_SIZE;
1610 return client_handle_message(client, &packet->dhcp, len);
1613 int sd_dhcp_client_start(sd_dhcp_client *client) {
1616 assert_return(client, -EINVAL);
1618 r = client_initialize(client);
1622 if (client->last_addr)
1623 client->state = DHCP_STATE_INIT_REBOOT;
1625 r = client_start(client);
1627 log_dhcp_client(client, "STARTED on ifindex %i", client->index);
1632 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1633 DHCP_CLIENT_DONT_DESTROY(client);
1635 assert_return(client, -EINVAL);
1637 client_stop(client, DHCP_EVENT_STOP);
1638 client->state = DHCP_STATE_STOPPED;
1643 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1647 assert_return(client, -EINVAL);
1648 assert_return(!client->event, -EBUSY);
1651 client->event = sd_event_ref(event);
1653 r = sd_event_default(&client->event);
1658 client->event_priority = priority;
1663 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1664 assert_return(client, -EINVAL);
1666 client->event = sd_event_unref(client->event);
1671 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1675 return client->event;
1678 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1680 assert_se(REFCNT_INC(client->n_ref) >= 2);
1685 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1686 if (client && REFCNT_DEC(client->n_ref) == 0) {
1687 log_dhcp_client(client, "FREE");
1689 client_initialize(client);
1691 client->receive_message =
1692 sd_event_source_unref(client->receive_message);
1694 sd_dhcp_client_detach_event(client);
1696 sd_dhcp_lease_unref(client->lease);
1698 free(client->req_opts);
1699 free(client->hostname);
1700 free(client->vendor_class_identifier);
1707 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1708 _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1710 assert_return(ret, -EINVAL);
1712 client = new0(sd_dhcp_client, 1);
1716 client->n_ref = REFCNT_INIT;
1717 client->state = DHCP_STATE_INIT;
1720 client->attempt = 1;
1721 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1723 client->req_opts_size = ELEMENTSOF(default_req_opts);
1725 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1726 if (!client->req_opts)