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 switch (client->state) {
704 case DHCP_STATE_INIT:
705 r = client_send_discover(client);
707 client->state = DHCP_STATE_SELECTING;
710 if (client->attempt >= 64)
716 case DHCP_STATE_SELECTING:
717 r = client_send_discover(client);
718 if (r < 0 && client->attempt >= 64)
723 case DHCP_STATE_INIT_REBOOT:
724 case DHCP_STATE_REQUESTING:
725 case DHCP_STATE_RENEWING:
726 case DHCP_STATE_REBINDING:
727 r = client_send_request(client);
728 if (r < 0 && client->attempt >= 64)
731 if (client->state == DHCP_STATE_INIT_REBOOT)
732 client->state = DHCP_STATE_REBOOTING;
734 client->request_sent = time_now;
738 case DHCP_STATE_REBOOTING:
739 case DHCP_STATE_BOUND:
743 case DHCP_STATE_STOPPED:
751 client_stop(client, r);
753 /* Errors were dealt with when stopping the client, don't spill
754 errors into the event loop handler */
758 static int client_initialize_io_events(sd_dhcp_client *client,
759 sd_event_io_handler_t io_callback) {
763 assert(client->event);
765 r = sd_event_add_io(client->event, &client->receive_message,
766 client->fd, EPOLLIN, io_callback,
771 r = sd_event_source_set_priority(client->receive_message,
772 client->event_priority);
778 client_stop(client, r);
783 static int client_initialize_time_events(sd_dhcp_client *client) {
787 assert(client->event);
789 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
791 r = sd_event_add_time(client->event,
792 &client->timeout_resend,
793 clock_boottime_or_monotonic(),
795 client_timeout_resend, client);
799 r = sd_event_source_set_priority(client->timeout_resend,
800 client->event_priority);
804 client_stop(client, r);
810 static int client_initialize_events(sd_dhcp_client *client,
811 sd_event_io_handler_t io_callback) {
812 client_initialize_io_events(client, io_callback);
813 client_initialize_time_events(client);
818 static int client_start(sd_dhcp_client *client) {
821 assert_return(client, -EINVAL);
822 assert_return(client->event, -EINVAL);
823 assert_return(client->index > 0, -EINVAL);
824 assert_return(client->fd < 0, -EBUSY);
825 assert_return(client->xid == 0, -EINVAL);
826 assert_return(client->state == DHCP_STATE_INIT ||
827 client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
829 client->xid = random_u32();
831 r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
833 client_stop(client, r);
838 if (client->state == DHCP_STATE_INIT) {
839 client->start_time = now(clock_boottime_or_monotonic());
843 return client_initialize_events(client, client_receive_message_raw);
846 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
848 sd_dhcp_client *client = userdata;
849 DHCP_CLIENT_DONT_DESTROY(client);
851 log_dhcp_client(client, "EXPIRED");
853 client_notify(client, DHCP_EVENT_EXPIRED);
855 /* lease was lost, start over if not freed or stopped in callback */
856 if (client->state != DHCP_STATE_STOPPED) {
857 client_initialize(client);
858 client_start(client);
864 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
865 sd_dhcp_client *client = userdata;
866 DHCP_CLIENT_DONT_DESTROY(client);
869 client->receive_message = sd_event_source_unref(client->receive_message);
870 client->fd = asynchronous_close(client->fd);
872 client->state = DHCP_STATE_REBINDING;
875 r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
877 client_stop(client, r);
882 return client_initialize_events(client, client_receive_message_raw);
885 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
887 sd_dhcp_client *client = userdata;
888 DHCP_CLIENT_DONT_DESTROY(client);
890 client->state = DHCP_STATE_RENEWING;
893 return client_initialize_time_events(client);
896 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
898 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
901 r = dhcp_lease_new(&lease);
905 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
906 if (r != DHCP_OFFER) {
907 log_dhcp_client(client, "receieved message was not an OFFER, ignoring");
911 lease->next_server = offer->siaddr;
913 lease->address = offer->yiaddr;
915 if (lease->address == INADDR_ANY ||
916 lease->server_address == INADDR_ANY ||
917 lease->lifetime == 0) {
918 log_dhcp_client(client, "receieved lease lacks address, server "
919 "address or lease lifetime, ignoring");
923 if (lease->subnet_mask == INADDR_ANY) {
924 r = dhcp_lease_set_default_subnet_mask(lease);
926 log_dhcp_client(client, "receieved lease lacks subnet "
927 "mask, and a fallback one can not be "
928 "generated, ignoring");
933 sd_dhcp_lease_unref(client->lease);
934 client->lease = lease;
937 log_dhcp_client(client, "OFFER");
942 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
946 r = dhcp_option_parse(force, len, NULL, NULL);
947 if (r != DHCP_FORCERENEW)
950 log_dhcp_client(client, "FORCERENEW");
955 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
957 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
960 r = dhcp_lease_new(&lease);
964 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
966 log_dhcp_client(client, "NAK");
967 return -EADDRNOTAVAIL;
971 log_dhcp_client(client, "receieved message was not an ACK, ignoring");
975 lease->next_server = ack->siaddr;
977 lease->address = ack->yiaddr;
979 if (lease->address == INADDR_ANY ||
980 lease->server_address == INADDR_ANY ||
981 lease->lifetime == 0) {
982 log_dhcp_client(client, "receieved lease lacks address, server "
983 "address or lease lifetime, ignoring");
987 if (lease->subnet_mask == INADDR_ANY) {
988 r = dhcp_lease_set_default_subnet_mask(lease);
990 log_dhcp_client(client, "receieved lease lacks subnet "
991 "mask, and a fallback one can not be "
992 "generated, ignoring");
997 r = DHCP_EVENT_IP_ACQUIRE;
999 if (client->lease->address != lease->address ||
1000 client->lease->subnet_mask != lease->subnet_mask ||
1001 client->lease->router != lease->router) {
1002 r = DHCP_EVENT_IP_CHANGE;
1004 r = DHCP_EVENT_RENEW;
1006 client->lease = sd_dhcp_lease_unref(client->lease);
1009 client->lease = lease;
1012 log_dhcp_client(client, "ACK");
1017 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1018 uint32_t lifetime, double factor) {
1020 assert(client->request_sent);
1023 return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1024 + (random_u32() & 0x1fffff);
1027 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1029 uint64_t lifetime_timeout;
1030 uint64_t t2_timeout;
1031 uint64_t t1_timeout;
1032 char time_string[FORMAT_TIMESPAN_MAX];
1036 assert(client->event);
1037 assert(client->lease);
1038 assert(client->lease->lifetime);
1040 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1041 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1042 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1044 /* don't set timers for infinite leases */
1045 if (client->lease->lifetime == 0xffffffff)
1048 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1051 assert(client->request_sent <= time_now);
1053 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1054 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1055 if (client->lease->t1 && client->lease->t2) {
1056 /* both T1 and T2 are given */
1057 if (client->lease->t1 < client->lease->t2 &&
1058 client->lease->t2 < client->lease->lifetime) {
1059 /* they are both valid */
1060 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1061 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1064 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1065 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1066 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1067 client->lease->t1 = client->lease->lifetime / 2;
1069 } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1070 /* only T2 is given, and it is valid */
1071 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1072 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1073 client->lease->t1 = client->lease->lifetime / 2;
1074 if (t2_timeout <= t1_timeout) {
1075 /* the computed T1 would be invalid, so discard T2 */
1076 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1077 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1079 } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1080 /* only T1 is given, and it is valid */
1081 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1082 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1083 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1084 if (t2_timeout <= t1_timeout) {
1085 /* the computed T2 would be invalid, so discard T1 */
1086 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1087 client->lease->t2 = client->lease->lifetime / 2;
1090 /* fall back to the default timeouts */
1091 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1092 client->lease->t1 = client->lease->lifetime / 2;
1093 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1094 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1097 /* arm lifetime timeout */
1098 r = sd_event_add_time(client->event, &client->timeout_expire,
1099 clock_boottime_or_monotonic(),
1100 lifetime_timeout, 10 * USEC_PER_MSEC,
1101 client_timeout_expire, client);
1105 r = sd_event_source_set_priority(client->timeout_expire,
1106 client->event_priority);
1110 log_dhcp_client(client, "lease expires in %s",
1111 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1112 lifetime_timeout - time_now, 0));
1114 /* don't arm earlier timeouts if this has already expired */
1115 if (lifetime_timeout <= time_now)
1118 /* arm T2 timeout */
1119 r = sd_event_add_time(client->event,
1120 &client->timeout_t2,
1121 clock_boottime_or_monotonic(),
1124 client_timeout_t2, client);
1128 r = sd_event_source_set_priority(client->timeout_t2,
1129 client->event_priority);
1133 log_dhcp_client(client, "T2 expires in %s",
1134 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1135 t2_timeout - time_now, 0));
1137 /* don't arm earlier timeout if this has already expired */
1138 if (t2_timeout <= time_now)
1141 /* arm T1 timeout */
1142 r = sd_event_add_time(client->event,
1143 &client->timeout_t1,
1144 clock_boottime_or_monotonic(),
1145 t1_timeout, 10 * USEC_PER_MSEC,
1146 client_timeout_t1, client);
1150 r = sd_event_source_set_priority(client->timeout_t1,
1151 client->event_priority);
1155 log_dhcp_client(client, "T1 expires in %s",
1156 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1157 t1_timeout - time_now, 0));
1162 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1164 DHCP_CLIENT_DONT_DESTROY(client);
1165 int r = 0, notify_event = 0;
1168 assert(client->event);
1171 switch (client->state) {
1172 case DHCP_STATE_SELECTING:
1174 r = client_handle_offer(client, message, len);
1177 client->timeout_resend =
1178 sd_event_source_unref(client->timeout_resend);
1180 client->state = DHCP_STATE_REQUESTING;
1181 client->attempt = 1;
1183 r = sd_event_add_time(client->event,
1184 &client->timeout_resend,
1185 clock_boottime_or_monotonic(),
1187 client_timeout_resend, client);
1191 r = sd_event_source_set_priority(client->timeout_resend,
1192 client->event_priority);
1195 } else if (r == -ENOMSG)
1196 /* invalid message, let's ignore it */
1201 case DHCP_STATE_REBOOTING:
1202 case DHCP_STATE_REQUESTING:
1203 case DHCP_STATE_RENEWING:
1204 case DHCP_STATE_REBINDING:
1206 r = client_handle_ack(client, message, len);
1208 client->timeout_resend =
1209 sd_event_source_unref(client->timeout_resend);
1211 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1212 DHCP_STATE_REBOOTING))
1213 notify_event = DHCP_EVENT_IP_ACQUIRE;
1214 else if (r != DHCP_EVENT_IP_ACQUIRE)
1217 client->state = DHCP_STATE_BOUND;
1218 client->attempt = 1;
1220 client->last_addr = client->lease->address;
1222 r = client_set_lease_timeouts(client);
1226 r = dhcp_network_bind_udp_socket(client->lease->address,
1229 log_dhcp_client(client, "could not bind UDP socket");
1235 client_initialize_io_events(client, client_receive_message_udp);
1238 client_notify(client, notify_event);
1239 if (client->state == DHCP_STATE_STOPPED)
1243 } else if (r == -EADDRNOTAVAIL) {
1244 /* got a NAK, let's restart the client */
1245 client->timeout_resend =
1246 sd_event_source_unref(client->timeout_resend);
1248 r = client_initialize(client);
1252 r = client_start(client);
1256 log_dhcp_client(client, "REBOOTED");
1259 } else if (r == -ENOMSG)
1260 /* invalid message, let's ignore it */
1265 case DHCP_STATE_BOUND:
1266 r = client_handle_forcerenew(client, message, len);
1268 r = client_timeout_t1(NULL, 0, client);
1271 } else if (r == -ENOMSG)
1272 /* invalid message, let's ignore it */
1277 case DHCP_STATE_INIT:
1278 case DHCP_STATE_INIT_REBOOT:
1282 case DHCP_STATE_STOPPED:
1289 client_stop(client, r);
1294 static int client_receive_message_udp(sd_event_source *s, int fd,
1295 uint32_t revents, void *userdata) {
1296 sd_dhcp_client *client = userdata;
1297 _cleanup_free_ DHCPMessage *message = NULL;
1298 int buflen = 0, len, r;
1303 r = ioctl(fd, FIONREAD, &buflen);
1308 /* this can't be right */
1311 message = malloc0(buflen);
1315 len = read(fd, message, buflen);
1317 log_dhcp_client(client, "could not receive message from UDP "
1320 } else if ((size_t)len < sizeof(DHCPMessage)) {
1321 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1325 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1326 log_dhcp_client(client, "not a DHCP message: ignoring");
1330 if (message->op != BOOTREPLY) {
1331 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1335 if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
1336 log_dhcp_client(client, "not an ethernet packet");
1340 if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
1342 log_dhcp_client(client, "received chaddr does not match "
1343 "expected: ignoring");
1347 if (client->state != DHCP_STATE_BOUND &&
1348 be32toh(message->xid) != client->xid) {
1349 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1350 so ignore the xid in this case */
1351 log_dhcp_client(client, "received xid (%u) does not match "
1352 "expected (%u): ignoring",
1353 be32toh(message->xid), client->xid);
1357 return client_handle_message(client, message, len);
1360 static int client_receive_message_raw(sd_event_source *s, int fd,
1361 uint32_t revents, void *userdata) {
1362 sd_dhcp_client *client = userdata;
1363 _cleanup_free_ DHCPPacket *packet = NULL;
1364 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1365 struct iovec iov = {};
1366 struct msghdr msg = {
1369 .msg_control = cmsgbuf,
1370 .msg_controllen = sizeof(cmsgbuf),
1372 struct cmsghdr *cmsg;
1373 bool checksum = true;
1374 int buflen = 0, len, r;
1379 r = ioctl(fd, FIONREAD, &buflen);
1384 /* this can't be right */
1387 packet = malloc0(buflen);
1391 iov.iov_base = packet;
1392 iov.iov_len = buflen;
1394 len = recvmsg(fd, &msg, 0);
1396 log_dhcp_client(client, "could not receive message from raw "
1399 } else if ((size_t)len < sizeof(DHCPPacket))
1402 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1403 if (cmsg->cmsg_level == SOL_PACKET &&
1404 cmsg->cmsg_type == PACKET_AUXDATA &&
1405 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1406 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1408 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1413 r = dhcp_packet_verify_headers(packet, len, checksum);
1417 len -= DHCP_IP_UDP_SIZE;
1419 return client_handle_message(client, &packet->dhcp, len);
1422 int sd_dhcp_client_start(sd_dhcp_client *client) {
1425 assert_return(client, -EINVAL);
1427 r = client_initialize(client);
1431 if (client->last_addr)
1432 client->state = DHCP_STATE_INIT_REBOOT;
1434 r = client_start(client);
1436 log_dhcp_client(client, "STARTED on ifindex %u with address %s",
1438 ether_ntoa(&client->client_id.mac_addr));
1443 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1444 DHCP_CLIENT_DONT_DESTROY(client);
1446 assert_return(client, -EINVAL);
1448 client_stop(client, DHCP_EVENT_STOP);
1449 client->state = DHCP_STATE_STOPPED;
1454 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1458 assert_return(client, -EINVAL);
1459 assert_return(!client->event, -EBUSY);
1462 client->event = sd_event_ref(event);
1464 r = sd_event_default(&client->event);
1469 client->event_priority = priority;
1474 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1475 assert_return(client, -EINVAL);
1477 client->event = sd_event_unref(client->event);
1482 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1486 return client->event;
1489 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1491 assert_se(REFCNT_INC(client->n_ref) >= 2);
1496 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1497 if (client && REFCNT_DEC(client->n_ref) <= 0) {
1498 log_dhcp_client(client, "FREE");
1500 client_initialize(client);
1502 client->receive_message =
1503 sd_event_source_unref(client->receive_message);
1505 sd_dhcp_client_detach_event(client);
1507 sd_dhcp_lease_unref(client->lease);
1509 free(client->req_opts);
1510 free(client->hostname);
1511 free(client->vendor_class_identifier);
1518 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1519 _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1521 assert_return(ret, -EINVAL);
1523 client = new0(sd_dhcp_client, 1);
1527 client->n_ref = REFCNT_INIT;
1528 client->state = DHCP_STATE_INIT;
1531 client->attempt = 1;
1532 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1534 client->req_opts_size = ELEMENTSOF(default_req_opts);
1536 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1537 if (!client->req_opts)