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_MAC_ADDR_LEN INFINIBAND_ALEN
43 struct sd_dhcp_client {
49 sd_event_source *timeout_resend;
52 union sockaddr_union link;
53 sd_event_source *receive_message;
54 bool request_broadcast;
56 size_t req_opts_allocated;
61 struct ether_addr mac_addr;
63 uint8_t mac_addr[MAX_MAC_ADDR_LEN];
67 char *vendor_class_identifier;
73 sd_event_source *timeout_t1;
74 sd_event_source *timeout_t2;
75 sd_event_source *timeout_expire;
76 sd_dhcp_client_cb_t cb;
81 static const uint8_t default_req_opts[] = {
82 DHCP_OPTION_SUBNET_MASK,
84 DHCP_OPTION_HOST_NAME,
85 DHCP_OPTION_DOMAIN_NAME,
86 DHCP_OPTION_DOMAIN_NAME_SERVER,
87 DHCP_OPTION_NTP_SERVER,
90 static int client_receive_message_raw(sd_event_source *s, int fd,
91 uint32_t revents, void *userdata);
92 static int client_receive_message_udp(sd_event_source *s, int fd,
93 uint32_t revents, void *userdata);
94 static void client_stop(sd_dhcp_client *client, int error);
96 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
98 assert_return(client, -EINVAL);
101 client->userdata = userdata;
106 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
107 assert_return(client, -EINVAL);
109 client->request_broadcast = !!broadcast;
114 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
117 assert_return(client, -EINVAL);
118 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
119 DHCP_STATE_STOPPED), -EBUSY);
122 case DHCP_OPTION_PAD:
123 case DHCP_OPTION_OVERLOAD:
124 case DHCP_OPTION_MESSAGE_TYPE:
125 case DHCP_OPTION_PARAMETER_REQUEST_LIST:
126 case DHCP_OPTION_END:
133 for (i = 0; i < client->req_opts_size; i++)
134 if (client->req_opts[i] == option)
137 if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
138 client->req_opts_size + 1))
141 client->req_opts[client->req_opts_size++] = option;
146 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
147 const struct in_addr *last_addr) {
148 assert_return(client, -EINVAL);
149 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
150 DHCP_STATE_STOPPED), -EBUSY);
153 client->last_addr = last_addr->s_addr;
155 client->last_addr = INADDR_ANY;
160 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
161 assert_return(client, -EINVAL);
162 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
163 DHCP_STATE_STOPPED), -EBUSY);
164 assert_return(interface_index > 0, -EINVAL);
166 client->index = interface_index;
171 int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
172 size_t addr_len, uint16_t arp_type) {
173 DHCP_CLIENT_DONT_DESTROY(client);
174 bool need_restart = false;
176 assert_return(client, -EINVAL);
177 assert_return(addr, -EINVAL);
178 assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
179 assert_return(arp_type > 0, -EINVAL);
181 if (arp_type == ARPHRD_ETHER)
182 assert_return(addr_len == ETH_ALEN, -EINVAL);
183 else if (arp_type == ARPHRD_INFINIBAND)
184 assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
188 if (client->mac_addr_len == addr_len &&
189 memcmp(&client->mac_addr, addr, addr_len) == 0)
192 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
193 log_dhcp_client(client, "Changing MAC address on running DHCP "
194 "client, restarting");
196 client_stop(client, DHCP_EVENT_STOP);
199 memcpy(&client->mac_addr, addr, addr_len);
200 client->mac_addr_len = addr_len;
201 client->arp_type = arp_type;
203 memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
204 client->client_id.type = 0x01;
206 if (need_restart && client->state != DHCP_STATE_STOPPED)
207 sd_dhcp_client_start(client);
212 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
213 const char *hostname) {
214 char *new_hostname = NULL;
216 assert_return(client, -EINVAL);
218 if (streq_ptr(client->hostname, hostname))
222 new_hostname = strdup(hostname);
227 free(client->hostname);
228 client->hostname = new_hostname;
233 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
235 char *new_vci = NULL;
237 assert_return(client, -EINVAL);
239 new_vci = strdup(vci);
243 free(client->vendor_class_identifier);
245 client->vendor_class_identifier = new_vci;
250 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
251 assert_return(client, -EINVAL);
252 assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
259 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
260 assert_return(client, -EINVAL);
261 assert_return(ret, -EINVAL);
263 if (client->state != DHCP_STATE_BOUND &&
264 client->state != DHCP_STATE_RENEWING &&
265 client->state != DHCP_STATE_REBINDING)
266 return -EADDRNOTAVAIL;
268 *ret = sd_dhcp_lease_ref(client->lease);
273 static void client_notify(sd_dhcp_client *client, int event) {
275 client->cb(client, event, client->userdata);
278 static int client_initialize(sd_dhcp_client *client) {
279 assert_return(client, -EINVAL);
281 client->receive_message =
282 sd_event_source_unref(client->receive_message);
284 client->fd = asynchronous_close(client->fd);
286 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
288 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
289 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
290 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
294 client->state = DHCP_STATE_INIT;
298 client->lease = sd_dhcp_lease_unref(client->lease);
303 static void client_stop(sd_dhcp_client *client, int error) {
307 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
308 else if (error == DHCP_EVENT_STOP)
309 log_dhcp_client(client, "STOPPED");
311 log_dhcp_client(client, "STOPPED: Unknown event");
313 client_notify(client, error);
315 client_initialize(client);
318 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
319 uint8_t type, size_t *_optlen, size_t *_optoffset) {
320 _cleanup_free_ DHCPPacket *packet;
321 size_t optlen, optoffset, size;
328 assert(client->start_time);
332 assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
334 optlen = DHCP_MIN_OPTIONS_SIZE;
335 size = sizeof(DHCPPacket) + optlen;
337 packet = malloc0(size);
341 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
342 client->arp_type, optlen, &optoffset);
346 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
347 refuse to issue an DHCP lease if 'secs' is set to zero */
348 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
351 assert(time_now >= client->start_time);
353 /* seconds between sending first and last DISCOVER
354 * must always be strictly positive to deal with broken servers */
355 secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
356 packet->dhcp.secs = htobe16(secs);
358 /* RFC2132 section 4.1
359 A client that cannot receive unicast IP datagrams until its protocol
360 software has been configured with an IP address SHOULD set the
361 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
362 DHCPREQUEST messages that client sends. The BROADCAST bit will
363 provide a hint to the DHCP server and BOOTP relay agent to broadcast
364 any messages to the client on the client's subnet.
366 Note: some interfaces needs this to be enabled, but some networks
367 needs this to be disabled as broadcasts are filteretd, so this
368 needs to be configurable */
369 if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
370 packet->dhcp.flags = htobe16(0x8000);
372 /* RFC2132 section 4.1.1:
373 The client MUST include its hardware address in the ’chaddr’ field, if
374 necessary for delivery of DHCP reply messages. Non-Ethernet
375 interfaces will leave 'chaddr' empty and use the client identifier
376 instead (eg, RFC 4390 section 2.1).
378 if (client->arp_type == ARPHRD_ETHER)
379 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
381 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
382 Identifier option is not set */
383 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
384 DHCP_OPTION_CLIENT_IDENTIFIER,
385 sizeof(client->client_id), &client->client_id);
390 /* RFC2131 section 3.5:
391 in its initial DHCPDISCOVER or DHCPREQUEST message, a
392 client may provide the server with a list of specific
393 parameters the client is interested in. If the client
394 includes a list of parameters in a DHCPDISCOVER message,
395 it MUST include that list in any subsequent DHCPREQUEST
398 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
399 DHCP_OPTION_PARAMETER_REQUEST_LIST,
400 client->req_opts_size, client->req_opts);
404 /* RFC2131 section 3.5:
405 The client SHOULD include the ’maximum DHCP message size’ option to
406 let the server know how large the server may make its DHCP messages.
408 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
409 than the defined default size unless the Maximum Messge Size option
412 RFC3442 "Requirements to Avoid Sizing Constraints":
413 Because a full routing table can be quite large, the standard 576
414 octet maximum size for a DHCP message may be too short to contain
415 some legitimate Classless Static Route options. Because of this,
416 clients implementing the Classless Static Route option SHOULD send a
417 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
418 stack is capable of receiving larger IP datagrams. In this case, the
419 client SHOULD set the value of this option to at least the MTU of the
420 interface that the client is configuring. The client MAY set the
421 value of this option higher, up to the size of the largest UDP packet
422 it is prepared to accept. (Note that the value specified in the
423 Maximum DHCP Message Size option is the total maximum packet size,
424 including IP and UDP headers.)
426 max_size = htobe16(size);
427 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
428 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
434 *_optoffset = optoffset;
441 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
443 dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
444 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
446 return dhcp_network_send_raw_socket(client->fd, &client->link,
450 static int client_send_discover(sd_dhcp_client *client) {
451 _cleanup_free_ DHCPPacket *discover = NULL;
452 size_t optoffset, optlen;
456 assert(client->state == DHCP_STATE_INIT ||
457 client->state == DHCP_STATE_SELECTING);
459 r = client_message_init(client, &discover, DHCP_DISCOVER,
460 &optlen, &optoffset);
464 /* the client may suggest values for the network address
465 and lease time in the DHCPDISCOVER message. The client may include
466 the ’requested IP address’ option to suggest that a particular IP
467 address be assigned, and may include the ’IP address lease time’
468 option to suggest the lease time it would like.
470 if (client->last_addr != INADDR_ANY) {
471 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
472 DHCP_OPTION_REQUESTED_IP_ADDRESS,
473 4, &client->last_addr);
478 /* it is unclear from RFC 2131 if client should send hostname in
479 DHCPDISCOVER but dhclient does and so we do as well
481 if (client->hostname) {
482 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
483 DHCP_OPTION_HOST_NAME,
484 strlen(client->hostname), client->hostname);
489 if (client->vendor_class_identifier) {
490 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
491 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
492 strlen(client->vendor_class_identifier),
493 client->vendor_class_identifier);
498 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
499 DHCP_OPTION_END, 0, NULL);
503 /* We currently ignore:
504 The client SHOULD wait a random time between one and ten seconds to
505 desynchronize the use of DHCP at startup.
507 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
511 log_dhcp_client(client, "DISCOVER");
516 static int client_send_request(sd_dhcp_client *client) {
517 _cleanup_free_ DHCPPacket *request = NULL;
518 size_t optoffset, optlen;
521 r = client_message_init(client, &request, DHCP_REQUEST,
522 &optlen, &optoffset);
526 switch (client->state) {
527 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
528 SELECTING should be REQUESTING)
531 case DHCP_STATE_REQUESTING:
532 /* Client inserts the address of the selected server in ’server
533 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
534 filled in with the yiaddr value from the chosen DHCPOFFER.
537 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
538 DHCP_OPTION_SERVER_IDENTIFIER,
539 4, &client->lease->server_address);
543 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
544 DHCP_OPTION_REQUESTED_IP_ADDRESS,
545 4, &client->lease->address);
551 case DHCP_STATE_INIT_REBOOT:
552 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
553 option MUST be filled in with client’s notion of its previously
554 assigned address. ’ciaddr’ MUST be zero.
556 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
557 DHCP_OPTION_REQUESTED_IP_ADDRESS,
558 4, &client->last_addr);
563 case DHCP_STATE_RENEWING:
564 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
565 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
566 client’s IP address.
570 case DHCP_STATE_REBINDING:
571 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
572 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
573 client’s IP address.
575 This message MUST be broadcast to the 0xffffffff IP broadcast address.
577 request->dhcp.ciaddr = client->lease->address;
581 case DHCP_STATE_INIT:
582 case DHCP_STATE_SELECTING:
583 case DHCP_STATE_REBOOTING:
584 case DHCP_STATE_BOUND:
585 case DHCP_STATE_STOPPED:
589 if (client->hostname) {
590 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
591 DHCP_OPTION_HOST_NAME,
592 strlen(client->hostname), client->hostname);
597 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
598 DHCP_OPTION_END, 0, NULL);
602 if (client->state == DHCP_STATE_RENEWING) {
603 r = dhcp_network_send_udp_socket(client->fd,
604 client->lease->server_address,
607 sizeof(DHCPMessage) + optoffset);
609 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
614 switch (client->state) {
615 case DHCP_STATE_REQUESTING:
616 log_dhcp_client(client, "REQUEST (requesting)");
618 case DHCP_STATE_INIT_REBOOT:
619 log_dhcp_client(client, "REQUEST (init-reboot)");
621 case DHCP_STATE_RENEWING:
622 log_dhcp_client(client, "REQUEST (renewing)");
624 case DHCP_STATE_REBINDING:
625 log_dhcp_client(client, "REQUEST (rebinding)");
628 log_dhcp_client(client, "REQUEST (invalid)");
635 static int client_start(sd_dhcp_client *client);
637 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
639 sd_dhcp_client *client = userdata;
640 DHCP_CLIENT_DONT_DESTROY(client);
641 usec_t next_timeout = 0;
648 assert(client->event);
650 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
654 switch (client->state) {
655 case DHCP_STATE_RENEWING:
657 time_left = (client->lease->t2 - client->lease->t1) / 2;
661 next_timeout = time_now + time_left * USEC_PER_SEC;
665 case DHCP_STATE_REBINDING:
667 time_left = (client->lease->lifetime - client->lease->t2) / 2;
671 next_timeout = time_now + time_left * USEC_PER_SEC;
674 case DHCP_STATE_REBOOTING:
675 /* start over as we did not receive a timely ack or nak */
676 r = client_initialize(client);
680 r = client_start(client);
684 log_dhcp_client(client, "REBOOTED");
688 case DHCP_STATE_INIT:
689 case DHCP_STATE_INIT_REBOOT:
690 case DHCP_STATE_SELECTING:
691 case DHCP_STATE_REQUESTING:
692 case DHCP_STATE_BOUND:
694 if (client->attempt < 64)
695 client->attempt *= 2;
697 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
701 case DHCP_STATE_STOPPED:
706 next_timeout += (random_u32() & 0x1fffff);
708 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
710 r = sd_event_add_time(client->event,
711 &client->timeout_resend,
712 clock_boottime_or_monotonic(),
713 next_timeout, 10 * USEC_PER_MSEC,
714 client_timeout_resend, client);
718 r = sd_event_source_set_priority(client->timeout_resend,
719 client->event_priority);
723 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
727 switch (client->state) {
728 case DHCP_STATE_INIT:
729 r = client_send_discover(client);
731 client->state = DHCP_STATE_SELECTING;
734 if (client->attempt >= 64)
740 case DHCP_STATE_SELECTING:
741 r = client_send_discover(client);
742 if (r < 0 && client->attempt >= 64)
747 case DHCP_STATE_INIT_REBOOT:
748 case DHCP_STATE_REQUESTING:
749 case DHCP_STATE_RENEWING:
750 case DHCP_STATE_REBINDING:
751 r = client_send_request(client);
752 if (r < 0 && client->attempt >= 64)
755 if (client->state == DHCP_STATE_INIT_REBOOT)
756 client->state = DHCP_STATE_REBOOTING;
758 client->request_sent = time_now;
762 case DHCP_STATE_REBOOTING:
763 case DHCP_STATE_BOUND:
767 case DHCP_STATE_STOPPED:
775 client_stop(client, r);
777 /* Errors were dealt with when stopping the client, don't spill
778 errors into the event loop handler */
782 static int client_initialize_io_events(sd_dhcp_client *client,
783 sd_event_io_handler_t io_callback) {
787 assert(client->event);
789 r = sd_event_add_io(client->event, &client->receive_message,
790 client->fd, EPOLLIN, io_callback,
795 r = sd_event_source_set_priority(client->receive_message,
796 client->event_priority);
800 r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
806 client_stop(client, r);
811 static int client_initialize_time_events(sd_dhcp_client *client) {
815 assert(client->event);
817 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
819 r = sd_event_add_time(client->event,
820 &client->timeout_resend,
821 clock_boottime_or_monotonic(),
823 client_timeout_resend, client);
827 r = sd_event_source_set_priority(client->timeout_resend,
828 client->event_priority);
830 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
836 client_stop(client, r);
842 static int client_initialize_events(sd_dhcp_client *client,
843 sd_event_io_handler_t io_callback) {
844 client_initialize_io_events(client, io_callback);
845 client_initialize_time_events(client);
850 static int client_start(sd_dhcp_client *client) {
853 assert_return(client, -EINVAL);
854 assert_return(client->event, -EINVAL);
855 assert_return(client->index > 0, -EINVAL);
856 assert_return(client->fd < 0, -EBUSY);
857 assert_return(client->xid == 0, -EINVAL);
858 assert_return(client->state == DHCP_STATE_INIT ||
859 client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
861 client->xid = random_u32();
863 r = dhcp_network_bind_raw_socket(client->index, &client->link,
864 client->xid, client->mac_addr,
865 client->mac_addr_len, client->arp_type);
867 client_stop(client, r);
872 if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
873 client->start_time = now(clock_boottime_or_monotonic());
875 return client_initialize_events(client, client_receive_message_raw);
878 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
880 sd_dhcp_client *client = userdata;
881 DHCP_CLIENT_DONT_DESTROY(client);
883 log_dhcp_client(client, "EXPIRED");
885 client_notify(client, DHCP_EVENT_EXPIRED);
887 /* lease was lost, start over if not freed or stopped in callback */
888 if (client->state != DHCP_STATE_STOPPED) {
889 client_initialize(client);
890 client_start(client);
896 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
897 sd_dhcp_client *client = userdata;
898 DHCP_CLIENT_DONT_DESTROY(client);
901 client->receive_message = sd_event_source_unref(client->receive_message);
902 client->fd = asynchronous_close(client->fd);
904 client->state = DHCP_STATE_REBINDING;
907 r = dhcp_network_bind_raw_socket(client->index, &client->link,
908 client->xid, client->mac_addr,
909 client->mac_addr_len, client->arp_type);
911 client_stop(client, r);
916 return client_initialize_events(client, client_receive_message_raw);
919 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
921 sd_dhcp_client *client = userdata;
922 DHCP_CLIENT_DONT_DESTROY(client);
924 client->state = DHCP_STATE_RENEWING;
927 return client_initialize_time_events(client);
930 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
932 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
935 r = dhcp_lease_new(&lease);
939 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
940 if (r != DHCP_OFFER) {
941 log_dhcp_client(client, "received message was not an OFFER, ignoring");
945 lease->next_server = offer->siaddr;
947 lease->address = offer->yiaddr;
949 if (lease->address == INADDR_ANY ||
950 lease->server_address == INADDR_ANY ||
951 lease->lifetime == 0) {
952 log_dhcp_client(client, "received lease lacks address, server "
953 "address or lease lifetime, ignoring");
957 if (lease->subnet_mask == INADDR_ANY) {
958 r = dhcp_lease_set_default_subnet_mask(lease);
960 log_dhcp_client(client, "received lease lacks subnet "
961 "mask, and a fallback one can not be "
962 "generated, ignoring");
967 sd_dhcp_lease_unref(client->lease);
968 client->lease = lease;
971 log_dhcp_client(client, "OFFER");
976 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
980 r = dhcp_option_parse(force, len, NULL, NULL);
981 if (r != DHCP_FORCERENEW)
984 log_dhcp_client(client, "FORCERENEW");
989 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
991 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
994 r = dhcp_lease_new(&lease);
998 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
1000 log_dhcp_client(client, "NAK");
1001 return -EADDRNOTAVAIL;
1004 if (r != DHCP_ACK) {
1005 log_dhcp_client(client, "received message was not an ACK, ignoring");
1009 lease->next_server = ack->siaddr;
1011 lease->address = ack->yiaddr;
1013 if (lease->address == INADDR_ANY ||
1014 lease->server_address == INADDR_ANY ||
1015 lease->lifetime == 0) {
1016 log_dhcp_client(client, "received lease lacks address, server "
1017 "address or lease lifetime, ignoring");
1021 if (lease->subnet_mask == INADDR_ANY) {
1022 r = dhcp_lease_set_default_subnet_mask(lease);
1024 log_dhcp_client(client, "received lease lacks subnet "
1025 "mask, and a fallback one can not be "
1026 "generated, ignoring");
1031 r = DHCP_EVENT_IP_ACQUIRE;
1032 if (client->lease) {
1033 if (client->lease->address != lease->address ||
1034 client->lease->subnet_mask != lease->subnet_mask ||
1035 client->lease->router != lease->router) {
1036 r = DHCP_EVENT_IP_CHANGE;
1038 r = DHCP_EVENT_RENEW;
1040 client->lease = sd_dhcp_lease_unref(client->lease);
1043 client->lease = lease;
1046 log_dhcp_client(client, "ACK");
1051 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1052 uint32_t lifetime, double factor) {
1054 assert(client->request_sent);
1057 return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1058 + (random_u32() & 0x1fffff);
1061 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1063 uint64_t lifetime_timeout;
1064 uint64_t t2_timeout;
1065 uint64_t t1_timeout;
1066 char time_string[FORMAT_TIMESPAN_MAX];
1070 assert(client->event);
1071 assert(client->lease);
1072 assert(client->lease->lifetime);
1074 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1075 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1076 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1078 /* don't set timers for infinite leases */
1079 if (client->lease->lifetime == 0xffffffff)
1082 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1085 assert(client->request_sent <= time_now);
1087 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1088 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1089 if (client->lease->t1 && client->lease->t2) {
1090 /* both T1 and T2 are given */
1091 if (client->lease->t1 < client->lease->t2 &&
1092 client->lease->t2 < client->lease->lifetime) {
1093 /* they are both valid */
1094 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1095 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1098 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1099 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1100 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1101 client->lease->t1 = client->lease->lifetime / 2;
1103 } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1104 /* only T2 is given, and it is valid */
1105 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1106 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1107 client->lease->t1 = client->lease->lifetime / 2;
1108 if (t2_timeout <= t1_timeout) {
1109 /* the computed T1 would be invalid, so discard T2 */
1110 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1111 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1113 } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1114 /* only T1 is given, and it is valid */
1115 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1116 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1117 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1118 if (t2_timeout <= t1_timeout) {
1119 /* the computed T2 would be invalid, so discard T1 */
1120 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1121 client->lease->t2 = client->lease->lifetime / 2;
1124 /* fall back to the default timeouts */
1125 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1126 client->lease->t1 = client->lease->lifetime / 2;
1127 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1128 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1131 /* arm lifetime timeout */
1132 r = sd_event_add_time(client->event, &client->timeout_expire,
1133 clock_boottime_or_monotonic(),
1134 lifetime_timeout, 10 * USEC_PER_MSEC,
1135 client_timeout_expire, client);
1139 r = sd_event_source_set_priority(client->timeout_expire,
1140 client->event_priority);
1144 r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
1148 log_dhcp_client(client, "lease expires in %s",
1149 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1150 lifetime_timeout - time_now, 0));
1152 /* don't arm earlier timeouts if this has already expired */
1153 if (lifetime_timeout <= time_now)
1156 /* arm T2 timeout */
1157 r = sd_event_add_time(client->event,
1158 &client->timeout_t2,
1159 clock_boottime_or_monotonic(),
1162 client_timeout_t2, client);
1166 r = sd_event_source_set_priority(client->timeout_t2,
1167 client->event_priority);
1171 r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
1175 log_dhcp_client(client, "T2 expires in %s",
1176 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1177 t2_timeout - time_now, 0));
1179 /* don't arm earlier timeout if this has already expired */
1180 if (t2_timeout <= time_now)
1183 /* arm T1 timeout */
1184 r = sd_event_add_time(client->event,
1185 &client->timeout_t1,
1186 clock_boottime_or_monotonic(),
1187 t1_timeout, 10 * USEC_PER_MSEC,
1188 client_timeout_t1, client);
1192 r = sd_event_source_set_priority(client->timeout_t1,
1193 client->event_priority);
1197 r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
1201 log_dhcp_client(client, "T1 expires in %s",
1202 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1203 t1_timeout - time_now, 0));
1208 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1210 DHCP_CLIENT_DONT_DESTROY(client);
1211 int r = 0, notify_event = 0;
1214 assert(client->event);
1217 switch (client->state) {
1218 case DHCP_STATE_SELECTING:
1220 r = client_handle_offer(client, message, len);
1223 client->timeout_resend =
1224 sd_event_source_unref(client->timeout_resend);
1226 client->state = DHCP_STATE_REQUESTING;
1227 client->attempt = 1;
1229 r = sd_event_add_time(client->event,
1230 &client->timeout_resend,
1231 clock_boottime_or_monotonic(),
1233 client_timeout_resend, client);
1237 r = sd_event_source_set_priority(client->timeout_resend,
1238 client->event_priority);
1242 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
1245 } else if (r == -ENOMSG)
1246 /* invalid message, let's ignore it */
1251 case DHCP_STATE_REBOOTING:
1252 case DHCP_STATE_REQUESTING:
1253 case DHCP_STATE_RENEWING:
1254 case DHCP_STATE_REBINDING:
1256 r = client_handle_ack(client, message, len);
1258 client->timeout_resend =
1259 sd_event_source_unref(client->timeout_resend);
1260 client->receive_message =
1261 sd_event_source_unref(client->receive_message);
1262 client->fd = asynchronous_close(client->fd);
1264 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1265 DHCP_STATE_REBOOTING))
1266 notify_event = DHCP_EVENT_IP_ACQUIRE;
1267 else if (r != DHCP_EVENT_IP_ACQUIRE)
1270 client->state = DHCP_STATE_BOUND;
1271 client->attempt = 1;
1273 client->last_addr = client->lease->address;
1275 r = client_set_lease_timeouts(client);
1279 r = dhcp_network_bind_udp_socket(client->lease->address,
1282 log_dhcp_client(client, "could not bind UDP socket");
1288 client_initialize_io_events(client, client_receive_message_udp);
1291 client_notify(client, notify_event);
1292 if (client->state == DHCP_STATE_STOPPED)
1296 } else if (r == -EADDRNOTAVAIL) {
1297 /* got a NAK, let's restart the client */
1298 client->timeout_resend =
1299 sd_event_source_unref(client->timeout_resend);
1301 r = client_initialize(client);
1305 r = client_start(client);
1309 log_dhcp_client(client, "REBOOTED");
1312 } else if (r == -ENOMSG)
1313 /* invalid message, let's ignore it */
1318 case DHCP_STATE_BOUND:
1319 r = client_handle_forcerenew(client, message, len);
1321 r = client_timeout_t1(NULL, 0, client);
1324 } else if (r == -ENOMSG)
1325 /* invalid message, let's ignore it */
1330 case DHCP_STATE_INIT:
1331 case DHCP_STATE_INIT_REBOOT:
1335 case DHCP_STATE_STOPPED:
1342 client_stop(client, r);
1347 static int client_receive_message_udp(sd_event_source *s, int fd,
1348 uint32_t revents, void *userdata) {
1349 sd_dhcp_client *client = userdata;
1350 _cleanup_free_ DHCPMessage *message = NULL;
1351 int buflen = 0, len, r;
1352 const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1353 const struct ether_addr *expected_chaddr = NULL;
1354 uint8_t expected_hlen = 0;
1359 r = ioctl(fd, FIONREAD, &buflen);
1364 /* this can't be right */
1367 message = malloc0(buflen);
1371 len = read(fd, message, buflen);
1373 log_dhcp_client(client, "could not receive message from UDP "
1376 } else if ((size_t)len < sizeof(DHCPMessage)) {
1377 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1381 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1382 log_dhcp_client(client, "not a DHCP message: ignoring");
1386 if (message->op != BOOTREPLY) {
1387 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1391 if (message->htype != client->arp_type) {
1392 log_dhcp_client(client, "packet type does not match client type");
1396 if (client->arp_type == ARPHRD_ETHER) {
1397 expected_hlen = ETH_ALEN;
1398 expected_chaddr = (const struct ether_addr *) &client->mac_addr;
1400 /* Non-ethernet links expect zero chaddr */
1402 expected_chaddr = &zero_mac;
1405 if (message->hlen != expected_hlen) {
1406 log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
1410 if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
1411 log_dhcp_client(client, "received chaddr does not match "
1412 "expected: ignoring");
1416 if (client->state != DHCP_STATE_BOUND &&
1417 be32toh(message->xid) != client->xid) {
1418 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1419 so ignore the xid in this case */
1420 log_dhcp_client(client, "received xid (%u) does not match "
1421 "expected (%u): ignoring",
1422 be32toh(message->xid), client->xid);
1426 return client_handle_message(client, message, len);
1429 static int client_receive_message_raw(sd_event_source *s, int fd,
1430 uint32_t revents, void *userdata) {
1431 sd_dhcp_client *client = userdata;
1432 _cleanup_free_ DHCPPacket *packet = NULL;
1433 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1434 struct iovec iov = {};
1435 struct msghdr msg = {
1438 .msg_control = cmsgbuf,
1439 .msg_controllen = sizeof(cmsgbuf),
1441 struct cmsghdr *cmsg;
1442 bool checksum = true;
1443 int buflen = 0, len, r;
1448 r = ioctl(fd, FIONREAD, &buflen);
1453 /* this can't be right */
1456 packet = malloc0(buflen);
1460 iov.iov_base = packet;
1461 iov.iov_len = buflen;
1463 len = recvmsg(fd, &msg, 0);
1465 log_dhcp_client(client, "could not receive message from raw "
1468 } else if ((size_t)len < sizeof(DHCPPacket))
1471 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1472 if (cmsg->cmsg_level == SOL_PACKET &&
1473 cmsg->cmsg_type == PACKET_AUXDATA &&
1474 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1475 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1477 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1482 r = dhcp_packet_verify_headers(packet, len, checksum);
1486 len -= DHCP_IP_UDP_SIZE;
1488 return client_handle_message(client, &packet->dhcp, len);
1491 int sd_dhcp_client_start(sd_dhcp_client *client) {
1494 assert_return(client, -EINVAL);
1496 r = client_initialize(client);
1500 if (client->last_addr)
1501 client->state = DHCP_STATE_INIT_REBOOT;
1503 r = client_start(client);
1505 log_dhcp_client(client, "STARTED on ifindex %u", client->index);
1510 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1511 DHCP_CLIENT_DONT_DESTROY(client);
1513 assert_return(client, -EINVAL);
1515 client_stop(client, DHCP_EVENT_STOP);
1516 client->state = DHCP_STATE_STOPPED;
1521 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1525 assert_return(client, -EINVAL);
1526 assert_return(!client->event, -EBUSY);
1529 client->event = sd_event_ref(event);
1531 r = sd_event_default(&client->event);
1536 client->event_priority = priority;
1541 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1542 assert_return(client, -EINVAL);
1544 client->event = sd_event_unref(client->event);
1549 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1553 return client->event;
1556 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1558 assert_se(REFCNT_INC(client->n_ref) >= 2);
1563 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1564 if (client && REFCNT_DEC(client->n_ref) <= 0) {
1565 log_dhcp_client(client, "FREE");
1567 client_initialize(client);
1569 client->receive_message =
1570 sd_event_source_unref(client->receive_message);
1572 sd_dhcp_client_detach_event(client);
1574 sd_dhcp_lease_unref(client->lease);
1576 free(client->req_opts);
1577 free(client->hostname);
1578 free(client->vendor_class_identifier);
1585 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1586 _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1588 assert_return(ret, -EINVAL);
1590 client = new0(sd_dhcp_client, 1);
1594 client->n_ref = REFCNT_INIT;
1595 client->state = DHCP_STATE_INIT;
1598 client->attempt = 1;
1599 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1601 client->req_opts_size = ELEMENTSOF(default_req_opts);
1603 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1604 if (!client->req_opts)