]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-client.c
Merge pull request #2409 from snakeroot/dropin-doc-2
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp-client.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5
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.
10
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.
15
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/>.
18 ***/
19
20 #include <errno.h>
21 #include <net/ethernet.h>
22 #include <net/if_arp.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/ioctl.h>
27 #include <linux/if_infiniband.h>
28
29 #include "sd-dhcp-client.h"
30
31 #include "alloc-util.h"
32 #include "async.h"
33 #include "dhcp-identifier.h"
34 #include "dhcp-internal.h"
35 #include "dhcp-lease-internal.h"
36 #include "dhcp-protocol.h"
37 #include "dns-domain.h"
38 #include "hostname-util.h"
39 #include "random-util.h"
40 #include "string-util.h"
41 #include "util.h"
42
43 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
44 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
45
46 struct sd_dhcp_client {
47 unsigned n_ref;
48
49 DHCPState state;
50 sd_event *event;
51 int event_priority;
52 sd_event_source *timeout_resend;
53 int index;
54 int fd;
55 union sockaddr_union link;
56 sd_event_source *receive_message;
57 bool request_broadcast;
58 uint8_t *req_opts;
59 size_t req_opts_allocated;
60 size_t req_opts_size;
61 be32_t last_addr;
62 uint8_t mac_addr[MAX_MAC_ADDR_LEN];
63 size_t mac_addr_len;
64 uint16_t arp_type;
65 struct {
66 uint8_t type;
67 union {
68 struct {
69 /* 0: Generic (non-LL) (RFC 2132) */
70 uint8_t data[MAX_CLIENT_ID_LEN];
71 } _packed_ gen;
72 struct {
73 /* 1: Ethernet Link-Layer (RFC 2132) */
74 uint8_t haddr[ETH_ALEN];
75 } _packed_ eth;
76 struct {
77 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
78 uint8_t haddr[0];
79 } _packed_ ll;
80 struct {
81 /* 255: Node-specific (RFC 4361) */
82 uint32_t iaid;
83 struct duid duid;
84 } _packed_ ns;
85 struct {
86 uint8_t data[MAX_CLIENT_ID_LEN];
87 } _packed_ raw;
88 };
89 } _packed_ client_id;
90 size_t client_id_len;
91 char *hostname;
92 char *vendor_class_identifier;
93 uint32_t mtu;
94 uint32_t xid;
95 usec_t start_time;
96 unsigned int attempt;
97 usec_t request_sent;
98 sd_event_source *timeout_t1;
99 sd_event_source *timeout_t2;
100 sd_event_source *timeout_expire;
101 sd_dhcp_client_cb_t cb;
102 void *userdata;
103 sd_dhcp_lease *lease;
104 };
105
106 static const uint8_t default_req_opts[] = {
107 SD_DHCP_OPTION_SUBNET_MASK,
108 SD_DHCP_OPTION_ROUTER,
109 SD_DHCP_OPTION_HOST_NAME,
110 SD_DHCP_OPTION_DOMAIN_NAME,
111 SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
112 };
113
114 static int client_receive_message_raw(sd_event_source *s, int fd,
115 uint32_t revents, void *userdata);
116 static int client_receive_message_udp(sd_event_source *s, int fd,
117 uint32_t revents, void *userdata);
118 static void client_stop(sd_dhcp_client *client, int error);
119
120 int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
121 void *userdata) {
122 assert_return(client, -EINVAL);
123
124 client->cb = cb;
125 client->userdata = userdata;
126
127 return 0;
128 }
129
130 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
131 assert_return(client, -EINVAL);
132
133 client->request_broadcast = !!broadcast;
134
135 return 0;
136 }
137
138 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
139 size_t i;
140
141 assert_return(client, -EINVAL);
142 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
143 DHCP_STATE_STOPPED), -EBUSY);
144
145 switch(option) {
146 case SD_DHCP_OPTION_PAD:
147 case SD_DHCP_OPTION_OVERLOAD:
148 case SD_DHCP_OPTION_MESSAGE_TYPE:
149 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
150 case SD_DHCP_OPTION_END:
151 return -EINVAL;
152
153 default:
154 break;
155 }
156
157 for (i = 0; i < client->req_opts_size; i++)
158 if (client->req_opts[i] == option)
159 return -EEXIST;
160
161 if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
162 client->req_opts_size + 1))
163 return -ENOMEM;
164
165 client->req_opts[client->req_opts_size++] = option;
166
167 return 0;
168 }
169
170 int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
171 const struct in_addr *last_addr) {
172 assert_return(client, -EINVAL);
173 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
174 DHCP_STATE_STOPPED), -EBUSY);
175
176 if (last_addr)
177 client->last_addr = last_addr->s_addr;
178 else
179 client->last_addr = INADDR_ANY;
180
181 return 0;
182 }
183
184 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
185 assert_return(client, -EINVAL);
186 assert_return (IN_SET(client->state, DHCP_STATE_INIT,
187 DHCP_STATE_STOPPED), -EBUSY);
188 assert_return(interface_index > 0, -EINVAL);
189
190 client->index = interface_index;
191
192 return 0;
193 }
194
195 int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
196 size_t addr_len, uint16_t arp_type) {
197 DHCP_CLIENT_DONT_DESTROY(client);
198 bool need_restart = false;
199
200 assert_return(client, -EINVAL);
201 assert_return(addr, -EINVAL);
202 assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
203 assert_return(arp_type > 0, -EINVAL);
204
205 if (arp_type == ARPHRD_ETHER)
206 assert_return(addr_len == ETH_ALEN, -EINVAL);
207 else if (arp_type == ARPHRD_INFINIBAND)
208 assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
209 else
210 return -EINVAL;
211
212 if (client->mac_addr_len == addr_len &&
213 memcmp(&client->mac_addr, addr, addr_len) == 0)
214 return 0;
215
216 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
217 log_dhcp_client(client, "Changing MAC address on running DHCP "
218 "client, restarting");
219 need_restart = true;
220 client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
221 }
222
223 memcpy(&client->mac_addr, addr, addr_len);
224 client->mac_addr_len = addr_len;
225 client->arp_type = arp_type;
226
227 if (need_restart && client->state != DHCP_STATE_STOPPED)
228 sd_dhcp_client_start(client);
229
230 return 0;
231 }
232
233 int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
234 const uint8_t **data, size_t *data_len) {
235
236 assert_return(client, -EINVAL);
237 assert_return(type, -EINVAL);
238 assert_return(data, -EINVAL);
239 assert_return(data_len, -EINVAL);
240
241 *type = 0;
242 *data = NULL;
243 *data_len = 0;
244 if (client->client_id_len) {
245 *type = client->client_id.type;
246 *data = client->client_id.raw.data;
247 *data_len = client->client_id_len - sizeof(client->client_id.type);
248 }
249
250 return 0;
251 }
252
253 int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
254 const uint8_t *data, size_t data_len) {
255 DHCP_CLIENT_DONT_DESTROY(client);
256 bool need_restart = false;
257
258 assert_return(client, -EINVAL);
259 assert_return(data, -EINVAL);
260 assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
261
262 switch (type) {
263 case ARPHRD_ETHER:
264 if (data_len != ETH_ALEN)
265 return -EINVAL;
266 break;
267 case ARPHRD_INFINIBAND:
268 if (data_len != INFINIBAND_ALEN)
269 return -EINVAL;
270 break;
271 default:
272 break;
273 }
274
275 if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
276 client->client_id.type == type &&
277 memcmp(&client->client_id.raw.data, data, data_len) == 0)
278 return 0;
279
280 if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
281 log_dhcp_client(client, "Changing client ID on running DHCP "
282 "client, restarting");
283 need_restart = true;
284 client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
285 }
286
287 client->client_id.type = type;
288 memcpy(&client->client_id.raw.data, data, data_len);
289 client->client_id_len = data_len + sizeof (client->client_id.type);
290
291 if (need_restart && client->state != DHCP_STATE_STOPPED)
292 sd_dhcp_client_start(client);
293
294 return 0;
295 }
296
297 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
298 const char *hostname) {
299 char *new_hostname = NULL;
300
301 assert_return(client, -EINVAL);
302
303 if (!hostname_is_valid(hostname, false) && !dns_name_is_valid(hostname))
304 return -EINVAL;
305
306 if (streq_ptr(client->hostname, hostname))
307 return 0;
308
309 if (hostname) {
310 new_hostname = strdup(hostname);
311 if (!new_hostname)
312 return -ENOMEM;
313 }
314
315 free(client->hostname);
316 client->hostname = new_hostname;
317
318 return 0;
319 }
320
321 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
322 const char *vci) {
323 char *new_vci = NULL;
324
325 assert_return(client, -EINVAL);
326
327 new_vci = strdup(vci);
328 if (!new_vci)
329 return -ENOMEM;
330
331 free(client->vendor_class_identifier);
332
333 client->vendor_class_identifier = new_vci;
334
335 return 0;
336 }
337
338 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
339 assert_return(client, -EINVAL);
340 assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
341
342 client->mtu = mtu;
343
344 return 0;
345 }
346
347 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
348 assert_return(client, -EINVAL);
349 assert_return(ret, -EINVAL);
350
351 if (client->state != DHCP_STATE_BOUND &&
352 client->state != DHCP_STATE_RENEWING &&
353 client->state != DHCP_STATE_REBINDING)
354 return -EADDRNOTAVAIL;
355
356 *ret = client->lease;
357
358 return 0;
359 }
360
361 static void client_notify(sd_dhcp_client *client, int event) {
362 if (client->cb)
363 client->cb(client, event, client->userdata);
364 }
365
366 static int client_initialize(sd_dhcp_client *client) {
367 assert_return(client, -EINVAL);
368
369 client->receive_message =
370 sd_event_source_unref(client->receive_message);
371
372 client->fd = asynchronous_close(client->fd);
373
374 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
375
376 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
377 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
378 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
379
380 client->attempt = 1;
381
382 client->state = DHCP_STATE_INIT;
383 client->xid = 0;
384
385 client->lease = sd_dhcp_lease_unref(client->lease);
386
387 return 0;
388 }
389
390 static void client_stop(sd_dhcp_client *client, int error) {
391 assert(client);
392
393 if (error < 0)
394 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
395 else if (error == SD_DHCP_CLIENT_EVENT_STOP)
396 log_dhcp_client(client, "STOPPED");
397 else
398 log_dhcp_client(client, "STOPPED: Unknown event");
399
400 client_notify(client, error);
401
402 client_initialize(client);
403 }
404
405 static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
406 uint8_t type, size_t *_optlen, size_t *_optoffset) {
407 _cleanup_free_ DHCPPacket *packet;
408 size_t optlen, optoffset, size;
409 be16_t max_size;
410 usec_t time_now;
411 uint16_t secs;
412 int r;
413
414 assert(client);
415 assert(client->start_time);
416 assert(ret);
417 assert(_optlen);
418 assert(_optoffset);
419 assert(type == DHCP_DISCOVER || type == DHCP_REQUEST);
420
421 optlen = DHCP_MIN_OPTIONS_SIZE;
422 size = sizeof(DHCPPacket) + optlen;
423
424 packet = malloc0(size);
425 if (!packet)
426 return -ENOMEM;
427
428 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
429 client->arp_type, optlen, &optoffset);
430 if (r < 0)
431 return r;
432
433 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
434 refuse to issue an DHCP lease if 'secs' is set to zero */
435 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
436 if (r < 0)
437 return r;
438 assert(time_now >= client->start_time);
439
440 /* seconds between sending first and last DISCOVER
441 * must always be strictly positive to deal with broken servers */
442 secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
443 packet->dhcp.secs = htobe16(secs);
444
445 /* RFC2132 section 4.1
446 A client that cannot receive unicast IP datagrams until its protocol
447 software has been configured with an IP address SHOULD set the
448 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
449 DHCPREQUEST messages that client sends. The BROADCAST bit will
450 provide a hint to the DHCP server and BOOTP relay agent to broadcast
451 any messages to the client on the client's subnet.
452
453 Note: some interfaces needs this to be enabled, but some networks
454 needs this to be disabled as broadcasts are filteretd, so this
455 needs to be configurable */
456 if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
457 packet->dhcp.flags = htobe16(0x8000);
458
459 /* RFC2132 section 4.1.1:
460 The client MUST include its hardware address in the ’chaddr’ field, if
461 necessary for delivery of DHCP reply messages. Non-Ethernet
462 interfaces will leave 'chaddr' empty and use the client identifier
463 instead (eg, RFC 4390 section 2.1).
464 */
465 if (client->arp_type == ARPHRD_ETHER)
466 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
467
468 /* If no client identifier exists, construct an RFC 4361-compliant one */
469 if (client->client_id_len == 0) {
470 size_t duid_len;
471
472 client->client_id.type = 255;
473
474 r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
475 if (r < 0)
476 return r;
477
478 r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len);
479 if (r < 0)
480 return r;
481
482 client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
483 }
484
485 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
486 Identifier option is not set */
487 if (client->client_id_len) {
488 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
489 SD_DHCP_OPTION_CLIENT_IDENTIFIER,
490 client->client_id_len,
491 &client->client_id);
492 if (r < 0)
493 return r;
494 }
495
496 /* RFC2131 section 3.5:
497 in its initial DHCPDISCOVER or DHCPREQUEST message, a
498 client may provide the server with a list of specific
499 parameters the client is interested in. If the client
500 includes a list of parameters in a DHCPDISCOVER message,
501 it MUST include that list in any subsequent DHCPREQUEST
502 messages.
503 */
504 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
505 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
506 client->req_opts_size, client->req_opts);
507 if (r < 0)
508 return r;
509
510 /* RFC2131 section 3.5:
511 The client SHOULD include the ’maximum DHCP message size’ option to
512 let the server know how large the server may make its DHCP messages.
513
514 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
515 than the defined default size unless the Maximum Messge Size option
516 is explicitly set
517
518 RFC3442 "Requirements to Avoid Sizing Constraints":
519 Because a full routing table can be quite large, the standard 576
520 octet maximum size for a DHCP message may be too short to contain
521 some legitimate Classless Static Route options. Because of this,
522 clients implementing the Classless Static Route option SHOULD send a
523 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
524 stack is capable of receiving larger IP datagrams. In this case, the
525 client SHOULD set the value of this option to at least the MTU of the
526 interface that the client is configuring. The client MAY set the
527 value of this option higher, up to the size of the largest UDP packet
528 it is prepared to accept. (Note that the value specified in the
529 Maximum DHCP Message Size option is the total maximum packet size,
530 including IP and UDP headers.)
531 */
532 max_size = htobe16(size);
533 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
534 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
535 2, &max_size);
536 if (r < 0)
537 return r;
538
539 *_optlen = optlen;
540 *_optoffset = optoffset;
541 *ret = packet;
542 packet = NULL;
543
544 return 0;
545 }
546
547 static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset,
548 const char *fqdn) {
549 uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
550 int r;
551
552 buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */
553 DHCP_FQDN_FLAG_E; /* Canonical wire format */
554 buffer[1] = 0; /* RCODE1 (deprecated) */
555 buffer[2] = 0; /* RCODE2 (deprecated) */
556
557 r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false);
558 if (r > 0)
559 r = dhcp_option_append(message, optlen, optoffset, 0,
560 SD_DHCP_OPTION_FQDN, 3 + r, buffer);
561
562 return r;
563 }
564
565 static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
566 size_t len) {
567 dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
568 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
569
570 return dhcp_network_send_raw_socket(client->fd, &client->link,
571 packet, len);
572 }
573
574 static int client_send_discover(sd_dhcp_client *client) {
575 _cleanup_free_ DHCPPacket *discover = NULL;
576 size_t optoffset, optlen;
577 int r;
578
579 assert(client);
580 assert(client->state == DHCP_STATE_INIT ||
581 client->state == DHCP_STATE_SELECTING);
582
583 r = client_message_init(client, &discover, DHCP_DISCOVER,
584 &optlen, &optoffset);
585 if (r < 0)
586 return r;
587
588 /* the client may suggest values for the network address
589 and lease time in the DHCPDISCOVER message. The client may include
590 the ’requested IP address’ option to suggest that a particular IP
591 address be assigned, and may include the ’IP address lease time’
592 option to suggest the lease time it would like.
593 */
594 if (client->last_addr != INADDR_ANY) {
595 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
596 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
597 4, &client->last_addr);
598 if (r < 0)
599 return r;
600 }
601
602 if (client->hostname) {
603 /* According to RFC 4702 "clients that send the Client FQDN option in
604 their messages MUST NOT also send the Host Name option". Just send
605 one of the two depending on the hostname type.
606 */
607 if (dns_name_is_single_label(client->hostname)) {
608 /* it is unclear from RFC 2131 if client should send hostname in
609 DHCPDISCOVER but dhclient does and so we do as well
610 */
611 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
612 SD_DHCP_OPTION_HOST_NAME,
613 strlen(client->hostname), client->hostname);
614 } else
615 r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
616 client->hostname);
617 if (r < 0)
618 return r;
619 }
620
621 if (client->vendor_class_identifier) {
622 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
623 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
624 strlen(client->vendor_class_identifier),
625 client->vendor_class_identifier);
626 if (r < 0)
627 return r;
628 }
629
630 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
631 SD_DHCP_OPTION_END, 0, NULL);
632 if (r < 0)
633 return r;
634
635 /* We currently ignore:
636 The client SHOULD wait a random time between one and ten seconds to
637 desynchronize the use of DHCP at startup.
638 */
639 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
640 if (r < 0)
641 return r;
642
643 log_dhcp_client(client, "DISCOVER");
644
645 return 0;
646 }
647
648 static int client_send_request(sd_dhcp_client *client) {
649 _cleanup_free_ DHCPPacket *request = NULL;
650 size_t optoffset, optlen;
651 int r;
652
653 r = client_message_init(client, &request, DHCP_REQUEST,
654 &optlen, &optoffset);
655 if (r < 0)
656 return r;
657
658 switch (client->state) {
659 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
660 SELECTING should be REQUESTING)
661 */
662
663 case DHCP_STATE_REQUESTING:
664 /* Client inserts the address of the selected server in ’server
665 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
666 filled in with the yiaddr value from the chosen DHCPOFFER.
667 */
668
669 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
670 SD_DHCP_OPTION_SERVER_IDENTIFIER,
671 4, &client->lease->server_address);
672 if (r < 0)
673 return r;
674
675 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
676 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
677 4, &client->lease->address);
678 if (r < 0)
679 return r;
680
681 break;
682
683 case DHCP_STATE_INIT_REBOOT:
684 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
685 option MUST be filled in with client’s notion of its previously
686 assigned address. ’ciaddr’ MUST be zero.
687 */
688 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
689 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
690 4, &client->last_addr);
691 if (r < 0)
692 return r;
693 break;
694
695 case DHCP_STATE_RENEWING:
696 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
697 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
698 client’s IP address.
699 */
700
701 /* fall through */
702 case DHCP_STATE_REBINDING:
703 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
704 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
705 client’s IP address.
706
707 This message MUST be broadcast to the 0xffffffff IP broadcast address.
708 */
709 request->dhcp.ciaddr = client->lease->address;
710
711 break;
712
713 case DHCP_STATE_INIT:
714 case DHCP_STATE_SELECTING:
715 case DHCP_STATE_REBOOTING:
716 case DHCP_STATE_BOUND:
717 case DHCP_STATE_STOPPED:
718 return -EINVAL;
719 }
720
721 if (client->hostname) {
722 if (dns_name_is_single_label(client->hostname))
723 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
724 SD_DHCP_OPTION_HOST_NAME,
725 strlen(client->hostname), client->hostname);
726 else
727 r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
728 client->hostname);
729 if (r < 0)
730 return r;
731 }
732
733 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
734 SD_DHCP_OPTION_END, 0, NULL);
735 if (r < 0)
736 return r;
737
738 if (client->state == DHCP_STATE_RENEWING) {
739 r = dhcp_network_send_udp_socket(client->fd,
740 client->lease->server_address,
741 DHCP_PORT_SERVER,
742 &request->dhcp,
743 sizeof(DHCPMessage) + optoffset);
744 } else {
745 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
746 }
747 if (r < 0)
748 return r;
749
750 switch (client->state) {
751 case DHCP_STATE_REQUESTING:
752 log_dhcp_client(client, "REQUEST (requesting)");
753 break;
754 case DHCP_STATE_INIT_REBOOT:
755 log_dhcp_client(client, "REQUEST (init-reboot)");
756 break;
757 case DHCP_STATE_RENEWING:
758 log_dhcp_client(client, "REQUEST (renewing)");
759 break;
760 case DHCP_STATE_REBINDING:
761 log_dhcp_client(client, "REQUEST (rebinding)");
762 break;
763 default:
764 log_dhcp_client(client, "REQUEST (invalid)");
765 break;
766 }
767
768 return 0;
769 }
770
771 static int client_start(sd_dhcp_client *client);
772
773 static int client_timeout_resend(sd_event_source *s, uint64_t usec,
774 void *userdata) {
775 sd_dhcp_client *client = userdata;
776 DHCP_CLIENT_DONT_DESTROY(client);
777 usec_t next_timeout = 0;
778 uint64_t time_now;
779 uint32_t time_left;
780 int r;
781
782 assert(s);
783 assert(client);
784 assert(client->event);
785
786 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
787 if (r < 0)
788 goto error;
789
790 switch (client->state) {
791 case DHCP_STATE_RENEWING:
792
793 time_left = (client->lease->t2 - client->lease->t1) / 2;
794 if (time_left < 60)
795 time_left = 60;
796
797 next_timeout = time_now + time_left * USEC_PER_SEC;
798
799 break;
800
801 case DHCP_STATE_REBINDING:
802
803 time_left = (client->lease->lifetime - client->lease->t2) / 2;
804 if (time_left < 60)
805 time_left = 60;
806
807 next_timeout = time_now + time_left * USEC_PER_SEC;
808 break;
809
810 case DHCP_STATE_REBOOTING:
811 /* start over as we did not receive a timely ack or nak */
812 r = client_initialize(client);
813 if (r < 0)
814 goto error;
815
816 r = client_start(client);
817 if (r < 0)
818 goto error;
819 else {
820 log_dhcp_client(client, "REBOOTED");
821 return 0;
822 }
823
824 case DHCP_STATE_INIT:
825 case DHCP_STATE_INIT_REBOOT:
826 case DHCP_STATE_SELECTING:
827 case DHCP_STATE_REQUESTING:
828 case DHCP_STATE_BOUND:
829
830 if (client->attempt < 64)
831 client->attempt *= 2;
832
833 next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
834
835 break;
836
837 case DHCP_STATE_STOPPED:
838 r = -EINVAL;
839 goto error;
840 }
841
842 next_timeout += (random_u32() & 0x1fffff);
843
844 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
845
846 r = sd_event_add_time(client->event,
847 &client->timeout_resend,
848 clock_boottime_or_monotonic(),
849 next_timeout, 10 * USEC_PER_MSEC,
850 client_timeout_resend, client);
851 if (r < 0)
852 goto error;
853
854 r = sd_event_source_set_priority(client->timeout_resend,
855 client->event_priority);
856 if (r < 0)
857 goto error;
858
859 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
860 if (r < 0)
861 goto error;
862
863 switch (client->state) {
864 case DHCP_STATE_INIT:
865 r = client_send_discover(client);
866 if (r >= 0) {
867 client->state = DHCP_STATE_SELECTING;
868 client->attempt = 1;
869 } else {
870 if (client->attempt >= 64)
871 goto error;
872 }
873
874 break;
875
876 case DHCP_STATE_SELECTING:
877 r = client_send_discover(client);
878 if (r < 0 && client->attempt >= 64)
879 goto error;
880
881 break;
882
883 case DHCP_STATE_INIT_REBOOT:
884 case DHCP_STATE_REQUESTING:
885 case DHCP_STATE_RENEWING:
886 case DHCP_STATE_REBINDING:
887 r = client_send_request(client);
888 if (r < 0 && client->attempt >= 64)
889 goto error;
890
891 if (client->state == DHCP_STATE_INIT_REBOOT)
892 client->state = DHCP_STATE_REBOOTING;
893
894 client->request_sent = time_now;
895
896 break;
897
898 case DHCP_STATE_REBOOTING:
899 case DHCP_STATE_BOUND:
900
901 break;
902
903 case DHCP_STATE_STOPPED:
904 r = -EINVAL;
905 goto error;
906 }
907
908 return 0;
909
910 error:
911 client_stop(client, r);
912
913 /* Errors were dealt with when stopping the client, don't spill
914 errors into the event loop handler */
915 return 0;
916 }
917
918 static int client_initialize_io_events(sd_dhcp_client *client,
919 sd_event_io_handler_t io_callback) {
920 int r;
921
922 assert(client);
923 assert(client->event);
924
925 r = sd_event_add_io(client->event, &client->receive_message,
926 client->fd, EPOLLIN, io_callback,
927 client);
928 if (r < 0)
929 goto error;
930
931 r = sd_event_source_set_priority(client->receive_message,
932 client->event_priority);
933 if (r < 0)
934 goto error;
935
936 r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
937 if (r < 0)
938 goto error;
939
940 error:
941 if (r < 0)
942 client_stop(client, r);
943
944 return 0;
945 }
946
947 static int client_initialize_time_events(sd_dhcp_client *client) {
948 int r;
949
950 assert(client);
951 assert(client->event);
952
953 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
954
955 r = sd_event_add_time(client->event,
956 &client->timeout_resend,
957 clock_boottime_or_monotonic(),
958 0, 0,
959 client_timeout_resend, client);
960 if (r < 0)
961 goto error;
962
963 r = sd_event_source_set_priority(client->timeout_resend,
964 client->event_priority);
965 if (r < 0)
966 goto error;
967
968 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
969 if (r < 0)
970 goto error;
971
972 error:
973 if (r < 0)
974 client_stop(client, r);
975
976 return 0;
977
978 }
979
980 static int client_initialize_events(sd_dhcp_client *client,
981 sd_event_io_handler_t io_callback) {
982 client_initialize_io_events(client, io_callback);
983 client_initialize_time_events(client);
984
985 return 0;
986 }
987
988 static int client_start(sd_dhcp_client *client) {
989 int r;
990
991 assert_return(client, -EINVAL);
992 assert_return(client->event, -EINVAL);
993 assert_return(client->index > 0, -EINVAL);
994 assert_return(client->fd < 0, -EBUSY);
995 assert_return(client->xid == 0, -EINVAL);
996 assert_return(client->state == DHCP_STATE_INIT ||
997 client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
998
999 client->xid = random_u32();
1000
1001 r = dhcp_network_bind_raw_socket(client->index, &client->link,
1002 client->xid, client->mac_addr,
1003 client->mac_addr_len, client->arp_type);
1004 if (r < 0) {
1005 client_stop(client, r);
1006 return r;
1007 }
1008 client->fd = r;
1009
1010 if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
1011 client->start_time = now(clock_boottime_or_monotonic());
1012
1013 return client_initialize_events(client, client_receive_message_raw);
1014 }
1015
1016 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
1017 void *userdata) {
1018 sd_dhcp_client *client = userdata;
1019 DHCP_CLIENT_DONT_DESTROY(client);
1020
1021 log_dhcp_client(client, "EXPIRED");
1022
1023 client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
1024
1025 /* lease was lost, start over if not freed or stopped in callback */
1026 if (client->state != DHCP_STATE_STOPPED) {
1027 client_initialize(client);
1028 client_start(client);
1029 }
1030
1031 return 0;
1032 }
1033
1034 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
1035 sd_dhcp_client *client = userdata;
1036 DHCP_CLIENT_DONT_DESTROY(client);
1037 int r;
1038
1039 client->receive_message = sd_event_source_unref(client->receive_message);
1040 client->fd = asynchronous_close(client->fd);
1041
1042 client->state = DHCP_STATE_REBINDING;
1043 client->attempt = 1;
1044
1045 r = dhcp_network_bind_raw_socket(client->index, &client->link,
1046 client->xid, client->mac_addr,
1047 client->mac_addr_len, client->arp_type);
1048 if (r < 0) {
1049 client_stop(client, r);
1050 return 0;
1051 }
1052 client->fd = r;
1053
1054 return client_initialize_events(client, client_receive_message_raw);
1055 }
1056
1057 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
1058 void *userdata) {
1059 sd_dhcp_client *client = userdata;
1060 DHCP_CLIENT_DONT_DESTROY(client);
1061
1062 client->state = DHCP_STATE_RENEWING;
1063 client->attempt = 1;
1064
1065 return client_initialize_time_events(client);
1066 }
1067
1068 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
1069 size_t len) {
1070 _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1071 int r;
1072
1073 r = dhcp_lease_new(&lease);
1074 if (r < 0)
1075 return r;
1076
1077 if (client->client_id_len) {
1078 r = dhcp_lease_set_client_id(lease,
1079 (uint8_t *) &client->client_id,
1080 client->client_id_len);
1081 if (r < 0)
1082 return r;
1083 }
1084
1085 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL);
1086 if (r != DHCP_OFFER) {
1087 log_dhcp_client(client, "received message was not an OFFER, ignoring");
1088 return -ENOMSG;
1089 }
1090
1091 lease->next_server = offer->siaddr;
1092 lease->address = offer->yiaddr;
1093
1094 if (lease->address == 0 ||
1095 lease->server_address == 0 ||
1096 lease->lifetime == 0) {
1097 log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring");
1098 return -ENOMSG;
1099 }
1100
1101 if (!lease->have_subnet_mask) {
1102 r = dhcp_lease_set_default_subnet_mask(lease);
1103 if (r < 0) {
1104 log_dhcp_client(client, "received lease lacks subnet "
1105 "mask, and a fallback one can not be "
1106 "generated, ignoring");
1107 return -ENOMSG;
1108 }
1109 }
1110
1111 sd_dhcp_lease_unref(client->lease);
1112 client->lease = lease;
1113 lease = NULL;
1114
1115 log_dhcp_client(client, "OFFER");
1116
1117 return 0;
1118 }
1119
1120 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
1121 size_t len) {
1122 int r;
1123
1124 r = dhcp_option_parse(force, len, NULL, NULL, NULL);
1125 if (r != DHCP_FORCERENEW)
1126 return -ENOMSG;
1127
1128 log_dhcp_client(client, "FORCERENEW");
1129
1130 return 0;
1131 }
1132
1133 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
1134 size_t len) {
1135 _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1136 _cleanup_free_ char *error_message = NULL;
1137 int r;
1138
1139 r = dhcp_lease_new(&lease);
1140 if (r < 0)
1141 return r;
1142
1143 if (client->client_id_len) {
1144 r = dhcp_lease_set_client_id(lease,
1145 (uint8_t *) &client->client_id,
1146 client->client_id_len);
1147 if (r < 0)
1148 return r;
1149 }
1150
1151 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message);
1152 if (r == DHCP_NAK) {
1153 log_dhcp_client(client, "NAK: %s", strna(error_message));
1154 return -EADDRNOTAVAIL;
1155 }
1156
1157 if (r != DHCP_ACK) {
1158 log_dhcp_client(client, "received message was not an ACK, ignoring");
1159 return -ENOMSG;
1160 }
1161
1162 lease->next_server = ack->siaddr;
1163
1164 lease->address = ack->yiaddr;
1165
1166 if (lease->address == INADDR_ANY ||
1167 lease->server_address == INADDR_ANY ||
1168 lease->lifetime == 0) {
1169 log_dhcp_client(client, "received lease lacks address, server "
1170 "address or lease lifetime, ignoring");
1171 return -ENOMSG;
1172 }
1173
1174 if (lease->subnet_mask == INADDR_ANY) {
1175 r = dhcp_lease_set_default_subnet_mask(lease);
1176 if (r < 0) {
1177 log_dhcp_client(client, "received lease lacks subnet "
1178 "mask, and a fallback one can not be "
1179 "generated, ignoring");
1180 return -ENOMSG;
1181 }
1182 }
1183
1184 r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1185 if (client->lease) {
1186 if (client->lease->address != lease->address ||
1187 client->lease->subnet_mask != lease->subnet_mask ||
1188 client->lease->router != lease->router) {
1189 r = SD_DHCP_CLIENT_EVENT_IP_CHANGE;
1190 } else
1191 r = SD_DHCP_CLIENT_EVENT_RENEW;
1192
1193 client->lease = sd_dhcp_lease_unref(client->lease);
1194 }
1195
1196 client->lease = lease;
1197 lease = NULL;
1198
1199 log_dhcp_client(client, "ACK");
1200
1201 return r;
1202 }
1203
1204 static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) {
1205 assert(client);
1206 assert(client->request_sent);
1207 assert(lifetime > 0);
1208
1209 if (lifetime > 3)
1210 lifetime -= 3;
1211 else
1212 lifetime = 0;
1213
1214 return client->request_sent + (lifetime * USEC_PER_SEC * factor) +
1215 + (random_u32() & 0x1fffff);
1216 }
1217
1218 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1219 usec_t time_now;
1220 uint64_t lifetime_timeout;
1221 uint64_t t2_timeout;
1222 uint64_t t1_timeout;
1223 char time_string[FORMAT_TIMESPAN_MAX];
1224 int r;
1225
1226 assert(client);
1227 assert(client->event);
1228 assert(client->lease);
1229 assert(client->lease->lifetime);
1230
1231 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1232 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1233 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1234
1235 /* don't set timers for infinite leases */
1236 if (client->lease->lifetime == 0xffffffff)
1237 return 0;
1238
1239 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1240 if (r < 0)
1241 return r;
1242 assert(client->request_sent <= time_now);
1243
1244 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1245 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1246 if (client->lease->t1 > 0 && client->lease->t2 > 0) {
1247 /* both T1 and T2 are given */
1248 if (client->lease->t1 < client->lease->t2 &&
1249 client->lease->t2 < client->lease->lifetime) {
1250 /* they are both valid */
1251 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1252 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1253 } else {
1254 /* discard both */
1255 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1256 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1257 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1258 client->lease->t1 = client->lease->lifetime / 2;
1259 }
1260 } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) {
1261 /* only T2 is given, and it is valid */
1262 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1263 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1264 client->lease->t1 = client->lease->lifetime / 2;
1265 if (t2_timeout <= t1_timeout) {
1266 /* the computed T1 would be invalid, so discard T2 */
1267 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1268 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1269 }
1270 } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) {
1271 /* only T1 is given, and it is valid */
1272 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1273 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1274 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1275 if (t2_timeout <= t1_timeout) {
1276 /* the computed T2 would be invalid, so discard T1 */
1277 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1278 client->lease->t2 = client->lease->lifetime / 2;
1279 }
1280 } else {
1281 /* fall back to the default timeouts */
1282 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1283 client->lease->t1 = client->lease->lifetime / 2;
1284 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1285 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1286 }
1287
1288 /* arm lifetime timeout */
1289 r = sd_event_add_time(client->event, &client->timeout_expire,
1290 clock_boottime_or_monotonic(),
1291 lifetime_timeout, 10 * USEC_PER_MSEC,
1292 client_timeout_expire, client);
1293 if (r < 0)
1294 return r;
1295
1296 r = sd_event_source_set_priority(client->timeout_expire,
1297 client->event_priority);
1298 if (r < 0)
1299 return r;
1300
1301 r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
1302 if (r < 0)
1303 return r;
1304
1305 log_dhcp_client(client, "lease expires in %s",
1306 format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC));
1307
1308 /* don't arm earlier timeouts if this has already expired */
1309 if (lifetime_timeout <= time_now)
1310 return 0;
1311
1312 /* arm T2 timeout */
1313 r = sd_event_add_time(client->event,
1314 &client->timeout_t2,
1315 clock_boottime_or_monotonic(),
1316 t2_timeout,
1317 10 * USEC_PER_MSEC,
1318 client_timeout_t2, client);
1319 if (r < 0)
1320 return r;
1321
1322 r = sd_event_source_set_priority(client->timeout_t2,
1323 client->event_priority);
1324 if (r < 0)
1325 return r;
1326
1327 r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
1328 if (r < 0)
1329 return r;
1330
1331 log_dhcp_client(client, "T2 expires in %s",
1332 format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC));
1333
1334 /* don't arm earlier timeout if this has already expired */
1335 if (t2_timeout <= time_now)
1336 return 0;
1337
1338 /* arm T1 timeout */
1339 r = sd_event_add_time(client->event,
1340 &client->timeout_t1,
1341 clock_boottime_or_monotonic(),
1342 t1_timeout, 10 * USEC_PER_MSEC,
1343 client_timeout_t1, client);
1344 if (r < 0)
1345 return r;
1346
1347 r = sd_event_source_set_priority(client->timeout_t1,
1348 client->event_priority);
1349 if (r < 0)
1350 return r;
1351
1352 r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
1353 if (r < 0)
1354 return r;
1355
1356 log_dhcp_client(client, "T1 expires in %s",
1357 format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC));
1358
1359 return 0;
1360 }
1361
1362 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1363 int len) {
1364 DHCP_CLIENT_DONT_DESTROY(client);
1365 int r = 0, notify_event = 0;
1366
1367 assert(client);
1368 assert(client->event);
1369 assert(message);
1370
1371 switch (client->state) {
1372 case DHCP_STATE_SELECTING:
1373
1374 r = client_handle_offer(client, message, len);
1375 if (r >= 0) {
1376
1377 client->timeout_resend =
1378 sd_event_source_unref(client->timeout_resend);
1379
1380 client->state = DHCP_STATE_REQUESTING;
1381 client->attempt = 1;
1382
1383 r = sd_event_add_time(client->event,
1384 &client->timeout_resend,
1385 clock_boottime_or_monotonic(),
1386 0, 0,
1387 client_timeout_resend, client);
1388 if (r < 0)
1389 goto error;
1390
1391 r = sd_event_source_set_priority(client->timeout_resend,
1392 client->event_priority);
1393 if (r < 0)
1394 goto error;
1395
1396 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
1397 if (r < 0)
1398 goto error;
1399 } else if (r == -ENOMSG)
1400 /* invalid message, let's ignore it */
1401 return 0;
1402
1403 break;
1404
1405 case DHCP_STATE_REBOOTING:
1406 case DHCP_STATE_REQUESTING:
1407 case DHCP_STATE_RENEWING:
1408 case DHCP_STATE_REBINDING:
1409
1410 r = client_handle_ack(client, message, len);
1411 if (r >= 0) {
1412 client->timeout_resend =
1413 sd_event_source_unref(client->timeout_resend);
1414 client->receive_message =
1415 sd_event_source_unref(client->receive_message);
1416 client->fd = asynchronous_close(client->fd);
1417
1418 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1419 DHCP_STATE_REBOOTING))
1420 notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1421 else if (r != SD_DHCP_CLIENT_EVENT_IP_ACQUIRE)
1422 notify_event = r;
1423
1424 client->state = DHCP_STATE_BOUND;
1425 client->attempt = 1;
1426
1427 client->last_addr = client->lease->address;
1428
1429 r = client_set_lease_timeouts(client);
1430 if (r < 0) {
1431 log_dhcp_client(client, "could not set lease timeouts");
1432 goto error;
1433 }
1434
1435 r = dhcp_network_bind_udp_socket(client->lease->address,
1436 DHCP_PORT_CLIENT);
1437 if (r < 0) {
1438 log_dhcp_client(client, "could not bind UDP socket");
1439 goto error;
1440 }
1441
1442 client->fd = r;
1443
1444 client_initialize_io_events(client, client_receive_message_udp);
1445
1446 if (notify_event) {
1447 client_notify(client, notify_event);
1448 if (client->state == DHCP_STATE_STOPPED)
1449 return 0;
1450 }
1451
1452 } else if (r == -EADDRNOTAVAIL) {
1453 /* got a NAK, let's restart the client */
1454 client->timeout_resend =
1455 sd_event_source_unref(client->timeout_resend);
1456
1457 r = client_initialize(client);
1458 if (r < 0)
1459 goto error;
1460
1461 r = client_start(client);
1462 if (r < 0)
1463 goto error;
1464
1465 log_dhcp_client(client, "REBOOTED");
1466
1467 return 0;
1468 } else if (r == -ENOMSG)
1469 /* invalid message, let's ignore it */
1470 return 0;
1471
1472 break;
1473
1474 case DHCP_STATE_BOUND:
1475 r = client_handle_forcerenew(client, message, len);
1476 if (r >= 0) {
1477 r = client_timeout_t1(NULL, 0, client);
1478 if (r < 0)
1479 goto error;
1480 } else if (r == -ENOMSG)
1481 /* invalid message, let's ignore it */
1482 return 0;
1483
1484 break;
1485
1486 case DHCP_STATE_INIT:
1487 case DHCP_STATE_INIT_REBOOT:
1488
1489 break;
1490
1491 case DHCP_STATE_STOPPED:
1492 r = -EINVAL;
1493 goto error;
1494 }
1495
1496 error:
1497 if (r < 0)
1498 client_stop(client, r);
1499
1500 return r;
1501 }
1502
1503 static int client_receive_message_udp(sd_event_source *s, int fd,
1504 uint32_t revents, void *userdata) {
1505 sd_dhcp_client *client = userdata;
1506 _cleanup_free_ DHCPMessage *message = NULL;
1507 int buflen = 0, len, r;
1508 const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1509 const struct ether_addr *expected_chaddr = NULL;
1510 uint8_t expected_hlen = 0;
1511
1512 assert(s);
1513 assert(client);
1514
1515 r = ioctl(fd, FIONREAD, &buflen);
1516 if (r < 0)
1517 return -errno;
1518 else if (buflen < 0)
1519 /* this can't be right */
1520 return -EIO;
1521
1522 message = malloc0(buflen);
1523 if (!message)
1524 return -ENOMEM;
1525
1526 len = read(fd, message, buflen);
1527 if (len < 0) {
1528 if (errno == EAGAIN || errno == EINTR)
1529 return 0;
1530
1531 log_dhcp_client(client, "Could not receive message from UDP socket: %m");
1532 return -errno;
1533 } else if ((size_t)len < sizeof(DHCPMessage)) {
1534 log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
1535 return 0;
1536 }
1537
1538 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1539 log_dhcp_client(client, "Not a DHCP message: ignoring");
1540 return 0;
1541 }
1542
1543 if (message->op != BOOTREPLY) {
1544 log_dhcp_client(client, "Not a BOOTREPLY message: ignoring");
1545 return 0;
1546 }
1547
1548 if (message->htype != client->arp_type) {
1549 log_dhcp_client(client, "Packet type does not match client type");
1550 return 0;
1551 }
1552
1553 if (client->arp_type == ARPHRD_ETHER) {
1554 expected_hlen = ETH_ALEN;
1555 expected_chaddr = (const struct ether_addr *) &client->mac_addr;
1556 } else {
1557 /* Non-Ethernet links expect zero chaddr */
1558 expected_hlen = 0;
1559 expected_chaddr = &zero_mac;
1560 }
1561
1562 if (message->hlen != expected_hlen) {
1563 log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen);
1564 return 0;
1565 }
1566
1567 if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
1568 log_dhcp_client(client, "Received chaddr does not match expected: ignoring");
1569 return 0;
1570 }
1571
1572 if (client->state != DHCP_STATE_BOUND &&
1573 be32toh(message->xid) != client->xid) {
1574 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1575 so ignore the xid in this case */
1576 log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring",
1577 be32toh(message->xid), client->xid);
1578 return 0;
1579 }
1580
1581 return client_handle_message(client, message, len);
1582 }
1583
1584 static int client_receive_message_raw(sd_event_source *s, int fd,
1585 uint32_t revents, void *userdata) {
1586 sd_dhcp_client *client = userdata;
1587 _cleanup_free_ DHCPPacket *packet = NULL;
1588 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1589 struct iovec iov = {};
1590 struct msghdr msg = {
1591 .msg_iov = &iov,
1592 .msg_iovlen = 1,
1593 .msg_control = cmsgbuf,
1594 .msg_controllen = sizeof(cmsgbuf),
1595 };
1596 struct cmsghdr *cmsg;
1597 bool checksum = true;
1598 int buflen = 0, len, r;
1599
1600 assert(s);
1601 assert(client);
1602
1603 r = ioctl(fd, FIONREAD, &buflen);
1604 if (r < 0)
1605 return -errno;
1606 else if (buflen < 0)
1607 /* this can't be right */
1608 return -EIO;
1609
1610 packet = malloc0(buflen);
1611 if (!packet)
1612 return -ENOMEM;
1613
1614 iov.iov_base = packet;
1615 iov.iov_len = buflen;
1616
1617 len = recvmsg(fd, &msg, 0);
1618 if (len < 0) {
1619 if (errno == EAGAIN || errno == EINTR)
1620 return 0;
1621
1622 log_dhcp_client(client, "Could not receive message from raw socket: %m");
1623
1624 return -errno;
1625 } else if ((size_t)len < sizeof(DHCPPacket))
1626 return 0;
1627
1628 CMSG_FOREACH(cmsg, &msg) {
1629 if (cmsg->cmsg_level == SOL_PACKET &&
1630 cmsg->cmsg_type == PACKET_AUXDATA &&
1631 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1632 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1633
1634 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1635 break;
1636 }
1637 }
1638
1639 r = dhcp_packet_verify_headers(packet, len, checksum);
1640 if (r < 0)
1641 return 0;
1642
1643 len -= DHCP_IP_UDP_SIZE;
1644
1645 return client_handle_message(client, &packet->dhcp, len);
1646 }
1647
1648 int sd_dhcp_client_start(sd_dhcp_client *client) {
1649 int r;
1650
1651 assert_return(client, -EINVAL);
1652
1653 r = client_initialize(client);
1654 if (r < 0)
1655 return r;
1656
1657 if (client->last_addr)
1658 client->state = DHCP_STATE_INIT_REBOOT;
1659
1660 r = client_start(client);
1661 if (r >= 0)
1662 log_dhcp_client(client, "STARTED on ifindex %i", client->index);
1663
1664 return r;
1665 }
1666
1667 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1668 DHCP_CLIENT_DONT_DESTROY(client);
1669
1670 assert_return(client, -EINVAL);
1671
1672 client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
1673 client->state = DHCP_STATE_STOPPED;
1674
1675 return 0;
1676 }
1677
1678 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1679 int priority) {
1680 int r;
1681
1682 assert_return(client, -EINVAL);
1683 assert_return(!client->event, -EBUSY);
1684
1685 if (event)
1686 client->event = sd_event_ref(event);
1687 else {
1688 r = sd_event_default(&client->event);
1689 if (r < 0)
1690 return 0;
1691 }
1692
1693 client->event_priority = priority;
1694
1695 return 0;
1696 }
1697
1698 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1699 assert_return(client, -EINVAL);
1700
1701 client->event = sd_event_unref(client->event);
1702
1703 return 0;
1704 }
1705
1706 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1707 if (!client)
1708 return NULL;
1709
1710 return client->event;
1711 }
1712
1713 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1714
1715 if (!client)
1716 return NULL;
1717
1718 assert(client->n_ref >= 1);
1719 client->n_ref++;
1720
1721 return client;
1722 }
1723
1724 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1725
1726 if (!client)
1727 return NULL;
1728
1729 assert(client->n_ref >= 1);
1730 client->n_ref--;
1731
1732 if (client->n_ref > 0)
1733 return NULL;
1734
1735 log_dhcp_client(client, "FREE");
1736
1737 client_initialize(client);
1738
1739 client->receive_message = sd_event_source_unref(client->receive_message);
1740
1741 sd_dhcp_client_detach_event(client);
1742
1743 sd_dhcp_lease_unref(client->lease);
1744
1745 free(client->req_opts);
1746 free(client->hostname);
1747 free(client->vendor_class_identifier);
1748 free(client);
1749
1750 return NULL;
1751 }
1752
1753 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1754 _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
1755
1756 assert_return(ret, -EINVAL);
1757
1758 client = new0(sd_dhcp_client, 1);
1759 if (!client)
1760 return -ENOMEM;
1761
1762 client->n_ref = 1;
1763 client->state = DHCP_STATE_INIT;
1764 client->index = -1;
1765 client->fd = -1;
1766 client->attempt = 1;
1767 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1768
1769 client->req_opts_size = ELEMENTSOF(default_req_opts);
1770
1771 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1772 if (!client->req_opts)
1773 return -ENOMEM;
1774
1775 *ret = client;
1776 client = NULL;
1777
1778 return 0;
1779 }