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;
74 sd_event_source *timeout_t1;
75 sd_event_source *timeout_t2;
76 sd_event_source *timeout_expire;
77 sd_dhcp_client_cb_t cb;
82 static const uint8_t default_req_opts[] = {
83 DHCP_OPTION_SUBNET_MASK,
85 DHCP_OPTION_HOST_NAME,
86 DHCP_OPTION_DOMAIN_NAME,
87 DHCP_OPTION_DOMAIN_NAME_SERVER,
88 DHCP_OPTION_NTP_SERVER,
91 static int client_receive_message_raw(sd_event_source *s, int fd,
92 uint32_t revents, void *userdata);
93 static int client_receive_message_udp(sd_event_source *s, int fd,
94 uint32_t revents, void *userdata);
95 static void client_stop(sd_dhcp_client *client, int error);
97 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
99 assert_return(client, -EINVAL);
102 client->userdata = userdata;
107 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
108 assert_return(client, -EINVAL);
110 client->request_broadcast = !!broadcast;
115 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
118 assert_return(client, -EINVAL);
119 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
120 DHCP_STATE_STOPPED), -EBUSY);
123 case DHCP_OPTION_PAD:
124 case DHCP_OPTION_OVERLOAD:
125 case DHCP_OPTION_MESSAGE_TYPE:
126 case DHCP_OPTION_PARAMETER_REQUEST_LIST:
127 case DHCP_OPTION_END:
134 for (i = 0; i < client->req_opts_size; i++)
135 if (client->req_opts[i] == option)
138 if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
139 client->req_opts_size + 1))
142 client->req_opts[client->req_opts_size++] = option;
147 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
148 const struct in_addr *last_addr) {
149 assert_return(client, -EINVAL);
150 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
151 DHCP_STATE_STOPPED), -EBUSY);
154 client->last_addr = last_addr->s_addr;
156 client->last_addr = INADDR_ANY;
161 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
162 assert_return(client, -EINVAL);
163 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
164 DHCP_STATE_STOPPED), -EBUSY);
165 assert_return(interface_index > 0, -EINVAL);
167 client->index = interface_index;
172 int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
173 size_t addr_len, uint16_t arp_type) {
174 DHCP_CLIENT_DONT_DESTROY(client);
175 bool need_restart = false;
177 assert_return(client, -EINVAL);
178 assert_return(addr, -EINVAL);
179 assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
180 assert_return(arp_type > 0, -EINVAL);
182 if (arp_type == ARPHRD_ETHER)
183 assert_return(addr_len == ETH_ALEN, -EINVAL);
184 else if (arp_type == ARPHRD_INFINIBAND)
185 assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
189 if (client->mac_addr_len == addr_len &&
190 memcmp(&client->mac_addr, addr, addr_len) == 0)
193 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
194 log_dhcp_client(client, "Changing MAC address on running DHCP "
195 "client, restarting");
197 client_stop(client, DHCP_EVENT_STOP);
200 memcpy(&client->mac_addr, addr, addr_len);
201 client->mac_addr_len = addr_len;
202 client->arp_type = arp_type;
204 memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
205 client->client_id.type = 0x01;
207 if (need_restart && client->state != DHCP_STATE_STOPPED)
208 sd_dhcp_client_start(client);
213 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
214 const char *hostname) {
215 char *new_hostname = NULL;
217 assert_return(client, -EINVAL);
219 if (streq_ptr(client->hostname, hostname))
223 new_hostname = strdup(hostname);
228 free(client->hostname);
229 client->hostname = new_hostname;
234 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
236 char *new_vci = NULL;
238 assert_return(client, -EINVAL);
240 new_vci = strdup(vci);
244 free(client->vendor_class_identifier);
246 client->vendor_class_identifier = new_vci;
251 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
252 assert_return(client, -EINVAL);
253 assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
260 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
261 assert_return(client, -EINVAL);
262 assert_return(ret, -EINVAL);
264 if (client->state != DHCP_STATE_BOUND &&
265 client->state != DHCP_STATE_RENEWING &&
266 client->state != DHCP_STATE_REBINDING)
267 return -EADDRNOTAVAIL;
269 *ret = sd_dhcp_lease_ref(client->lease);
274 static void client_notify(sd_dhcp_client *client, int event) {
276 client->cb(client, event, client->userdata);
279 static int client_initialize(sd_dhcp_client *client) {
280 assert_return(client, -EINVAL);
282 client->receive_message =
283 sd_event_source_unref(client->receive_message);
285 client->fd = asynchronous_close(client->fd);
287 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
289 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
290 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
291 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
295 client->state = DHCP_STATE_INIT;
299 client->lease = sd_dhcp_lease_unref(client->lease);
304 static void client_stop(sd_dhcp_client *client, int error) {
308 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
309 else if (error == DHCP_EVENT_STOP)
310 log_dhcp_client(client, "STOPPED");
312 log_dhcp_client(client, "STOPPED: Unknown event");
314 client_notify(client, error);
316 client_initialize(client);
319 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
320 uint8_t type, size_t *_optlen, size_t *_optoffset) {
321 _cleanup_free_ DHCPPacket *packet;
322 size_t optlen, optoffset, size;
327 assert(client->secs);
331 assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
333 optlen = DHCP_MIN_OPTIONS_SIZE;
334 size = sizeof(DHCPPacket) + optlen;
336 packet = malloc0(size);
340 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
341 client->arp_type, optlen, &optoffset);
345 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
346 refuse to issue an DHCP lease if 'secs' is set to zero */
347 packet->dhcp.secs = htobe16(client->secs);
349 /* RFC2132 section 4.1
350 A client that cannot receive unicast IP datagrams until its protocol
351 software has been configured with an IP address SHOULD set the
352 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
353 DHCPREQUEST messages that client sends. The BROADCAST bit will
354 provide a hint to the DHCP server and BOOTP relay agent to broadcast
355 any messages to the client on the client's subnet.
357 Note: some interfaces needs this to be enabled, but some networks
358 needs this to be disabled as broadcasts are filteretd, so this
359 needs to be configurable */
360 if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
361 packet->dhcp.flags = htobe16(0x8000);
363 /* RFC2132 section 4.1.1:
364 The client MUST include its hardware address in the ’chaddr’ field, if
365 necessary for delivery of DHCP reply messages. Non-Ethernet
366 interfaces will leave 'chaddr' empty and use the client identifier
367 instead (eg, RFC 4390 section 2.1).
369 if (client->arp_type == ARPHRD_ETHER)
370 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
372 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
373 Identifier option is not set */
374 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
375 DHCP_OPTION_CLIENT_IDENTIFIER,
376 sizeof(client->client_id), &client->client_id);
381 /* RFC2131 section 3.5:
382 in its initial DHCPDISCOVER or DHCPREQUEST message, a
383 client may provide the server with a list of specific
384 parameters the client is interested in. If the client
385 includes a list of parameters in a DHCPDISCOVER message,
386 it MUST include that list in any subsequent DHCPREQUEST
389 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
390 DHCP_OPTION_PARAMETER_REQUEST_LIST,
391 client->req_opts_size, client->req_opts);
395 /* RFC2131 section 3.5:
396 The client SHOULD include the ’maximum DHCP message size’ option to
397 let the server know how large the server may make its DHCP messages.
399 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
400 than the defined default size unless the Maximum Messge Size option
403 RFC3442 "Requirements to Avoid Sizing Constraints":
404 Because a full routing table can be quite large, the standard 576
405 octet maximum size for a DHCP message may be too short to contain
406 some legitimate Classless Static Route options. Because of this,
407 clients implementing the Classless Static Route option SHOULD send a
408 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
409 stack is capable of receiving larger IP datagrams. In this case, the
410 client SHOULD set the value of this option to at least the MTU of the
411 interface that the client is configuring. The client MAY set the
412 value of this option higher, up to the size of the largest UDP packet
413 it is prepared to accept. (Note that the value specified in the
414 Maximum DHCP Message Size option is the total maximum packet size,
415 including IP and UDP headers.)
417 max_size = htobe16(size);
418 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
419 DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
425 *_optoffset = optoffset;
432 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
434 dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
435 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
437 return dhcp_network_send_raw_socket(client->fd, &client->link,
441 static int client_send_discover(sd_dhcp_client *client) {
442 _cleanup_free_ DHCPPacket *discover = NULL;
443 size_t optoffset, optlen;
448 assert(client->state == DHCP_STATE_INIT ||
449 client->state == DHCP_STATE_SELECTING);
451 /* See RFC2131 section 4.4.1 */
453 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
456 assert(time_now >= client->start_time);
458 /* seconds between sending first and last DISCOVER
459 * must always be strictly positive to deal with broken servers */
460 client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
462 r = client_message_init(client, &discover, DHCP_DISCOVER,
463 &optlen, &optoffset);
467 /* the client may suggest values for the network address
468 and lease time in the DHCPDISCOVER message. The client may include
469 the ’requested IP address’ option to suggest that a particular IP
470 address be assigned, and may include the ’IP address lease time’
471 option to suggest the lease time it would like.
473 if (client->last_addr != INADDR_ANY) {
474 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
475 DHCP_OPTION_REQUESTED_IP_ADDRESS,
476 4, &client->last_addr);
481 /* it is unclear from RFC 2131 if client should send hostname in
482 DHCPDISCOVER but dhclient does and so we do as well
484 if (client->hostname) {
485 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
486 DHCP_OPTION_HOST_NAME,
487 strlen(client->hostname), client->hostname);
492 if (client->vendor_class_identifier) {
493 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
494 DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
495 strlen(client->vendor_class_identifier),
496 client->vendor_class_identifier);
501 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
502 DHCP_OPTION_END, 0, NULL);
506 /* We currently ignore:
507 The client SHOULD wait a random time between one and ten seconds to
508 desynchronize the use of DHCP at startup.
510 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
514 log_dhcp_client(client, "DISCOVER");
519 static int client_send_request(sd_dhcp_client *client) {
520 _cleanup_free_ DHCPPacket *request = NULL;
521 size_t optoffset, optlen;
524 r = client_message_init(client, &request, DHCP_REQUEST,
525 &optlen, &optoffset);
529 switch (client->state) {
530 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
531 SELECTING should be REQUESTING)
534 case DHCP_STATE_REQUESTING:
535 /* Client inserts the address of the selected server in ’server
536 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
537 filled in with the yiaddr value from the chosen DHCPOFFER.
540 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
541 DHCP_OPTION_SERVER_IDENTIFIER,
542 4, &client->lease->server_address);
546 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
547 DHCP_OPTION_REQUESTED_IP_ADDRESS,
548 4, &client->lease->address);
554 case DHCP_STATE_INIT_REBOOT:
555 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
556 option MUST be filled in with client’s notion of its previously
557 assigned address. ’ciaddr’ MUST be zero.
559 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
560 DHCP_OPTION_REQUESTED_IP_ADDRESS,
561 4, &client->last_addr);
566 case DHCP_STATE_RENEWING:
567 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
568 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
569 client’s IP address.
573 case DHCP_STATE_REBINDING:
574 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
575 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
576 client’s IP address.
578 This message MUST be broadcast to the 0xffffffff IP broadcast address.
580 request->dhcp.ciaddr = client->lease->address;
584 case DHCP_STATE_INIT:
585 case DHCP_STATE_SELECTING:
586 case DHCP_STATE_REBOOTING:
587 case DHCP_STATE_BOUND:
588 case DHCP_STATE_STOPPED:
592 if (client->hostname) {
593 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
594 DHCP_OPTION_HOST_NAME,
595 strlen(client->hostname), client->hostname);
600 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
601 DHCP_OPTION_END, 0, NULL);
605 if (client->state == DHCP_STATE_RENEWING) {
606 r = dhcp_network_send_udp_socket(client->fd,
607 client->lease->server_address,
610 sizeof(DHCPMessage) + optoffset);
612 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
617 switch (client->state) {
618 case DHCP_STATE_REQUESTING:
619 log_dhcp_client(client, "REQUEST (requesting)");
621 case DHCP_STATE_INIT_REBOOT:
622 log_dhcp_client(client, "REQUEST (init-reboot)");
624 case DHCP_STATE_RENEWING:
625 log_dhcp_client(client, "REQUEST (renewing)");
627 case DHCP_STATE_REBINDING:
628 log_dhcp_client(client, "REQUEST (rebinding)");
631 log_dhcp_client(client, "REQUEST (invalid)");
638 static int client_start(sd_dhcp_client *client);
640 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
642 sd_dhcp_client *client = userdata;
643 DHCP_CLIENT_DONT_DESTROY(client);
644 usec_t next_timeout = 0;
651 assert(client->event);
653 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
657 switch (client->state) {
658 case DHCP_STATE_RENEWING:
660 time_left = (client->lease->t2 - client->lease->t1) / 2;
664 next_timeout = time_now + time_left * USEC_PER_SEC;
668 case DHCP_STATE_REBINDING:
670 time_left = (client->lease->lifetime - client->lease->t2) / 2;
674 next_timeout = time_now + time_left * USEC_PER_SEC;
677 case DHCP_STATE_REBOOTING:
678 /* start over as we did not receive a timely ack or nak */
679 r = client_initialize(client);
683 r = client_start(client);
687 log_dhcp_client(client, "REBOOTED");
691 case DHCP_STATE_INIT:
692 case DHCP_STATE_INIT_REBOOT:
693 case DHCP_STATE_SELECTING:
694 case DHCP_STATE_REQUESTING:
695 case DHCP_STATE_BOUND:
697 if (client->attempt < 64)
698 client->attempt *= 2;
700 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
704 case DHCP_STATE_STOPPED:
709 next_timeout += (random_u32() & 0x1fffff);
711 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
713 r = sd_event_add_time(client->event,
714 &client->timeout_resend,
715 clock_boottime_or_monotonic(),
716 next_timeout, 10 * USEC_PER_MSEC,
717 client_timeout_resend, client);
721 r = sd_event_source_set_priority(client->timeout_resend,
722 client->event_priority);
726 r = sd_event_source_set_name(client->timeout_resend,
727 "dhcp4-resend-timer");
731 switch (client->state) {
732 case DHCP_STATE_INIT:
733 r = client_send_discover(client);
735 client->state = DHCP_STATE_SELECTING;
738 if (client->attempt >= 64)
744 case DHCP_STATE_SELECTING:
745 r = client_send_discover(client);
746 if (r < 0 && client->attempt >= 64)
751 case DHCP_STATE_INIT_REBOOT:
752 case DHCP_STATE_REQUESTING:
753 case DHCP_STATE_RENEWING:
754 case DHCP_STATE_REBINDING:
755 r = client_send_request(client);
756 if (r < 0 && client->attempt >= 64)
759 if (client->state == DHCP_STATE_INIT_REBOOT)
760 client->state = DHCP_STATE_REBOOTING;
762 client->request_sent = time_now;
766 case DHCP_STATE_REBOOTING:
767 case DHCP_STATE_BOUND:
771 case DHCP_STATE_STOPPED:
779 client_stop(client, r);
781 /* Errors were dealt with when stopping the client, don't spill
782 errors into the event loop handler */
786 static int client_initialize_io_events(sd_dhcp_client *client,
787 sd_event_io_handler_t io_callback) {
791 assert(client->event);
793 r = sd_event_add_io(client->event, &client->receive_message,
794 client->fd, EPOLLIN, io_callback,
799 r = sd_event_source_set_priority(client->receive_message,
800 client->event_priority);
804 r = sd_event_source_set_name(client->receive_message,
805 "dhcp4-receive-message");
811 client_stop(client, r);
816 static int client_initialize_time_events(sd_dhcp_client *client) {
820 assert(client->event);
822 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
824 r = sd_event_add_time(client->event,
825 &client->timeout_resend,
826 clock_boottime_or_monotonic(),
828 client_timeout_resend, client);
832 r = sd_event_source_set_priority(client->timeout_resend,
833 client->event_priority);
835 r = sd_event_source_set_name(client->timeout_resend,
836 "dhcp4-resend-timer");
842 client_stop(client, r);
848 static int client_initialize_events(sd_dhcp_client *client,
849 sd_event_io_handler_t io_callback) {
850 client_initialize_io_events(client, io_callback);
851 client_initialize_time_events(client);
856 static int client_start(sd_dhcp_client *client) {
859 assert_return(client, -EINVAL);
860 assert_return(client->event, -EINVAL);
861 assert_return(client->index > 0, -EINVAL);
862 assert_return(client->fd < 0, -EBUSY);
863 assert_return(client->xid == 0, -EINVAL);
864 assert_return(client->state == DHCP_STATE_INIT ||
865 client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
867 client->xid = random_u32();
869 r = dhcp_network_bind_raw_socket(client->index, &client->link,
870 client->xid, client->mac_addr,
871 client->mac_addr_len, client->arp_type);
873 client_stop(client, r);
878 if (client->state == DHCP_STATE_INIT) {
879 client->start_time = now(clock_boottime_or_monotonic());
883 return client_initialize_events(client, client_receive_message_raw);
886 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
888 sd_dhcp_client *client = userdata;
889 DHCP_CLIENT_DONT_DESTROY(client);
891 log_dhcp_client(client, "EXPIRED");
893 client_notify(client, DHCP_EVENT_EXPIRED);
895 /* lease was lost, start over if not freed or stopped in callback */
896 if (client->state != DHCP_STATE_STOPPED) {
897 client_initialize(client);
898 client_start(client);
904 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
905 sd_dhcp_client *client = userdata;
906 DHCP_CLIENT_DONT_DESTROY(client);
909 client->receive_message = sd_event_source_unref(client->receive_message);
910 client->fd = asynchronous_close(client->fd);
912 client->state = DHCP_STATE_REBINDING;
915 r = dhcp_network_bind_raw_socket(client->index, &client->link,
916 client->xid, client->mac_addr,
917 client->mac_addr_len, client->arp_type);
919 client_stop(client, r);
924 return client_initialize_events(client, client_receive_message_raw);
927 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
929 sd_dhcp_client *client = userdata;
930 DHCP_CLIENT_DONT_DESTROY(client);
932 client->state = DHCP_STATE_RENEWING;
935 return client_initialize_time_events(client);
938 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
940 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
943 r = dhcp_lease_new(&lease);
947 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
948 if (r != DHCP_OFFER) {
949 log_dhcp_client(client, "received message was not an OFFER, ignoring");
953 lease->next_server = offer->siaddr;
955 lease->address = offer->yiaddr;
957 if (lease->address == INADDR_ANY ||
958 lease->server_address == INADDR_ANY ||
959 lease->lifetime == 0) {
960 log_dhcp_client(client, "received lease lacks address, server "
961 "address or lease lifetime, ignoring");
965 if (lease->subnet_mask == INADDR_ANY) {
966 r = dhcp_lease_set_default_subnet_mask(lease);
968 log_dhcp_client(client, "received lease lacks subnet "
969 "mask, and a fallback one can not be "
970 "generated, ignoring");
975 sd_dhcp_lease_unref(client->lease);
976 client->lease = lease;
979 log_dhcp_client(client, "OFFER");
984 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
988 r = dhcp_option_parse(force, len, NULL, NULL);
989 if (r != DHCP_FORCERENEW)
992 log_dhcp_client(client, "FORCERENEW");
997 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
999 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
1002 r = dhcp_lease_new(&lease);
1006 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
1007 if (r == DHCP_NAK) {
1008 log_dhcp_client(client, "NAK");
1009 return -EADDRNOTAVAIL;
1012 if (r != DHCP_ACK) {
1013 log_dhcp_client(client, "received message was not an ACK, ignoring");
1017 lease->next_server = ack->siaddr;
1019 lease->address = ack->yiaddr;
1021 if (lease->address == INADDR_ANY ||
1022 lease->server_address == INADDR_ANY ||
1023 lease->lifetime == 0) {
1024 log_dhcp_client(client, "received lease lacks address, server "
1025 "address or lease lifetime, ignoring");
1029 if (lease->subnet_mask == INADDR_ANY) {
1030 r = dhcp_lease_set_default_subnet_mask(lease);
1032 log_dhcp_client(client, "received lease lacks subnet "
1033 "mask, and a fallback one can not be "
1034 "generated, ignoring");
1039 r = DHCP_EVENT_IP_ACQUIRE;
1040 if (client->lease) {
1041 if (client->lease->address != lease->address ||
1042 client->lease->subnet_mask != lease->subnet_mask ||
1043 client->lease->router != lease->router) {
1044 r = DHCP_EVENT_IP_CHANGE;
1046 r = DHCP_EVENT_RENEW;
1048 client->lease = sd_dhcp_lease_unref(client->lease);
1051 client->lease = lease;
1054 log_dhcp_client(client, "ACK");
1059 static uint64_t client_compute_timeout(sd_dhcp_client *client,
1060 uint32_t lifetime, double factor) {
1062 assert(client->request_sent);
1065 return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
1066 + (random_u32() & 0x1fffff);
1069 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1071 uint64_t lifetime_timeout;
1072 uint64_t t2_timeout;
1073 uint64_t t1_timeout;
1074 char time_string[FORMAT_TIMESPAN_MAX];
1078 assert(client->event);
1079 assert(client->lease);
1080 assert(client->lease->lifetime);
1082 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1083 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1084 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1086 /* don't set timers for infinite leases */
1087 if (client->lease->lifetime == 0xffffffff)
1090 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1093 assert(client->request_sent <= time_now);
1095 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1096 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1097 if (client->lease->t1 && client->lease->t2) {
1098 /* both T1 and T2 are given */
1099 if (client->lease->t1 < client->lease->t2 &&
1100 client->lease->t2 < client->lease->lifetime) {
1101 /* they are both valid */
1102 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1103 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1106 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1107 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1108 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1109 client->lease->t1 = client->lease->lifetime / 2;
1111 } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
1112 /* only T2 is given, and it is valid */
1113 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1114 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1115 client->lease->t1 = client->lease->lifetime / 2;
1116 if (t2_timeout <= t1_timeout) {
1117 /* the computed T1 would be invalid, so discard T2 */
1118 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1119 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1121 } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
1122 /* only T1 is given, and it is valid */
1123 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1124 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1125 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1126 if (t2_timeout <= t1_timeout) {
1127 /* the computed T2 would be invalid, so discard T1 */
1128 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1129 client->lease->t2 = client->lease->lifetime / 2;
1132 /* fall back to the default timeouts */
1133 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1134 client->lease->t1 = client->lease->lifetime / 2;
1135 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1136 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1139 /* arm lifetime timeout */
1140 r = sd_event_add_time(client->event, &client->timeout_expire,
1141 clock_boottime_or_monotonic(),
1142 lifetime_timeout, 10 * USEC_PER_MSEC,
1143 client_timeout_expire, client);
1147 r = sd_event_source_set_priority(client->timeout_expire,
1148 client->event_priority);
1152 r = sd_event_source_set_name(client->timeout_expire,
1157 log_dhcp_client(client, "lease expires in %s",
1158 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1159 lifetime_timeout - time_now, 0));
1161 /* don't arm earlier timeouts if this has already expired */
1162 if (lifetime_timeout <= time_now)
1165 /* arm T2 timeout */
1166 r = sd_event_add_time(client->event,
1167 &client->timeout_t2,
1168 clock_boottime_or_monotonic(),
1171 client_timeout_t2, client);
1175 r = sd_event_source_set_priority(client->timeout_t2,
1176 client->event_priority);
1180 r = sd_event_source_set_name(client->timeout_t2,
1181 "dhcp4-t2-timeout");
1185 log_dhcp_client(client, "T2 expires in %s",
1186 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1187 t2_timeout - time_now, 0));
1189 /* don't arm earlier timeout if this has already expired */
1190 if (t2_timeout <= time_now)
1193 /* arm T1 timeout */
1194 r = sd_event_add_time(client->event,
1195 &client->timeout_t1,
1196 clock_boottime_or_monotonic(),
1197 t1_timeout, 10 * USEC_PER_MSEC,
1198 client_timeout_t1, client);
1202 r = sd_event_source_set_priority(client->timeout_t1,
1203 client->event_priority);
1207 r = sd_event_source_set_name(client->timeout_t1,
1212 log_dhcp_client(client, "T1 expires in %s",
1213 format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1214 t1_timeout - time_now, 0));
1219 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1221 DHCP_CLIENT_DONT_DESTROY(client);
1222 int r = 0, notify_event = 0;
1225 assert(client->event);
1228 switch (client->state) {
1229 case DHCP_STATE_SELECTING:
1231 r = client_handle_offer(client, message, len);
1234 client->timeout_resend =
1235 sd_event_source_unref(client->timeout_resend);
1237 client->state = DHCP_STATE_REQUESTING;
1238 client->attempt = 1;
1240 r = sd_event_add_time(client->event,
1241 &client->timeout_resend,
1242 clock_boottime_or_monotonic(),
1244 client_timeout_resend, client);
1248 r = sd_event_source_set_priority(client->timeout_resend,
1249 client->event_priority);
1253 r = sd_event_source_set_name(client->timeout_resend,
1254 "dhcp4-resend-timer");
1257 } else if (r == -ENOMSG)
1258 /* invalid message, let's ignore it */
1263 case DHCP_STATE_REBOOTING:
1264 case DHCP_STATE_REQUESTING:
1265 case DHCP_STATE_RENEWING:
1266 case DHCP_STATE_REBINDING:
1268 r = client_handle_ack(client, message, len);
1270 client->timeout_resend =
1271 sd_event_source_unref(client->timeout_resend);
1272 client->receive_message =
1273 sd_event_source_unref(client->receive_message);
1274 client->fd = asynchronous_close(client->fd);
1276 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1277 DHCP_STATE_REBOOTING))
1278 notify_event = DHCP_EVENT_IP_ACQUIRE;
1279 else if (r != DHCP_EVENT_IP_ACQUIRE)
1282 client->state = DHCP_STATE_BOUND;
1283 client->attempt = 1;
1285 client->last_addr = client->lease->address;
1287 r = client_set_lease_timeouts(client);
1291 r = dhcp_network_bind_udp_socket(client->lease->address,
1294 log_dhcp_client(client, "could not bind UDP socket");
1300 client_initialize_io_events(client, client_receive_message_udp);
1303 client_notify(client, notify_event);
1304 if (client->state == DHCP_STATE_STOPPED)
1308 } else if (r == -EADDRNOTAVAIL) {
1309 /* got a NAK, let's restart the client */
1310 client->timeout_resend =
1311 sd_event_source_unref(client->timeout_resend);
1313 r = client_initialize(client);
1317 r = client_start(client);
1321 log_dhcp_client(client, "REBOOTED");
1324 } else if (r == -ENOMSG)
1325 /* invalid message, let's ignore it */
1330 case DHCP_STATE_BOUND:
1331 r = client_handle_forcerenew(client, message, len);
1333 r = client_timeout_t1(NULL, 0, client);
1336 } else if (r == -ENOMSG)
1337 /* invalid message, let's ignore it */
1342 case DHCP_STATE_INIT:
1343 case DHCP_STATE_INIT_REBOOT:
1347 case DHCP_STATE_STOPPED:
1354 client_stop(client, r);
1359 static int client_receive_message_udp(sd_event_source *s, int fd,
1360 uint32_t revents, void *userdata) {
1361 sd_dhcp_client *client = userdata;
1362 _cleanup_free_ DHCPMessage *message = NULL;
1363 int buflen = 0, len, r;
1364 const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1365 const struct ether_addr *expected_chaddr = NULL;
1366 uint8_t expected_hlen = 0;
1371 r = ioctl(fd, FIONREAD, &buflen);
1376 /* this can't be right */
1379 message = malloc0(buflen);
1383 len = read(fd, message, buflen);
1385 log_dhcp_client(client, "could not receive message from UDP "
1388 } else if ((size_t)len < sizeof(DHCPMessage)) {
1389 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1393 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1394 log_dhcp_client(client, "not a DHCP message: ignoring");
1398 if (message->op != BOOTREPLY) {
1399 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1403 if (message->htype != client->arp_type) {
1404 log_dhcp_client(client, "packet type does not match client type");
1408 if (client->arp_type == ARPHRD_ETHER) {
1409 expected_hlen = ETH_ALEN;
1410 expected_chaddr = (const struct ether_addr *) &client->mac_addr;
1412 /* Non-ethernet links expect zero chaddr */
1414 expected_chaddr = &zero_mac;
1417 if (message->hlen != expected_hlen) {
1418 log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
1422 if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
1423 log_dhcp_client(client, "received chaddr does not match "
1424 "expected: ignoring");
1428 if (client->state != DHCP_STATE_BOUND &&
1429 be32toh(message->xid) != client->xid) {
1430 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1431 so ignore the xid in this case */
1432 log_dhcp_client(client, "received xid (%u) does not match "
1433 "expected (%u): ignoring",
1434 be32toh(message->xid), client->xid);
1438 return client_handle_message(client, message, len);
1441 static int client_receive_message_raw(sd_event_source *s, int fd,
1442 uint32_t revents, void *userdata) {
1443 sd_dhcp_client *client = userdata;
1444 _cleanup_free_ DHCPPacket *packet = NULL;
1445 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1446 struct iovec iov = {};
1447 struct msghdr msg = {
1450 .msg_control = cmsgbuf,
1451 .msg_controllen = sizeof(cmsgbuf),
1453 struct cmsghdr *cmsg;
1454 bool checksum = true;
1455 int buflen = 0, len, r;
1460 r = ioctl(fd, FIONREAD, &buflen);
1465 /* this can't be right */
1468 packet = malloc0(buflen);
1472 iov.iov_base = packet;
1473 iov.iov_len = buflen;
1475 len = recvmsg(fd, &msg, 0);
1477 log_dhcp_client(client, "could not receive message from raw "
1480 } else if ((size_t)len < sizeof(DHCPPacket))
1483 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1484 if (cmsg->cmsg_level == SOL_PACKET &&
1485 cmsg->cmsg_type == PACKET_AUXDATA &&
1486 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1487 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1489 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1494 r = dhcp_packet_verify_headers(packet, len, checksum);
1498 len -= DHCP_IP_UDP_SIZE;
1500 return client_handle_message(client, &packet->dhcp, len);
1503 int sd_dhcp_client_start(sd_dhcp_client *client) {
1506 assert_return(client, -EINVAL);
1508 r = client_initialize(client);
1512 if (client->last_addr)
1513 client->state = DHCP_STATE_INIT_REBOOT;
1515 r = client_start(client);
1517 log_dhcp_client(client, "STARTED on ifindex %u", client->index);
1522 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1523 DHCP_CLIENT_DONT_DESTROY(client);
1525 assert_return(client, -EINVAL);
1527 client_stop(client, DHCP_EVENT_STOP);
1528 client->state = DHCP_STATE_STOPPED;
1533 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1537 assert_return(client, -EINVAL);
1538 assert_return(!client->event, -EBUSY);
1541 client->event = sd_event_ref(event);
1543 r = sd_event_default(&client->event);
1548 client->event_priority = priority;
1553 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1554 assert_return(client, -EINVAL);
1556 client->event = sd_event_unref(client->event);
1561 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1565 return client->event;
1568 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1570 assert_se(REFCNT_INC(client->n_ref) >= 2);
1575 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1576 if (client && REFCNT_DEC(client->n_ref) <= 0) {
1577 log_dhcp_client(client, "FREE");
1579 client_initialize(client);
1581 client->receive_message =
1582 sd_event_source_unref(client->receive_message);
1584 sd_dhcp_client_detach_event(client);
1586 sd_dhcp_lease_unref(client->lease);
1588 free(client->req_opts);
1589 free(client->hostname);
1590 free(client->vendor_class_identifier);
1597 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1598 _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1600 assert_return(ret, -EINVAL);
1602 client = new0(sd_dhcp_client, 1);
1606 client->n_ref = REFCNT_INIT;
1607 client->state = DHCP_STATE_INIT;
1610 client->attempt = 1;
1611 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1613 client->req_opts_size = ELEMENTSOF(default_req_opts);
1615 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1616 if (!client->req_opts)