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 <netinet/ether.h>
27 #include <sys/param.h>
28 #include <sys/ioctl.h>
35 #include "dhcp-protocol.h"
36 #include "dhcp-internal.h"
37 #include "dhcp-lease-internal.h"
38 #include "sd-dhcp-client.h"
40 struct sd_dhcp_client {
46 sd_event_source *timeout_resend;
49 union sockaddr_union link;
50 sd_event_source *receive_message;
51 bool request_broadcast;
53 size_t req_opts_allocated;
58 struct ether_addr mac_addr;
61 char *vendor_class_identifier;
68 sd_event_source *timeout_t1;
69 sd_event_source *timeout_t2;
70 sd_event_source *timeout_expire;
71 sd_dhcp_client_cb_t cb;
76 static const uint8_t default_req_opts[] = {
77 DHCP_OPTION_SUBNET_MASK,
79 DHCP_OPTION_HOST_NAME,
80 DHCP_OPTION_DOMAIN_NAME,
81 DHCP_OPTION_DOMAIN_NAME_SERVER,
82 DHCP_OPTION_NTP_SERVER,
85 static int client_receive_message_raw(sd_event_source *s, int fd,
86 uint32_t revents, void *userdata);
87 static int client_receive_message_udp(sd_event_source *s, int fd,
88 uint32_t revents, void *userdata);
89 static void client_stop(sd_dhcp_client *client, int error);
91 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
93 assert_return(client, -EINVAL);
96 client->userdata = userdata;
101 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
102 assert_return(client, -EINVAL);
104 client->request_broadcast = !!broadcast;
109 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
112 assert_return(client, -EINVAL);
113 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
114 DHCP_STATE_STOPPED), -EBUSY);
117 case DHCP_OPTION_PAD:
118 case DHCP_OPTION_OVERLOAD:
119 case DHCP_OPTION_MESSAGE_TYPE:
120 case DHCP_OPTION_PARAMETER_REQUEST_LIST:
121 case DHCP_OPTION_END:
128 for (i = 0; i < client->req_opts_size; i++)
129 if (client->req_opts[i] == option)
132 if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
133 client->req_opts_size + 1))
136 client->req_opts[client->req_opts_size++] = option;
141 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
142 const struct in_addr *last_addr) {
143 assert_return(client, -EINVAL);
144 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
145 DHCP_STATE_STOPPED), -EBUSY);
148 client->last_addr = last_addr->s_addr;
150 client->last_addr = INADDR_ANY;
155 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
156 assert_return(client, -EINVAL);
157 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
158 DHCP_STATE_STOPPED), -EBUSY);
159 assert_return(interface_index > 0, -EINVAL);
161 client->index = interface_index;
166 int sd_dhcp_client_set_mac(sd_dhcp_client *client,
167 const struct ether_addr *addr) {
168 DHCP_CLIENT_DONT_DESTROY(client);
169 bool need_restart = false;
171 assert_return(client, -EINVAL);
172 assert_return(addr, -EINVAL);
174 if (memcmp(&client->client_id.mac_addr, addr, ETH_ALEN) == 0)
177 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
178 log_dhcp_client(client, "Changing MAC address on running DHCP "
179 "client, restarting");
181 client_stop(client, DHCP_EVENT_STOP);
184 memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
185 client->client_id.type = 0x01;
187 if (need_restart && client->state != DHCP_STATE_STOPPED)
188 sd_dhcp_client_start(client);
193 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
194 const char *hostname) {
195 char *new_hostname = NULL;
197 assert_return(client, -EINVAL);
199 if (streq_ptr(client->hostname, hostname))
203 new_hostname = strdup(hostname);
208 free(client->hostname);
209 client->hostname = new_hostname;
214 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
216 char *new_vci = NULL;
218 assert_return(client, -EINVAL);
220 new_vci = strdup(vci);
224 free(client->vendor_class_identifier);
226 client->vendor_class_identifier = new_vci;
231 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
232 assert_return(client, -EINVAL);
233 assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
240 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
241 assert_return(client, -EINVAL);
242 assert_return(ret, -EINVAL);
244 if (client->state != DHCP_STATE_BOUND &&
245 client->state != DHCP_STATE_RENEWING &&
246 client->state != DHCP_STATE_REBINDING)
247 return -EADDRNOTAVAIL;
249 *ret = sd_dhcp_lease_ref(client->lease);
254 static void client_notify(sd_dhcp_client *client, int event) {
256 client->cb(client, event, client->userdata);
259 static int client_initialize(sd_dhcp_client *client) {
260 assert_return(client, -EINVAL);
262 client->receive_message =
263 sd_event_source_unref(client->receive_message);
265 client->fd = asynchronous_close(client->fd);
267 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
269 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
270 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
271 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
275 client->state = DHCP_STATE_INIT;
279 client->lease = sd_dhcp_lease_unref(client->lease);
284 static void client_stop(sd_dhcp_client *client, int error) {
288 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
289 else if (error == DHCP_EVENT_STOP)
290 log_dhcp_client(client, "STOPPED");
292 log_dhcp_client(client, "STOPPED: Unknown event");
294 client_notify(client, error);
296 client_initialize(client);
299 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
300 uint8_t type, size_t *_optlen, size_t *_optoffset) {
301 _cleanup_free_ DHCPPacket *packet;
302 size_t optlen, optoffset, size;
307 assert(client->secs);
311 assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
313 optlen = DHCP_MIN_OPTIONS_SIZE;
314 size = sizeof(DHCPPacket) + optlen;
316 packet = malloc0(size);
320 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
325 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
326 refuse to issue an DHCP lease if 'secs' is set to zero */
327 packet->dhcp.secs = htobe16(client->secs);
329 /* RFC2132 section 4.1
330 A client that cannot receive unicast IP datagrams until its protocol
331 software has been configured with an IP address SHOULD set the
332 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
333 DHCPREQUEST messages that client sends. The BROADCAST bit will
334 provide a hint to the DHCP server and BOOTP relay agent to broadcast
335 any messages to the client on the client's subnet.
337 Note: some interfaces needs this to be enabled, but some networks
338 needs this to be disabled as broadcasts are filteretd, so this
339 needs to be configurable */
340 if (client->request_broadcast)
341 packet->dhcp.flags = htobe16(0x8000);
343 /* RFC2132 section 4.1.1:
344 The client MUST include its hardware address in the ’chaddr’ field, if
345 necessary for delivery of DHCP reply messages.
347 memcpy(&packet->dhcp.chaddr, &client->client_id.mac_addr, ETH_ALEN);
349 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
350 Identifier option is not set */
351 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
352 DHCP_OPTION_CLIENT_IDENTIFIER,
353 sizeof(client->client_id), &client->client_id);
358 /* RFC2131 section 3.5:
359 in its initial DHCPDISCOVER or DHCPREQUEST message, a
360 client may provide the server with a list of specific
361 parameters the client is interested in. If the client
362 includes a list of parameters in a DHCPDISCOVER message,
363 it MUST include that list in any subsequent DHCPREQUEST
366 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
367 DHCP_OPTION_PARAMETER_REQUEST_LIST,
368 client->req_opts_size, client->req_opts);
372 /* RFC2131 section 3.5:
373 The client SHOULD include the ’maximum DHCP message size’ option to
374 let the server know how large the server may make its DHCP messages.
376 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
377 than the defined default size unless the Maximum Messge Size option
380 RFC3442 "Requirements to Avoid Sizing Constraints":
381 Because a full routing table can be quite large, the standard 576
382 octet maximum size for a DHCP message may be too short to contain
383 some legitimate Classless Static Route options. Because of this,
384 clients implementing the Classless Static Route option SHOULD send a
385 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
386 stack is capable of receiving larger IP datagrams. In this case, the
387 client SHOULD set the value of this option to at least the MTU of the
388 interface that the client is configuring. The client MAY set the
389 value of this option higher, up to the size of the largest UDP packet
390 it is prepared to accept. (Note that the value specified in the
391 Maximum DHCP Message Size option is the total maximum packet size,
392 including IP and UDP headers.)
394 max_size = htobe16(size);
395 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
396 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
402 *_optoffset = optoffset;
409 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
411 dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
412 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
414 return dhcp_network_send_raw_socket(client->fd, &client->link,
418 static int client_send_discover(sd_dhcp_client *client) {
419 _cleanup_free_ DHCPPacket *discover = NULL;
420 size_t optoffset, optlen;
425 assert(client->state == DHCP_STATE_INIT ||
426 client->state == DHCP_STATE_SELECTING);
428 /* See RFC2131 section 4.4.1 */
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 client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
439 r = client_message_init(client, &discover, DHCP_DISCOVER,
440 &optlen, &optoffset);
444 /* the client may suggest values for the network address
445 and lease time in the DHCPDISCOVER message. The client may include
446 the ’requested IP address’ option to suggest that a particular IP
447 address be assigned, and may include the ’IP address lease time’
448 option to suggest the lease time it would like.
450 if (client->last_addr != INADDR_ANY) {
451 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
452 DHCP_OPTION_REQUESTED_IP_ADDRESS,
453 4, &client->last_addr);
458 /* it is unclear from RFC 2131 if client should send hostname in
459 DHCPDISCOVER but dhclient does and so we do as well
461 if (client->hostname) {
462 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
463 DHCP_OPTION_HOST_NAME,
464 strlen(client->hostname), client->hostname);
469 if (client->vendor_class_identifier) {
470 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
471 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
472 strlen(client->vendor_class_identifier),
473 client->vendor_class_identifier);
478 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
479 DHCP_OPTION_END, 0, NULL);
483 /* We currently ignore:
484 The client SHOULD wait a random time between one and ten seconds to
485 desynchronize the use of DHCP at startup.
487 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
491 log_dhcp_client(client, "DISCOVER");
496 static int client_send_request(sd_dhcp_client *client) {
497 _cleanup_free_ DHCPPacket *request = NULL;
498 size_t optoffset, optlen;
501 r = client_message_init(client, &request, DHCP_REQUEST,
502 &optlen, &optoffset);
506 switch (client->state) {
507 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
508 SELECTING should be REQUESTING)
511 case DHCP_STATE_REQUESTING:
512 /* Client inserts the address of the selected server in ’server
513 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
514 filled in with the yiaddr value from the chosen DHCPOFFER.
517 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
518 DHCP_OPTION_SERVER_IDENTIFIER,
519 4, &client->lease->server_address);
523 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
524 DHCP_OPTION_REQUESTED_IP_ADDRESS,
525 4, &client->lease->address);
531 case DHCP_STATE_INIT_REBOOT:
532 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
533 option MUST be filled in with client’s notion of its previously
534 assigned address. ’ciaddr’ MUST be zero.
536 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
537 DHCP_OPTION_REQUESTED_IP_ADDRESS,
538 4, &client->last_addr);
543 case DHCP_STATE_RENEWING:
544 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
545 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
546 client’s IP address.
550 case DHCP_STATE_REBINDING:
551 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
552 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
553 client’s IP address.
555 This message MUST be broadcast to the 0xffffffff IP broadcast address.
557 request->dhcp.ciaddr = client->lease->address;
561 case DHCP_STATE_INIT:
562 case DHCP_STATE_SELECTING:
563 case DHCP_STATE_REBOOTING:
564 case DHCP_STATE_BOUND:
565 case DHCP_STATE_STOPPED:
569 if (client->hostname) {
570 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
571 DHCP_OPTION_HOST_NAME,
572 strlen(client->hostname), client->hostname);
577 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
578 DHCP_OPTION_END, 0, NULL);
582 if (client->state == DHCP_STATE_RENEWING) {
583 r = dhcp_network_send_udp_socket(client->fd,
584 client->lease->server_address,
587 sizeof(DHCPMessage) + optoffset);
589 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
594 switch (client->state) {
595 case DHCP_STATE_REQUESTING:
596 log_dhcp_client(client, "REQUEST (requesting)");
598 case DHCP_STATE_INIT_REBOOT:
599 log_dhcp_client(client, "REQUEST (init-reboot)");
601 case DHCP_STATE_RENEWING:
602 log_dhcp_client(client, "REQUEST (renewing)");
604 case DHCP_STATE_REBINDING:
605 log_dhcp_client(client, "REQUEST (rebinding)");
608 log_dhcp_client(client, "REQUEST (invalid)");
615 static int client_start(sd_dhcp_client *client);
617 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
619 sd_dhcp_client *client = userdata;
620 DHCP_CLIENT_DONT_DESTROY(client);
621 usec_t next_timeout = 0;
628 assert(client->event);
630 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
634 switch (client->state) {
635 case DHCP_STATE_RENEWING:
637 time_left = (client->lease->t2 - client->lease->t1) / 2;
641 next_timeout = time_now + time_left * USEC_PER_SEC;
645 case DHCP_STATE_REBINDING:
647 time_left = (client->lease->lifetime - client->lease->t2) / 2;
651 next_timeout = time_now + time_left * USEC_PER_SEC;
654 case DHCP_STATE_REBOOTING:
655 /* start over as we did not receive a timely ack or nak */
656 r = client_initialize(client);
660 r = client_start(client);
664 log_dhcp_client(client, "REBOOTED");
668 case DHCP_STATE_INIT:
669 case DHCP_STATE_INIT_REBOOT:
670 case DHCP_STATE_SELECTING:
671 case DHCP_STATE_REQUESTING:
672 case DHCP_STATE_BOUND:
674 if (client->attempt < 64)
675 client->attempt *= 2;
677 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
681 case DHCP_STATE_STOPPED:
686 next_timeout += (random_u32() & 0x1fffff);
688 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
690 r = sd_event_add_time(client->event,
691 &client->timeout_resend,
692 clock_boottime_or_monotonic(),
693 next_timeout, 10 * USEC_PER_MSEC,
694 client_timeout_resend, client);
698 r = sd_event_source_set_priority(client->timeout_resend,
699 client->event_priority);
703 r = sd_event_source_set_name(client->timeout_resend,
704 "dhcp4-resend-timer");
708 switch (client->state) {
709 case DHCP_STATE_INIT:
710 r = client_send_discover(client);
712 client->state = DHCP_STATE_SELECTING;
715 if (client->attempt >= 64)
721 case DHCP_STATE_SELECTING:
722 r = client_send_discover(client);
723 if (r < 0 && client->attempt >= 64)
728 case DHCP_STATE_INIT_REBOOT:
729 case DHCP_STATE_REQUESTING:
730 case DHCP_STATE_RENEWING:
731 case DHCP_STATE_REBINDING:
732 r = client_send_request(client);
733 if (r < 0 && client->attempt >= 64)
736 if (client->state == DHCP_STATE_INIT_REBOOT)
737 client->state = DHCP_STATE_REBOOTING;
739 client->request_sent = time_now;
743 case DHCP_STATE_REBOOTING:
744 case DHCP_STATE_BOUND:
748 case DHCP_STATE_STOPPED:
756 client_stop(client, r);
758 /* Errors were dealt with when stopping the client, don't spill
759 errors into the event loop handler */
763 static int client_initialize_io_events(sd_dhcp_client *client,
764 sd_event_io_handler_t io_callback) {
768 assert(client->event);
770 r = sd_event_add_io(client->event, &client->receive_message,
771 client->fd, EPOLLIN, io_callback,
776 r = sd_event_source_set_priority(client->receive_message,
777 client->event_priority);
781 r = sd_event_source_set_name(client->receive_message,
782 "dhcp4-receive-message");
788 client_stop(client, r);
793 static int client_initialize_time_events(sd_dhcp_client *client) {
797 assert(client->event);
799 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
801 r = sd_event_add_time(client->event,
802 &client->timeout_resend,
803 clock_boottime_or_monotonic(),
805 client_timeout_resend, client);
809 r = sd_event_source_set_priority(client->timeout_resend,
810 client->event_priority);
812 r = sd_event_source_set_name(client->timeout_resend,
813 "dhcp4-resend-timer");
819 client_stop(client, r);
825 static int client_initialize_events(sd_dhcp_client *client,
826 sd_event_io_handler_t io_callback) {
827 client_initialize_io_events(client, io_callback);
828 client_initialize_time_events(client);
833 static int client_start(sd_dhcp_client *client) {
836 assert_return(client, -EINVAL);
837 assert_return(client->event, -EINVAL);
838 assert_return(client->index > 0, -EINVAL);
839 assert_return(client->fd < 0, -EBUSY);
840 assert_return(client->xid == 0, -EINVAL);
841 assert_return(client->state == DHCP_STATE_INIT ||
842 client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
844 client->xid = random_u32();
846 r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
848 client_stop(client, r);
853 if (client->state == DHCP_STATE_INIT) {
854 client->start_time = now(clock_boottime_or_monotonic());
858 return client_initialize_events(client, client_receive_message_raw);
861 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
863 sd_dhcp_client *client = userdata;
864 DHCP_CLIENT_DONT_DESTROY(client);
866 log_dhcp_client(client, "EXPIRED");
868 client_notify(client, DHCP_EVENT_EXPIRED);
870 /* lease was lost, start over if not freed or stopped in callback */
871 if (client->state != DHCP_STATE_STOPPED) {
872 client_initialize(client);
873 client_start(client);
879 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
880 sd_dhcp_client *client = userdata;
881 DHCP_CLIENT_DONT_DESTROY(client);
884 client->receive_message = sd_event_source_unref(client->receive_message);
885 client->fd = asynchronous_close(client->fd);
887 client->state = DHCP_STATE_REBINDING;
890 r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
892 client_stop(client, r);
897 return client_initialize_events(client, client_receive_message_raw);
900 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
902 sd_dhcp_client *client = userdata;
903 DHCP_CLIENT_DONT_DESTROY(client);
905 client->state = DHCP_STATE_RENEWING;
908 return client_initialize_time_events(client);
911 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
913 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
916 r = dhcp_lease_new(&lease);
920 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
921 if (r != DHCP_OFFER) {
922 log_dhcp_client(client, "received message was not an OFFER, ignoring");
926 lease->next_server = offer->siaddr;
928 lease->address = offer->yiaddr;
930 if (lease->address == INADDR_ANY ||
931 lease->server_address == INADDR_ANY ||
932 lease->lifetime == 0) {
933 log_dhcp_client(client, "received lease lacks address, server "
934 "address or lease lifetime, ignoring");
938 if (lease->subnet_mask == INADDR_ANY) {
939 r = dhcp_lease_set_default_subnet_mask(lease);
941 log_dhcp_client(client, "received lease lacks subnet "
942 "mask, and a fallback one can not be "
943 "generated, ignoring");
948 sd_dhcp_lease_unref(client->lease);
949 client->lease = lease;
952 log_dhcp_client(client, "OFFER");
957 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
961 r = dhcp_option_parse(force, len, NULL, NULL);
962 if (r != DHCP_FORCERENEW)
965 log_dhcp_client(client, "FORCERENEW");
970 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
972 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
975 r = dhcp_lease_new(&lease);
979 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
981 log_dhcp_client(client, "NAK");
982 return -EADDRNOTAVAIL;
986 log_dhcp_client(client, "received message was not an ACK, ignoring");
990 lease->next_server = ack->siaddr;
992 lease->address = ack->yiaddr;
994 if (lease->address == INADDR_ANY ||
995 lease->server_address == INADDR_ANY ||
996 lease->lifetime == 0) {
997 log_dhcp_client(client, "received lease lacks address, server "
998 "address or lease lifetime, ignoring");
1002 if (lease->subnet_mask == INADDR_ANY) {
1003 r = dhcp_lease_set_default_subnet_mask(lease);
1005 log_dhcp_client(client, "received lease lacks subnet "
1006 "mask, and a fallback one can not be "
1007 "generated, ignoring");
1012 r = DHCP_EVENT_IP_ACQUIRE;
1013 if (client->lease) {
1014 if (client->lease->address != lease->address ||
1015 client->lease->subnet_mask != lease->subnet_mask ||
1016 client->lease->router != lease->router) {
1017 r = DHCP_EVENT_IP_CHANGE;
1019 r = DHCP_EVENT_RENEW;
1021 client->lease = sd_dhcp_lease_unref(client->lease);
1024 client->lease = lease;
1027 log_dhcp_client(client, "ACK");
1032 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1033 uint32_t lifetime, double factor) {
1035 assert(client->request_sent);
1038 return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1039 + (random_u32() & 0x1fffff);
1042 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1044 uint64_t lifetime_timeout;
1045 uint64_t t2_timeout;
1046 uint64_t t1_timeout;
1047 char time_string[FORMAT_TIMESPAN_MAX];
1051 assert(client->event);
1052 assert(client->lease);
1053 assert(client->lease->lifetime);
1055 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1056 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1057 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1059 /* don't set timers for infinite leases */
1060 if (client->lease->lifetime == 0xffffffff)
1063 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1066 assert(client->request_sent <= time_now);
1068 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1069 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1070 if (client->lease->t1 && client->lease->t2) {
1071 /* both T1 and T2 are given */
1072 if (client->lease->t1 < client->lease->t2 &&
1073 client->lease->t2 < client->lease->lifetime) {
1074 /* they are both valid */
1075 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1076 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1079 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1080 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1081 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1082 client->lease->t1 = client->lease->lifetime / 2;
1084 } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1085 /* only T2 is given, and it is valid */
1086 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1087 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1088 client->lease->t1 = client->lease->lifetime / 2;
1089 if (t2_timeout <= t1_timeout) {
1090 /* the computed T1 would be invalid, so discard T2 */
1091 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1092 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1094 } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1095 /* only T1 is given, and it is valid */
1096 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1097 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1098 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1099 if (t2_timeout <= t1_timeout) {
1100 /* the computed T2 would be invalid, so discard T1 */
1101 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1102 client->lease->t2 = client->lease->lifetime / 2;
1105 /* fall back to the default timeouts */
1106 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1107 client->lease->t1 = client->lease->lifetime / 2;
1108 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1109 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1112 /* arm lifetime timeout */
1113 r = sd_event_add_time(client->event, &client->timeout_expire,
1114 clock_boottime_or_monotonic(),
1115 lifetime_timeout, 10 * USEC_PER_MSEC,
1116 client_timeout_expire, client);
1120 r = sd_event_source_set_priority(client->timeout_expire,
1121 client->event_priority);
1125 r = sd_event_source_set_name(client->timeout_expire,
1130 log_dhcp_client(client, "lease expires in %s",
1131 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1132 lifetime_timeout - time_now, 0));
1134 /* don't arm earlier timeouts if this has already expired */
1135 if (lifetime_timeout <= time_now)
1138 /* arm T2 timeout */
1139 r = sd_event_add_time(client->event,
1140 &client->timeout_t2,
1141 clock_boottime_or_monotonic(),
1144 client_timeout_t2, client);
1148 r = sd_event_source_set_priority(client->timeout_t2,
1149 client->event_priority);
1153 r = sd_event_source_set_name(client->timeout_t2,
1154 "dhcp4-t2-timeout");
1158 log_dhcp_client(client, "T2 expires in %s",
1159 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1160 t2_timeout - time_now, 0));
1162 /* don't arm earlier timeout if this has already expired */
1163 if (t2_timeout <= time_now)
1166 /* arm T1 timeout */
1167 r = sd_event_add_time(client->event,
1168 &client->timeout_t1,
1169 clock_boottime_or_monotonic(),
1170 t1_timeout, 10 * USEC_PER_MSEC,
1171 client_timeout_t1, client);
1175 r = sd_event_source_set_priority(client->timeout_t1,
1176 client->event_priority);
1180 r = sd_event_source_set_name(client->timeout_t1,
1185 log_dhcp_client(client, "T1 expires in %s",
1186 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1187 t1_timeout - time_now, 0));
1192 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1194 DHCP_CLIENT_DONT_DESTROY(client);
1195 int r = 0, notify_event = 0;
1198 assert(client->event);
1201 switch (client->state) {
1202 case DHCP_STATE_SELECTING:
1204 r = client_handle_offer(client, message, len);
1207 client->timeout_resend =
1208 sd_event_source_unref(client->timeout_resend);
1210 client->state = DHCP_STATE_REQUESTING;
1211 client->attempt = 1;
1213 r = sd_event_add_time(client->event,
1214 &client->timeout_resend,
1215 clock_boottime_or_monotonic(),
1217 client_timeout_resend, client);
1221 r = sd_event_source_set_priority(client->timeout_resend,
1222 client->event_priority);
1226 r = sd_event_source_set_name(client->timeout_resend,
1227 "dhcp4-resend-timer");
1230 } else if (r == -ENOMSG)
1231 /* invalid message, let's ignore it */
1236 case DHCP_STATE_REBOOTING:
1237 case DHCP_STATE_REQUESTING:
1238 case DHCP_STATE_RENEWING:
1239 case DHCP_STATE_REBINDING:
1241 r = client_handle_ack(client, message, len);
1243 client->timeout_resend =
1244 sd_event_source_unref(client->timeout_resend);
1246 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1247 DHCP_STATE_REBOOTING))
1248 notify_event = DHCP_EVENT_IP_ACQUIRE;
1249 else if (r != DHCP_EVENT_IP_ACQUIRE)
1252 client->state = DHCP_STATE_BOUND;
1253 client->attempt = 1;
1255 client->last_addr = client->lease->address;
1257 r = client_set_lease_timeouts(client);
1261 r = dhcp_network_bind_udp_socket(client->lease->address,
1264 log_dhcp_client(client, "could not bind UDP socket");
1270 client_initialize_io_events(client, client_receive_message_udp);
1273 client_notify(client, notify_event);
1274 if (client->state == DHCP_STATE_STOPPED)
1278 } else if (r == -EADDRNOTAVAIL) {
1279 /* got a NAK, let's restart the client */
1280 client->timeout_resend =
1281 sd_event_source_unref(client->timeout_resend);
1283 r = client_initialize(client);
1287 r = client_start(client);
1291 log_dhcp_client(client, "REBOOTED");
1294 } else if (r == -ENOMSG)
1295 /* invalid message, let's ignore it */
1300 case DHCP_STATE_BOUND:
1301 r = client_handle_forcerenew(client, message, len);
1303 r = client_timeout_t1(NULL, 0, client);
1306 } else if (r == -ENOMSG)
1307 /* invalid message, let's ignore it */
1312 case DHCP_STATE_INIT:
1313 case DHCP_STATE_INIT_REBOOT:
1317 case DHCP_STATE_STOPPED:
1324 client_stop(client, r);
1329 static int client_receive_message_udp(sd_event_source *s, int fd,
1330 uint32_t revents, void *userdata) {
1331 sd_dhcp_client *client = userdata;
1332 _cleanup_free_ DHCPMessage *message = NULL;
1333 int buflen = 0, len, r;
1338 r = ioctl(fd, FIONREAD, &buflen);
1343 /* this can't be right */
1346 message = malloc0(buflen);
1350 len = read(fd, message, buflen);
1352 log_dhcp_client(client, "could not receive message from UDP "
1355 } else if ((size_t)len < sizeof(DHCPMessage)) {
1356 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1360 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1361 log_dhcp_client(client, "not a DHCP message: ignoring");
1365 if (message->op != BOOTREPLY) {
1366 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1370 if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
1371 log_dhcp_client(client, "not an ethernet packet");
1375 if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
1377 log_dhcp_client(client, "received chaddr does not match "
1378 "expected: ignoring");
1382 if (client->state != DHCP_STATE_BOUND &&
1383 be32toh(message->xid) != client->xid) {
1384 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1385 so ignore the xid in this case */
1386 log_dhcp_client(client, "received xid (%u) does not match "
1387 "expected (%u): ignoring",
1388 be32toh(message->xid), client->xid);
1392 return client_handle_message(client, message, len);
1395 static int client_receive_message_raw(sd_event_source *s, int fd,
1396 uint32_t revents, void *userdata) {
1397 sd_dhcp_client *client = userdata;
1398 _cleanup_free_ DHCPPacket *packet = NULL;
1399 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1400 struct iovec iov = {};
1401 struct msghdr msg = {
1404 .msg_control = cmsgbuf,
1405 .msg_controllen = sizeof(cmsgbuf),
1407 struct cmsghdr *cmsg;
1408 bool checksum = true;
1409 int buflen = 0, len, r;
1414 r = ioctl(fd, FIONREAD, &buflen);
1419 /* this can't be right */
1422 packet = malloc0(buflen);
1426 iov.iov_base = packet;
1427 iov.iov_len = buflen;
1429 len = recvmsg(fd, &msg, 0);
1431 log_dhcp_client(client, "could not receive message from raw "
1434 } else if ((size_t)len < sizeof(DHCPPacket))
1437 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1438 if (cmsg->cmsg_level == SOL_PACKET &&
1439 cmsg->cmsg_type == PACKET_AUXDATA &&
1440 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1441 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1443 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1448 r = dhcp_packet_verify_headers(packet, len, checksum);
1452 len -= DHCP_IP_UDP_SIZE;
1454 return client_handle_message(client, &packet->dhcp, len);
1457 int sd_dhcp_client_start(sd_dhcp_client *client) {
1458 char buffer[ETHER_ADDR_TO_STRING_MAX];
1461 assert_return(client, -EINVAL);
1463 r = client_initialize(client);
1467 if (client->last_addr)
1468 client->state = DHCP_STATE_INIT_REBOOT;
1470 r = client_start(client);
1472 log_dhcp_client(client, "STARTED on ifindex %u with address %s",
1474 ether_addr_to_string(&client->client_id.mac_addr, buffer));
1479 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1480 DHCP_CLIENT_DONT_DESTROY(client);
1482 assert_return(client, -EINVAL);
1484 client_stop(client, DHCP_EVENT_STOP);
1485 client->state = DHCP_STATE_STOPPED;
1490 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1494 assert_return(client, -EINVAL);
1495 assert_return(!client->event, -EBUSY);
1498 client->event = sd_event_ref(event);
1500 r = sd_event_default(&client->event);
1505 client->event_priority = priority;
1510 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1511 assert_return(client, -EINVAL);
1513 client->event = sd_event_unref(client->event);
1518 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1522 return client->event;
1525 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1527 assert_se(REFCNT_INC(client->n_ref) >= 2);
1532 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1533 if (client && REFCNT_DEC(client->n_ref) <= 0) {
1534 log_dhcp_client(client, "FREE");
1536 client_initialize(client);
1538 client->receive_message =
1539 sd_event_source_unref(client->receive_message);
1541 sd_dhcp_client_detach_event(client);
1543 sd_dhcp_lease_unref(client->lease);
1545 free(client->req_opts);
1546 free(client->hostname);
1547 free(client->vendor_class_identifier);
1554 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1555 _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1557 assert_return(ret, -EINVAL);
1559 client = new0(sd_dhcp_client, 1);
1563 client->n_ref = REFCNT_INIT;
1564 client->state = DHCP_STATE_INIT;
1567 client->attempt = 1;
1568 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1570 client->req_opts_size = ELEMENTSOF(default_req_opts);
1572 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1573 if (!client->req_opts)