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>
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 INFINIBAND_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,
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.type;
243 *data = client->client_id.raw.data;
244 *data_len = client->client_id_len - sizeof(client->client_id.type);
250 int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
251 const uint8_t *data, size_t data_len) {
252 DHCP_CLIENT_DONT_DESTROY(client);
253 bool need_restart = false;
255 assert_return(client, -EINVAL);
256 assert_return(data, -EINVAL);
257 assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
261 if (data_len != ETH_ALEN)
264 case ARPHRD_INFINIBAND:
265 if (data_len != INFINIBAND_ALEN)
272 if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
273 client->client_id.type == type &&
274 memcmp(&client->client_id.raw.data, data, data_len) == 0)
277 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
278 log_dhcp_client(client, "Changing client ID on running DHCP "
279 "client, restarting");
281 client_stop(client, DHCP_EVENT_STOP);
284 client->client_id.type = type;
285 memcpy(&client->client_id.raw.data, data, data_len);
286 client->client_id_len = data_len + sizeof (client->client_id.type);
288 if (need_restart && client->state != DHCP_STATE_STOPPED)
289 sd_dhcp_client_start(client);
294 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
295 const char *hostname) {
296 char *new_hostname = NULL;
298 assert_return(client, -EINVAL);
300 if (streq_ptr(client->hostname, hostname))
304 new_hostname = strdup(hostname);
309 free(client->hostname);
310 client->hostname = new_hostname;
315 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
317 char *new_vci = NULL;
319 assert_return(client, -EINVAL);
321 new_vci = strdup(vci);
325 free(client->vendor_class_identifier);
327 client->vendor_class_identifier = new_vci;
332 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
333 assert_return(client, -EINVAL);
334 assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
341 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
342 assert_return(client, -EINVAL);
343 assert_return(ret, -EINVAL);
345 if (client->state != DHCP_STATE_BOUND &&
346 client->state != DHCP_STATE_RENEWING &&
347 client->state != DHCP_STATE_REBINDING)
348 return -EADDRNOTAVAIL;
350 *ret = sd_dhcp_lease_ref(client->lease);
355 static void client_notify(sd_dhcp_client *client, int event) {
357 client->cb(client, event, client->userdata);
360 static int client_initialize(sd_dhcp_client *client) {
361 assert_return(client, -EINVAL);
363 client->receive_message =
364 sd_event_source_unref(client->receive_message);
366 client->fd = asynchronous_close(client->fd);
368 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
370 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
371 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
372 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
376 client->state = DHCP_STATE_INIT;
380 client->lease = sd_dhcp_lease_unref(client->lease);
385 static void client_stop(sd_dhcp_client *client, int error) {
389 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
390 else if (error == DHCP_EVENT_STOP)
391 log_dhcp_client(client, "STOPPED");
393 log_dhcp_client(client, "STOPPED: Unknown event");
395 client_notify(client, error);
397 client_initialize(client);
400 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
401 uint8_t type, size_t *_optlen, size_t *_optoffset) {
402 _cleanup_free_ DHCPPacket *packet;
403 size_t optlen, optoffset, size;
410 assert(client->start_time);
414 assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
416 optlen = DHCP_MIN_OPTIONS_SIZE;
417 size = sizeof(DHCPPacket) + optlen;
419 packet = malloc0(size);
423 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
424 client->arp_type, optlen, &optoffset);
428 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
429 refuse to issue an DHCP lease if 'secs' is set to zero */
430 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
433 assert(time_now >= client->start_time);
435 /* seconds between sending first and last DISCOVER
436 * must always be strictly positive to deal with broken servers */
437 secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
438 packet->dhcp.secs = htobe16(secs);
440 /* RFC2132 section 4.1
441 A client that cannot receive unicast IP datagrams until its protocol
442 software has been configured with an IP address SHOULD set the
443 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
444 DHCPREQUEST messages that client sends. The BROADCAST bit will
445 provide a hint to the DHCP server and BOOTP relay agent to broadcast
446 any messages to the client on the client's subnet.
448 Note: some interfaces needs this to be enabled, but some networks
449 needs this to be disabled as broadcasts are filteretd, so this
450 needs to be configurable */
451 if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
452 packet->dhcp.flags = htobe16(0x8000);
454 /* RFC2132 section 4.1.1:
455 The client MUST include its hardware address in the ’chaddr’ field, if
456 necessary for delivery of DHCP reply messages. Non-Ethernet
457 interfaces will leave 'chaddr' empty and use the client identifier
458 instead (eg, RFC 4390 section 2.1).
460 if (client->arp_type == ARPHRD_ETHER)
461 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
463 /* If no client identifier exists, construct an RFC 4361-compliant one */
464 if (client->client_id_len == 0) {
467 client->client_id.type = 255;
469 r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
473 r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len);
477 client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
480 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
481 Identifier option is not set */
482 if (client->client_id_len) {
483 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
484 DHCP_OPTION_CLIENT_IDENTIFIER,
485 client->client_id_len,
491 /* RFC2131 section 3.5:
492 in its initial DHCPDISCOVER or DHCPREQUEST message, a
493 client may provide the server with a list of specific
494 parameters the client is interested in. If the client
495 includes a list of parameters in a DHCPDISCOVER message,
496 it MUST include that list in any subsequent DHCPREQUEST
499 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
500 DHCP_OPTION_PARAMETER_REQUEST_LIST,
501 client->req_opts_size, client->req_opts);
505 /* RFC2131 section 3.5:
506 The client SHOULD include the ’maximum DHCP message size’ option to
507 let the server know how large the server may make its DHCP messages.
509 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
510 than the defined default size unless the Maximum Messge Size option
513 RFC3442 "Requirements to Avoid Sizing Constraints":
514 Because a full routing table can be quite large, the standard 576
515 octet maximum size for a DHCP message may be too short to contain
516 some legitimate Classless Static Route options. Because of this,
517 clients implementing the Classless Static Route option SHOULD send a
518 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
519 stack is capable of receiving larger IP datagrams. In this case, the
520 client SHOULD set the value of this option to at least the MTU of the
521 interface that the client is configuring. The client MAY set the
522 value of this option higher, up to the size of the largest UDP packet
523 it is prepared to accept. (Note that the value specified in the
524 Maximum DHCP Message Size option is the total maximum packet size,
525 including IP and UDP headers.)
527 max_size = htobe16(size);
528 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
529 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
535 *_optoffset = optoffset;
542 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
544 dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
545 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
547 return dhcp_network_send_raw_socket(client->fd, &client->link,
551 static int client_send_discover(sd_dhcp_client *client) {
552 _cleanup_free_ DHCPPacket *discover = NULL;
553 size_t optoffset, optlen;
557 assert(client->state == DHCP_STATE_INIT ||
558 client->state == DHCP_STATE_SELECTING);
560 r = client_message_init(client, &discover, DHCP_DISCOVER,
561 &optlen, &optoffset);
565 /* the client may suggest values for the network address
566 and lease time in the DHCPDISCOVER message. The client may include
567 the ’requested IP address’ option to suggest that a particular IP
568 address be assigned, and may include the ’IP address lease time’
569 option to suggest the lease time it would like.
571 if (client->last_addr != INADDR_ANY) {
572 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
573 DHCP_OPTION_REQUESTED_IP_ADDRESS,
574 4, &client->last_addr);
579 /* it is unclear from RFC 2131 if client should send hostname in
580 DHCPDISCOVER but dhclient does and so we do as well
582 if (client->hostname) {
583 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
584 DHCP_OPTION_HOST_NAME,
585 strlen(client->hostname), client->hostname);
590 if (client->vendor_class_identifier) {
591 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
592 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
593 strlen(client->vendor_class_identifier),
594 client->vendor_class_identifier);
599 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
600 DHCP_OPTION_END, 0, NULL);
604 /* We currently ignore:
605 The client SHOULD wait a random time between one and ten seconds to
606 desynchronize the use of DHCP at startup.
608 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
612 log_dhcp_client(client, "DISCOVER");
617 static int client_send_request(sd_dhcp_client *client) {
618 _cleanup_free_ DHCPPacket *request = NULL;
619 size_t optoffset, optlen;
622 r = client_message_init(client, &request, DHCP_REQUEST,
623 &optlen, &optoffset);
627 switch (client->state) {
628 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
629 SELECTING should be REQUESTING)
632 case DHCP_STATE_REQUESTING:
633 /* Client inserts the address of the selected server in ’server
634 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
635 filled in with the yiaddr value from the chosen DHCPOFFER.
638 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
639 DHCP_OPTION_SERVER_IDENTIFIER,
640 4, &client->lease->server_address);
644 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
645 DHCP_OPTION_REQUESTED_IP_ADDRESS,
646 4, &client->lease->address);
652 case DHCP_STATE_INIT_REBOOT:
653 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
654 option MUST be filled in with client’s notion of its previously
655 assigned address. ’ciaddr’ MUST be zero.
657 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
658 DHCP_OPTION_REQUESTED_IP_ADDRESS,
659 4, &client->last_addr);
664 case DHCP_STATE_RENEWING:
665 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
666 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
667 client’s IP address.
671 case DHCP_STATE_REBINDING:
672 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
673 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
674 client’s IP address.
676 This message MUST be broadcast to the 0xffffffff IP broadcast address.
678 request->dhcp.ciaddr = client->lease->address;
682 case DHCP_STATE_INIT:
683 case DHCP_STATE_SELECTING:
684 case DHCP_STATE_REBOOTING:
685 case DHCP_STATE_BOUND:
686 case DHCP_STATE_STOPPED:
690 if (client->hostname) {
691 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
692 DHCP_OPTION_HOST_NAME,
693 strlen(client->hostname), client->hostname);
698 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
699 DHCP_OPTION_END, 0, NULL);
703 if (client->state == DHCP_STATE_RENEWING) {
704 r = dhcp_network_send_udp_socket(client->fd,
705 client->lease->server_address,
708 sizeof(DHCPMessage) + optoffset);
710 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
715 switch (client->state) {
716 case DHCP_STATE_REQUESTING:
717 log_dhcp_client(client, "REQUEST (requesting)");
719 case DHCP_STATE_INIT_REBOOT:
720 log_dhcp_client(client, "REQUEST (init-reboot)");
722 case DHCP_STATE_RENEWING:
723 log_dhcp_client(client, "REQUEST (renewing)");
725 case DHCP_STATE_REBINDING:
726 log_dhcp_client(client, "REQUEST (rebinding)");
729 log_dhcp_client(client, "REQUEST (invalid)");
736 static int client_start(sd_dhcp_client *client);
738 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
740 sd_dhcp_client *client = userdata;
741 DHCP_CLIENT_DONT_DESTROY(client);
742 usec_t next_timeout = 0;
749 assert(client->event);
751 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
755 switch (client->state) {
756 case DHCP_STATE_RENEWING:
758 time_left = (client->lease->t2 - client->lease->t1) / 2;
762 next_timeout = time_now + time_left * USEC_PER_SEC;
766 case DHCP_STATE_REBINDING:
768 time_left = (client->lease->lifetime - client->lease->t2) / 2;
772 next_timeout = time_now + time_left * USEC_PER_SEC;
775 case DHCP_STATE_REBOOTING:
776 /* start over as we did not receive a timely ack or nak */
777 r = client_initialize(client);
781 r = client_start(client);
785 log_dhcp_client(client, "REBOOTED");
789 case DHCP_STATE_INIT:
790 case DHCP_STATE_INIT_REBOOT:
791 case DHCP_STATE_SELECTING:
792 case DHCP_STATE_REQUESTING:
793 case DHCP_STATE_BOUND:
795 if (client->attempt < 64)
796 client->attempt *= 2;
798 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
802 case DHCP_STATE_STOPPED:
807 next_timeout += (random_u32() & 0x1fffff);
809 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
811 r = sd_event_add_time(client->event,
812 &client->timeout_resend,
813 clock_boottime_or_monotonic(),
814 next_timeout, 10 * USEC_PER_MSEC,
815 client_timeout_resend, client);
819 r = sd_event_source_set_priority(client->timeout_resend,
820 client->event_priority);
824 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
828 switch (client->state) {
829 case DHCP_STATE_INIT:
830 r = client_send_discover(client);
832 client->state = DHCP_STATE_SELECTING;
835 if (client->attempt >= 64)
841 case DHCP_STATE_SELECTING:
842 r = client_send_discover(client);
843 if (r < 0 && client->attempt >= 64)
848 case DHCP_STATE_INIT_REBOOT:
849 case DHCP_STATE_REQUESTING:
850 case DHCP_STATE_RENEWING:
851 case DHCP_STATE_REBINDING:
852 r = client_send_request(client);
853 if (r < 0 && client->attempt >= 64)
856 if (client->state == DHCP_STATE_INIT_REBOOT)
857 client->state = DHCP_STATE_REBOOTING;
859 client->request_sent = time_now;
863 case DHCP_STATE_REBOOTING:
864 case DHCP_STATE_BOUND:
868 case DHCP_STATE_STOPPED:
876 client_stop(client, r);
878 /* Errors were dealt with when stopping the client, don't spill
879 errors into the event loop handler */
883 static int client_initialize_io_events(sd_dhcp_client *client,
884 sd_event_io_handler_t io_callback) {
888 assert(client->event);
890 r = sd_event_add_io(client->event, &client->receive_message,
891 client->fd, EPOLLIN, io_callback,
896 r = sd_event_source_set_priority(client->receive_message,
897 client->event_priority);
901 r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
907 client_stop(client, r);
912 static int client_initialize_time_events(sd_dhcp_client *client) {
916 assert(client->event);
918 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
920 r = sd_event_add_time(client->event,
921 &client->timeout_resend,
922 clock_boottime_or_monotonic(),
924 client_timeout_resend, client);
928 r = sd_event_source_set_priority(client->timeout_resend,
929 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;
1056 lease->address = offer->yiaddr;
1058 if (lease->address == INADDR_ANY ||
1059 lease->server_address == INADDR_ANY ||
1060 lease->lifetime == 0) {
1061 log_dhcp_client(client, "received lease lacks address, server "
1062 "address or lease lifetime, ignoring");
1066 if (lease->subnet_mask == INADDR_ANY) {
1067 r = dhcp_lease_set_default_subnet_mask(lease);
1069 log_dhcp_client(client, "received lease lacks subnet "
1070 "mask, and a fallback one can not be "
1071 "generated, ignoring");
1076 sd_dhcp_lease_unref(client->lease);
1077 client->lease = lease;
1080 log_dhcp_client(client, "OFFER");
1085 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
1089 r = dhcp_option_parse(force, len, NULL, NULL);
1090 if (r != DHCP_FORCERENEW)
1093 log_dhcp_client(client, "FORCERENEW");
1098 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
1100 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
1103 r = dhcp_lease_new(&lease);
1107 if (client->client_id_len) {
1108 r = dhcp_lease_set_client_id(lease,
1109 (uint8_t *) &client->client_id,
1110 client->client_id_len);
1115 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
1116 if (r == DHCP_NAK) {
1117 log_dhcp_client(client, "NAK");
1118 return -EADDRNOTAVAIL;
1121 if (r != DHCP_ACK) {
1122 log_dhcp_client(client, "received message was not an ACK, ignoring");
1126 lease->next_server = ack->siaddr;
1128 lease->address = ack->yiaddr;
1130 if (lease->address == INADDR_ANY ||
1131 lease->server_address == INADDR_ANY ||
1132 lease->lifetime == 0) {
1133 log_dhcp_client(client, "received lease lacks address, server "
1134 "address or lease lifetime, ignoring");
1138 if (lease->subnet_mask == INADDR_ANY) {
1139 r = dhcp_lease_set_default_subnet_mask(lease);
1141 log_dhcp_client(client, "received lease lacks subnet "
1142 "mask, and a fallback one can not be "
1143 "generated, ignoring");
1148 r = DHCP_EVENT_IP_ACQUIRE;
1149 if (client->lease) {
1150 if (client->lease->address != lease->address ||
1151 client->lease->subnet_mask != lease->subnet_mask ||
1152 client->lease->router != lease->router) {
1153 r = DHCP_EVENT_IP_CHANGE;
1155 r = DHCP_EVENT_RENEW;
1157 client->lease = sd_dhcp_lease_unref(client->lease);
1160 client->lease = lease;
1163 log_dhcp_client(client, "ACK");
1168 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1169 uint32_t lifetime, double factor) {
1171 assert(client->request_sent);
1174 return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1175 + (random_u32() & 0x1fffff);
1178 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1180 uint64_t lifetime_timeout;
1181 uint64_t t2_timeout;
1182 uint64_t t1_timeout;
1183 char time_string[FORMAT_TIMESPAN_MAX];
1187 assert(client->event);
1188 assert(client->lease);
1189 assert(client->lease->lifetime);
1191 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1192 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1193 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1195 /* don't set timers for infinite leases */
1196 if (client->lease->lifetime == 0xffffffff)
1199 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1202 assert(client->request_sent <= time_now);
1204 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1205 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1206 if (client->lease->t1 && client->lease->t2) {
1207 /* both T1 and T2 are given */
1208 if (client->lease->t1 < client->lease->t2 &&
1209 client->lease->t2 < client->lease->lifetime) {
1210 /* they are both valid */
1211 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1212 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1215 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1216 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1217 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1218 client->lease->t1 = client->lease->lifetime / 2;
1220 } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1221 /* only T2 is given, and it is valid */
1222 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1223 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1224 client->lease->t1 = client->lease->lifetime / 2;
1225 if (t2_timeout <= t1_timeout) {
1226 /* the computed T1 would be invalid, so discard T2 */
1227 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1228 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1230 } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1231 /* only T1 is given, and it is valid */
1232 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1233 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1234 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1235 if (t2_timeout <= t1_timeout) {
1236 /* the computed T2 would be invalid, so discard T1 */
1237 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1238 client->lease->t2 = client->lease->lifetime / 2;
1241 /* fall back to the default timeouts */
1242 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1243 client->lease->t1 = client->lease->lifetime / 2;
1244 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1245 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1248 /* arm lifetime timeout */
1249 r = sd_event_add_time(client->event, &client->timeout_expire,
1250 clock_boottime_or_monotonic(),
1251 lifetime_timeout, 10 * USEC_PER_MSEC,
1252 client_timeout_expire, client);
1256 r = sd_event_source_set_priority(client->timeout_expire,
1257 client->event_priority);
1261 r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
1265 log_dhcp_client(client, "lease expires in %s",
1266 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1267 lifetime_timeout - time_now, 0));
1269 /* don't arm earlier timeouts if this has already expired */
1270 if (lifetime_timeout <= time_now)
1273 /* arm T2 timeout */
1274 r = sd_event_add_time(client->event,
1275 &client->timeout_t2,
1276 clock_boottime_or_monotonic(),
1279 client_timeout_t2, client);
1283 r = sd_event_source_set_priority(client->timeout_t2,
1284 client->event_priority);
1288 r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
1292 log_dhcp_client(client, "T2 expires in %s",
1293 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1294 t2_timeout - time_now, 0));
1296 /* don't arm earlier timeout if this has already expired */
1297 if (t2_timeout <= time_now)
1300 /* arm T1 timeout */
1301 r = sd_event_add_time(client->event,
1302 &client->timeout_t1,
1303 clock_boottime_or_monotonic(),
1304 t1_timeout, 10 * USEC_PER_MSEC,
1305 client_timeout_t1, client);
1309 r = sd_event_source_set_priority(client->timeout_t1,
1310 client->event_priority);
1314 r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
1318 log_dhcp_client(client, "T1 expires in %s",
1319 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1320 t1_timeout - time_now, 0));
1325 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1327 DHCP_CLIENT_DONT_DESTROY(client);
1328 int r = 0, notify_event = 0;
1331 assert(client->event);
1334 switch (client->state) {
1335 case DHCP_STATE_SELECTING:
1337 r = client_handle_offer(client, message, len);
1340 client->timeout_resend =
1341 sd_event_source_unref(client->timeout_resend);
1343 client->state = DHCP_STATE_REQUESTING;
1344 client->attempt = 1;
1346 r = sd_event_add_time(client->event,
1347 &client->timeout_resend,
1348 clock_boottime_or_monotonic(),
1350 client_timeout_resend, client);
1354 r = sd_event_source_set_priority(client->timeout_resend,
1355 client->event_priority);
1359 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
1362 } else if (r == -ENOMSG)
1363 /* invalid message, let's ignore it */
1368 case DHCP_STATE_REBOOTING:
1369 case DHCP_STATE_REQUESTING:
1370 case DHCP_STATE_RENEWING:
1371 case DHCP_STATE_REBINDING:
1373 r = client_handle_ack(client, message, len);
1375 client->timeout_resend =
1376 sd_event_source_unref(client->timeout_resend);
1377 client->receive_message =
1378 sd_event_source_unref(client->receive_message);
1379 client->fd = asynchronous_close(client->fd);
1381 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1382 DHCP_STATE_REBOOTING))
1383 notify_event = DHCP_EVENT_IP_ACQUIRE;
1384 else if (r != DHCP_EVENT_IP_ACQUIRE)
1387 client->state = DHCP_STATE_BOUND;
1388 client->attempt = 1;
1390 client->last_addr = client->lease->address;
1392 r = client_set_lease_timeouts(client);
1394 log_dhcp_client(client, "could not set lease timeouts");
1398 r = dhcp_network_bind_udp_socket(client->lease->address,
1401 log_dhcp_client(client, "could not bind UDP socket");
1407 client_initialize_io_events(client, client_receive_message_udp);
1410 client_notify(client, notify_event);
1411 if (client->state == DHCP_STATE_STOPPED)
1415 } else if (r == -EADDRNOTAVAIL) {
1416 /* got a NAK, let's restart the client */
1417 client->timeout_resend =
1418 sd_event_source_unref(client->timeout_resend);
1420 r = client_initialize(client);
1424 r = client_start(client);
1428 log_dhcp_client(client, "REBOOTED");
1431 } else if (r == -ENOMSG)
1432 /* invalid message, let's ignore it */
1437 case DHCP_STATE_BOUND:
1438 r = client_handle_forcerenew(client, message, len);
1440 r = client_timeout_t1(NULL, 0, client);
1443 } else if (r == -ENOMSG)
1444 /* invalid message, let's ignore it */
1449 case DHCP_STATE_INIT:
1450 case DHCP_STATE_INIT_REBOOT:
1454 case DHCP_STATE_STOPPED:
1461 client_stop(client, r);
1466 static int client_receive_message_udp(sd_event_source *s, int fd,
1467 uint32_t revents, void *userdata) {
1468 sd_dhcp_client *client = userdata;
1469 _cleanup_free_ DHCPMessage *message = NULL;
1470 int buflen = 0, len, r;
1471 const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1473 uint8_t expected_hlen = 0;
1478 r = ioctl(fd, FIONREAD, &buflen);
1483 /* this can't be right */
1486 message = malloc0(buflen);
1490 len = read(fd, message, buflen);
1492 log_dhcp_client(client, "could not receive message from UDP "
1495 } else if ((size_t)len < sizeof(DHCPMessage)) {
1496 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1500 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1501 log_dhcp_client(client, "not a DHCP message: ignoring");
1505 if (message->op != BOOTREPLY) {
1506 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1510 if (message->htype != client->arp_type) {
1511 log_dhcp_client(client, "packet type does not match client type");
1515 if (client->arp_type == ARPHRD_ETHER) {
1516 expected_hlen = ETH_ALEN;
1517 expect_chaddr = true;
1519 /* Non-ethernet links expect zero chaddr */
1521 expect_chaddr = false;
1524 if (message->hlen != expected_hlen) {
1525 log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
1529 if (memcmp(&message->chaddr[0], expect_chaddr ?
1530 (void *)&client->mac_addr :
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)