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