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