]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-client.c
sd-ipv4acd: fix assertion triggered when an ARP received in STARTED state
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp-client.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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 <sys/ioctl.h>
12 #include <linux/if_infiniband.h>
13
14 #include "sd-dhcp-client.h"
15
16 #include "alloc-util.h"
17 #include "device-util.h"
18 #include "dhcp-client-id-internal.h"
19 #include "dhcp-client-internal.h"
20 #include "dhcp-lease-internal.h"
21 #include "dhcp-network.h"
22 #include "dhcp-option.h"
23 #include "dhcp-packet.h"
24 #include "dns-domain.h"
25 #include "ether-addr-util.h"
26 #include "event-util.h"
27 #include "fd-util.h"
28 #include "hostname-util.h"
29 #include "iovec-util.h"
30 #include "memory-util.h"
31 #include "network-common.h"
32 #include "random-util.h"
33 #include "set.h"
34 #include "sort-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
37 #include "strv.h"
38 #include "time-util.h"
39 #include "utf8.h"
40 #include "web-util.h"
41
42 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
43
44 #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
45 #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
46
47 #define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
48 * transient failure. */
49
50 struct sd_dhcp_client {
51 unsigned n_ref;
52
53 DHCPState state;
54 sd_event *event;
55 int event_priority;
56 sd_event_source *timeout_resend;
57
58 int ifindex;
59 char *ifname;
60
61 sd_device *dev;
62
63 int fd;
64 uint16_t port;
65 uint16_t server_port;
66 union sockaddr_union link;
67 sd_event_source *receive_message;
68 bool request_broadcast;
69 Set *req_opts;
70 bool anonymize;
71 bool rapid_commit;
72 be32_t last_addr;
73 struct hw_addr_data hw_addr;
74 struct hw_addr_data bcast_addr;
75 uint16_t arp_type;
76 sd_dhcp_client_id client_id;
77 char *hostname;
78 char *vendor_class_identifier;
79 char *mudurl;
80 char **user_class;
81 uint32_t mtu;
82 usec_t fallback_lease_lifetime;
83 uint32_t xid;
84 usec_t start_time;
85 usec_t t1_time;
86 usec_t t2_time;
87 usec_t expire_time;
88 uint64_t discover_attempt;
89 uint64_t request_attempt;
90 uint64_t max_discover_attempts;
91 uint64_t max_request_attempts;
92 OrderedHashmap *extra_options;
93 OrderedHashmap *vendor_options;
94 sd_event_source *timeout_t1;
95 sd_event_source *timeout_t2;
96 sd_event_source *timeout_expire;
97 sd_event_source *timeout_ipv6_only_mode;
98 sd_dhcp_client_callback_t callback;
99 void *userdata;
100 sd_dhcp_client_callback_t state_callback;
101 void *state_userdata;
102 sd_dhcp_lease *lease;
103 usec_t start_delay;
104 int ip_service_type;
105 int socket_priority;
106 bool socket_priority_set;
107 bool ipv6_acquired;
108 };
109
110 static const uint8_t default_req_opts[] = {
111 SD_DHCP_OPTION_SUBNET_MASK,
112 SD_DHCP_OPTION_ROUTER,
113 SD_DHCP_OPTION_HOST_NAME,
114 SD_DHCP_OPTION_DOMAIN_NAME,
115 SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
116 };
117
118 /* RFC7844 section 3:
119 MAY contain the Parameter Request List option.
120 RFC7844 section 3.6:
121 The client intending to protect its privacy SHOULD only request a
122 minimal number of options in the PRL and SHOULD also randomly shuffle
123 the ordering of option codes in the PRL. If this random ordering
124 cannot be implemented, the client MAY order the option codes in the
125 PRL by option code number (lowest to highest).
126 */
127 /* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
128 static const uint8_t default_req_opts_anonymize[] = {
129 SD_DHCP_OPTION_SUBNET_MASK, /* 1 */
130 SD_DHCP_OPTION_ROUTER, /* 3 */
131 SD_DHCP_OPTION_DOMAIN_NAME_SERVER, /* 6 */
132 SD_DHCP_OPTION_DOMAIN_NAME, /* 15 */
133 SD_DHCP_OPTION_ROUTER_DISCOVERY, /* 31 */
134 SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */
135 SD_DHCP_OPTION_VENDOR_SPECIFIC, /* 43 */
136 SD_DHCP_OPTION_NETBIOS_NAME_SERVER, /* 44 */
137 SD_DHCP_OPTION_NETBIOS_NODE_TYPE, /* 46 */
138 SD_DHCP_OPTION_NETBIOS_SCOPE, /* 47 */
139 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, /* 121 */
140 SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, /* 249 */
141 SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, /* 252 */
142 };
143
144 static int client_receive_message_raw(
145 sd_event_source *s,
146 int fd,
147 uint32_t revents,
148 void *userdata);
149 static int client_receive_message_udp(
150 sd_event_source *s,
151 int fd,
152 uint32_t revents,
153 void *userdata);
154 static void client_stop(sd_dhcp_client *client, int error);
155 static int client_restart(sd_dhcp_client *client);
156
157 int dhcp_client_set_state_callback(
158 sd_dhcp_client *client,
159 sd_dhcp_client_callback_t cb,
160 void *userdata) {
161
162 assert_return(client, -EINVAL);
163
164 client->state_callback = cb;
165 client->state_userdata = userdata;
166
167 return 0;
168 }
169
170 int sd_dhcp_client_set_callback(
171 sd_dhcp_client *client,
172 sd_dhcp_client_callback_t cb,
173 void *userdata) {
174
175 assert_return(client, -EINVAL);
176
177 client->callback = cb;
178 client->userdata = userdata;
179
180 return 0;
181 }
182
183 int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
184 assert_return(client, -EINVAL);
185 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
186
187 client->request_broadcast = broadcast;
188
189 return 0;
190 }
191
192 int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
193 assert_return(client, -EINVAL);
194 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
195
196 switch (option) {
197
198 case SD_DHCP_OPTION_PAD:
199 case SD_DHCP_OPTION_OVERLOAD:
200 case SD_DHCP_OPTION_MESSAGE_TYPE:
201 case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
202 case SD_DHCP_OPTION_END:
203 return -EINVAL;
204
205 default:
206 break;
207 }
208
209 return set_ensure_put(&client->req_opts, NULL, UINT8_TO_PTR(option));
210 }
211
212 static int client_request_contains(sd_dhcp_client *client, uint8_t option) {
213 assert(client);
214
215 return set_contains(client->req_opts, UINT8_TO_PTR(option));
216 }
217
218 int sd_dhcp_client_set_request_address(
219 sd_dhcp_client *client,
220 const struct in_addr *last_addr) {
221
222 assert_return(client, -EINVAL);
223 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
224
225 if (last_addr)
226 client->last_addr = last_addr->s_addr;
227 else
228 client->last_addr = INADDR_ANY;
229
230 return 0;
231 }
232
233 int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) {
234 assert_return(client, -EINVAL);
235 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
236 assert_return(ifindex > 0, -EINVAL);
237
238 client->ifindex = ifindex;
239 return 0;
240 }
241
242 int sd_dhcp_client_set_ifname(sd_dhcp_client *client, const char *ifname) {
243 assert_return(client, -EINVAL);
244 assert_return(ifname, -EINVAL);
245
246 if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
247 return -EINVAL;
248
249 return free_and_strdup(&client->ifname, ifname);
250 }
251
252 int sd_dhcp_client_get_ifname(sd_dhcp_client *client, const char **ret) {
253 int r;
254
255 assert_return(client, -EINVAL);
256
257 r = get_ifname(client->ifindex, &client->ifname);
258 if (r < 0)
259 return r;
260
261 if (ret)
262 *ret = client->ifname;
263
264 return 0;
265 }
266
267 int sd_dhcp_client_set_mac(
268 sd_dhcp_client *client,
269 const uint8_t *hw_addr,
270 const uint8_t *bcast_addr,
271 size_t addr_len,
272 uint16_t arp_type) {
273
274 assert_return(client, -EINVAL);
275 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
276 assert_return(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND), -EINVAL);
277 assert_return(hw_addr, -EINVAL);
278 assert_return(addr_len == (arp_type == ARPHRD_ETHER ? ETH_ALEN : INFINIBAND_ALEN), -EINVAL);
279
280 client->arp_type = arp_type;
281 hw_addr_set(&client->hw_addr, hw_addr, addr_len);
282 hw_addr_set(&client->bcast_addr, bcast_addr, bcast_addr ? addr_len : 0);
283
284 return 0;
285 }
286
287 int sd_dhcp_client_get_client_id(sd_dhcp_client *client, const sd_dhcp_client_id **ret) {
288 assert_return(client, -EINVAL);
289 assert_return(ret, -EINVAL);
290
291 if (!sd_dhcp_client_id_is_set(&client->client_id))
292 return -ENODATA;
293
294 *ret = &client->client_id;
295 return 0;
296 }
297
298 int sd_dhcp_client_set_client_id(
299 sd_dhcp_client *client,
300 uint8_t type,
301 const uint8_t *data,
302 size_t data_len) {
303
304 assert_return(client, -EINVAL);
305 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
306 assert_return(data, -EINVAL);
307 assert_return(client_id_data_size_is_valid(data_len), -EINVAL);
308
309 /* For hardware types, log debug message about unexpected data length.
310 *
311 * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
312 * the last 8 bytes of the address are stable and suitable to put into
313 * the client-id. The caller is advised to account for that. */
314 if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) ||
315 (type == ARPHRD_INFINIBAND && data_len != 8))
316 log_dhcp_client(client,
317 "Changing client ID to hardware type %u with unexpected address length %zu",
318 type, data_len);
319
320 return sd_dhcp_client_id_set(&client->client_id, type, data, data_len);
321 }
322
323 static int dhcp_client_set_iaid_duid(
324 sd_dhcp_client *client,
325 bool iaid_set,
326 uint32_t iaid,
327 sd_dhcp_duid *duid) {
328
329 int r;
330
331 if (!iaid_set) {
332 r = dhcp_identifier_set_iaid(client->dev, &client->hw_addr,
333 /* legacy_unstable_byteorder = */ true,
334 &iaid);
335 if (r < 0)
336 return r;
337
338 iaid = be32toh(iaid);
339 }
340
341 return sd_dhcp_client_id_set_iaid_duid(&client->client_id, iaid, duid);
342 }
343
344 int sd_dhcp_client_set_iaid_duid_llt(
345 sd_dhcp_client *client,
346 bool iaid_set,
347 uint32_t iaid,
348 usec_t llt_time) {
349
350 sd_dhcp_duid duid;
351 int r;
352
353 assert_return(client, -EINVAL);
354 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
355
356 r = sd_dhcp_duid_set_llt(&duid, client->hw_addr.bytes, client->hw_addr.length, client->arp_type, llt_time);
357 if (r < 0)
358 return r;
359
360 return dhcp_client_set_iaid_duid(client, iaid_set, iaid, &duid);
361 }
362
363 int sd_dhcp_client_set_iaid_duid_ll(
364 sd_dhcp_client *client,
365 bool iaid_set,
366 uint32_t iaid) {
367
368 sd_dhcp_duid duid;
369 int r;
370
371 assert_return(client, -EINVAL);
372 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
373
374 r = sd_dhcp_duid_set_ll(&duid, client->hw_addr.bytes, client->hw_addr.length, client->arp_type);
375 if (r < 0)
376 return r;
377
378 return dhcp_client_set_iaid_duid(client, iaid_set, iaid, &duid);
379 }
380
381 int sd_dhcp_client_set_iaid_duid_en(
382 sd_dhcp_client *client,
383 bool iaid_set,
384 uint32_t iaid) {
385
386 sd_dhcp_duid duid;
387 int r;
388
389 assert_return(client, -EINVAL);
390 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
391
392 r = sd_dhcp_duid_set_en(&duid);
393 if (r < 0)
394 return r;
395
396 return dhcp_client_set_iaid_duid(client, iaid_set, iaid, &duid);
397 }
398
399 int sd_dhcp_client_set_iaid_duid_uuid(
400 sd_dhcp_client *client,
401 bool iaid_set,
402 uint32_t iaid) {
403
404 sd_dhcp_duid duid;
405 int r;
406
407 assert_return(client, -EINVAL);
408 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
409
410 r = sd_dhcp_duid_set_uuid(&duid);
411 if (r < 0)
412 return r;
413
414 return dhcp_client_set_iaid_duid(client, iaid_set, iaid, &duid);
415 }
416
417 int sd_dhcp_client_set_iaid_duid_raw(
418 sd_dhcp_client *client,
419 bool iaid_set,
420 uint32_t iaid,
421 uint16_t duid_type,
422 const uint8_t *duid_data,
423 size_t duid_data_len) {
424
425 sd_dhcp_duid duid;
426 int r;
427
428 assert_return(client, -EINVAL);
429 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
430 assert_return(duid_data || duid_data_len == 0, -EINVAL);
431
432 r = sd_dhcp_duid_set(&duid, duid_type, duid_data, duid_data_len);
433 if (r < 0)
434 return r;
435
436 return dhcp_client_set_iaid_duid(client, iaid_set, iaid, &duid);
437 }
438
439 int sd_dhcp_client_set_rapid_commit(sd_dhcp_client *client, bool rapid_commit) {
440 assert_return(client, -EINVAL);
441
442 client->rapid_commit = !client->anonymize && rapid_commit;
443 return 0;
444 }
445
446 int sd_dhcp_client_set_hostname(
447 sd_dhcp_client *client,
448 const char *hostname) {
449
450 assert_return(client, -EINVAL);
451 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
452
453 /* Make sure hostnames qualify as DNS and as Linux hostnames */
454 if (hostname &&
455 !(hostname_is_valid(hostname, 0) && dns_name_is_valid(hostname) > 0))
456 return -EINVAL;
457
458 return free_and_strdup(&client->hostname, hostname);
459 }
460
461 int sd_dhcp_client_set_vendor_class_identifier(
462 sd_dhcp_client *client,
463 const char *vci) {
464
465 assert_return(client, -EINVAL);
466 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
467
468 return free_and_strdup(&client->vendor_class_identifier, vci);
469 }
470
471 int sd_dhcp_client_set_mud_url(
472 sd_dhcp_client *client,
473 const char *mudurl) {
474
475 assert_return(client, -EINVAL);
476 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
477 assert_return(mudurl, -EINVAL);
478 assert_return(strlen(mudurl) <= 255, -EINVAL);
479 assert_return(http_url_is_valid(mudurl), -EINVAL);
480
481 return free_and_strdup(&client->mudurl, mudurl);
482 }
483
484 int sd_dhcp_client_set_user_class(
485 sd_dhcp_client *client,
486 char * const *user_class) {
487
488 char **s = NULL;
489
490 assert_return(client, -EINVAL);
491 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
492 assert_return(!strv_isempty(user_class), -EINVAL);
493
494 STRV_FOREACH(p, user_class) {
495 size_t n = strlen(*p);
496
497 if (n > 255 || n == 0)
498 return -EINVAL;
499 }
500
501 s = strv_copy(user_class);
502 if (!s)
503 return -ENOMEM;
504
505 return strv_free_and_replace(client->user_class, s);
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 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
514
515 client->port = port;
516
517 return 0;
518 }
519
520 int sd_dhcp_client_set_port(
521 sd_dhcp_client *client,
522 uint16_t port) {
523
524 assert_return(client, -EINVAL);
525 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
526
527 client->server_port = port;
528
529 return 0;
530 }
531
532 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
533 assert_return(client, -EINVAL);
534 assert_return(mtu >= DHCP_MIN_PACKET_SIZE, -ERANGE);
535
536 /* MTU may be changed by the acquired lease. Hence, we cannot require that the client is stopped here.
537 * Please do not add assertion for !sd_dhcp_client_is_running(client) here. */
538
539 client->mtu = mtu;
540
541 return 0;
542 }
543
544 int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
545 assert_return(client, -EINVAL);
546 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
547
548 client->max_discover_attempts = max_attempts;
549
550 return 0;
551 }
552
553 int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v) {
554 int r;
555
556 assert_return(client, -EINVAL);
557 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
558 assert_return(v, -EINVAL);
559
560 r = ordered_hashmap_ensure_put(&client->extra_options, &dhcp_option_hash_ops, UINT_TO_PTR(v->option), v);
561 if (r < 0)
562 return r;
563
564 sd_dhcp_option_ref(v);
565 return 0;
566 }
567
568 int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v) {
569 int r;
570
571 assert_return(client, -EINVAL);
572 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
573 assert_return(v, -EINVAL);
574
575 r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp_option_hash_ops);
576 if (r < 0)
577 return -ENOMEM;
578
579 r = ordered_hashmap_put(client->vendor_options, v, v);
580 if (r < 0)
581 return r;
582
583 sd_dhcp_option_ref(v);
584
585 return 1;
586 }
587
588 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
589 assert_return(client, -EINVAL);
590
591 if (!client->lease)
592 return -EADDRNOTAVAIL;
593
594 if (ret)
595 *ret = client->lease;
596
597 return 0;
598 }
599
600 int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) {
601 assert_return(client, -EINVAL);
602 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
603
604 client->ip_service_type = type;
605
606 return 0;
607 }
608
609 int sd_dhcp_client_set_socket_priority(sd_dhcp_client *client, int socket_priority) {
610 assert_return(client, -EINVAL);
611 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
612
613 client->socket_priority_set = true;
614 client->socket_priority = socket_priority;
615
616 return 0;
617 }
618
619 int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint64_t fallback_lease_lifetime) {
620 assert_return(client, -EINVAL);
621 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
622 assert_return(fallback_lease_lifetime > 0, -EINVAL);
623
624 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
625 client->fallback_lease_lifetime = fallback_lease_lifetime;
626
627 return 0;
628 }
629
630 static void client_set_state(sd_dhcp_client *client, DHCPState state) {
631 assert(client);
632
633 if (client->state == state)
634 return;
635
636 log_dhcp_client(client, "State changed: %s -> %s",
637 dhcp_state_to_string(client->state), dhcp_state_to_string(state));
638
639 client->state = state;
640
641 if (client->state_callback)
642 client->state_callback(client, state, client->state_userdata);
643 }
644
645 int dhcp_client_get_state(sd_dhcp_client *client) {
646 assert_return(client, -EINVAL);
647
648 return client->state;
649 }
650
651 static int client_notify(sd_dhcp_client *client, int event) {
652 assert(client);
653
654 if (client->callback)
655 return client->callback(client, event, client->userdata);
656
657 return 0;
658 }
659
660 static int client_initialize(sd_dhcp_client *client) {
661 assert_return(client, -EINVAL);
662
663 client->receive_message = sd_event_source_disable_unref(client->receive_message);
664
665 client->fd = safe_close(client->fd);
666
667 (void) event_source_disable(client->timeout_resend);
668 (void) event_source_disable(client->timeout_t1);
669 (void) event_source_disable(client->timeout_t2);
670 (void) event_source_disable(client->timeout_expire);
671 (void) event_source_disable(client->timeout_ipv6_only_mode);
672
673 client->discover_attempt = 0;
674 client->request_attempt = 0;
675
676 client_set_state(client, DHCP_STATE_STOPPED);
677 client->xid = 0;
678
679 client->lease = sd_dhcp_lease_unref(client->lease);
680
681 return 0;
682 }
683
684 static void client_stop(sd_dhcp_client *client, int error) {
685 assert(client);
686 DHCP_CLIENT_DONT_DESTROY(client);
687
688 if (sd_dhcp_client_is_running(client)) {
689 if (error < 0)
690 log_dhcp_client_errno(client, error, "STOPPED: %m");
691 else if (error == SD_DHCP_CLIENT_EVENT_STOP)
692 log_dhcp_client(client, "STOPPED");
693 else
694 log_dhcp_client(client, "STOPPED: Unknown event");
695
696 client_notify(client, error);
697 } else if (error < 0) {
698 log_dhcp_client_errno(client, error, "FAILED: %m");
699 client_notify(client, error);
700 }
701
702 client_initialize(client);
703 }
704
705 /* RFC2131 section 4.1:
706 * retransmission delays should include -1 to +1 sec of random 'fuzz'. */
707 #define RFC2131_RANDOM_FUZZ \
708 ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
709
710 /* RFC2131 section 4.1:
711 * for retransmission delays, timeout should start at 4s then double
712 * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
713 * This assumes the first call will be using attempt 1. */
714 static usec_t client_compute_request_timeout(usec_t now, uint64_t attempt) {
715 usec_t timeout = (UINT64_C(1) << MIN(attempt + 1, UINT64_C(6))) * USEC_PER_SEC;
716
717 return usec_sub_signed(usec_add(now, timeout), RFC2131_RANDOM_FUZZ);
718 }
719
720 /* RFC2131 section 4.4.5:
721 * T1 defaults to (0.5 * duration_of_lease).
722 * T2 defaults to (0.875 * duration_of_lease). */
723 #define T1_DEFAULT(lifetime) ((lifetime) / 2)
724 #define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
725
726 /* RFC2131 section 4.4.5:
727 * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
728 * and one-half of the remaining lease time (in REBINDING state), down to a minimum
729 * of 60 seconds.
730 * Note that while the default T1/T2 initial times do have random 'fuzz' applied,
731 * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
732 static usec_t client_compute_reacquisition_timeout(usec_t now, usec_t expire) {
733 return now + MAX(usec_sub_unsigned(expire, now) / 2, 60 * USEC_PER_SEC);
734 }
735
736 static int cmp_uint8(const uint8_t *a, const uint8_t *b) {
737 return CMP(*a, *b);
738 }
739
740 static int client_message_init(
741 sd_dhcp_client *client,
742 DHCPPacket **ret,
743 uint8_t type,
744 size_t *_optlen,
745 size_t *_optoffset) {
746
747 _cleanup_free_ DHCPPacket *packet = NULL;
748 size_t optlen, optoffset, size;
749 usec_t time_now;
750 uint16_t secs;
751 int r;
752
753 assert(client);
754 assert(client->start_time);
755 assert(ret);
756 assert(_optlen);
757 assert(_optoffset);
758 assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE, DHCP_DECLINE));
759
760 optlen = DHCP_MIN_OPTIONS_SIZE;
761 size = sizeof(DHCPPacket) + optlen;
762
763 packet = malloc0(size);
764 if (!packet)
765 return -ENOMEM;
766
767 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
768 client->arp_type, client->hw_addr.length, client->hw_addr.bytes,
769 optlen, &optoffset);
770 if (r < 0)
771 return r;
772
773 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
774 refuse to issue an DHCP lease if 'secs' is set to zero */
775 r = sd_event_now(client->event, CLOCK_BOOTTIME, &time_now);
776 if (r < 0)
777 return r;
778 assert(time_now >= client->start_time);
779
780 /* seconds between sending first and last DISCOVER
781 * must always be strictly positive to deal with broken servers */
782 secs = ((time_now - client->start_time) / USEC_PER_SEC) ?: 1;
783 packet->dhcp.secs = htobe16(secs);
784
785 /* RFC2131 section 4.1
786 A client that cannot receive unicast IP datagrams until its protocol
787 software has been configured with an IP address SHOULD set the
788 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
789 DHCPREQUEST messages that client sends. The BROADCAST bit will
790 provide a hint to the DHCP server and BOOTP relay agent to broadcast
791 any messages to the client on the client's subnet.
792
793 Note: some interfaces needs this to be enabled, but some networks
794 needs this to be disabled as broadcasts are filteretd, so this
795 needs to be configurable */
796 if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
797 packet->dhcp.flags = htobe16(0x8000);
798
799 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
800 Identifier option is not set */
801 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
802 SD_DHCP_OPTION_CLIENT_IDENTIFIER,
803 client->client_id.size,
804 client->client_id.raw);
805 if (r < 0)
806 return r;
807
808 /* RFC2131 section 3.5:
809 in its initial DHCPDISCOVER or DHCPREQUEST message, a
810 client may provide the server with a list of specific
811 parameters the client is interested in. If the client
812 includes a list of parameters in a DHCPDISCOVER message,
813 it MUST include that list in any subsequent DHCPREQUEST
814 messages.
815 */
816
817 /* RFC7844 section 3:
818 MAY contain the Parameter Request List option. */
819 /* NOTE: in case that there would be an option to do not send
820 * any PRL at all, the size should be checked before sending */
821 if (!set_isempty(client->req_opts) && type != DHCP_RELEASE) {
822 _cleanup_free_ uint8_t *opts = NULL;
823 size_t n_opts, i = 0;
824 void *val;
825
826 n_opts = set_size(client->req_opts);
827 opts = new(uint8_t, n_opts);
828 if (!opts)
829 return -ENOMEM;
830
831 SET_FOREACH(val, client->req_opts)
832 opts[i++] = PTR_TO_UINT8(val);
833 assert(i == n_opts);
834
835 /* For anonymizing the request, let's sort the options. */
836 typesafe_qsort(opts, n_opts, cmp_uint8);
837
838 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
839 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
840 n_opts, opts);
841 if (r < 0)
842 return r;
843 }
844
845 /* RFC2131 section 3.5:
846 The client SHOULD include the ’maximum DHCP message size’ option to
847 let the server know how large the server may make its DHCP messages.
848
849 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
850 than the defined default size unless the Maximum Message Size option
851 is explicitly set
852
853 RFC3442 "Requirements to Avoid Sizing Constraints":
854 Because a full routing table can be quite large, the standard 576
855 octet maximum size for a DHCP message may be too short to contain
856 some legitimate Classless Static Route options. Because of this,
857 clients implementing the Classless Static Route option SHOULD send a
858 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
859 stack is capable of receiving larger IP datagrams. In this case, the
860 client SHOULD set the value of this option to at least the MTU of the
861 interface that the client is configuring. The client MAY set the
862 value of this option higher, up to the size of the largest UDP packet
863 it is prepared to accept. (Note that the value specified in the
864 Maximum DHCP Message Size option is the total maximum packet size,
865 including IP and UDP headers.)
866 */
867 /* RFC7844 section 3:
868 SHOULD NOT contain any other option. */
869 if (!client->anonymize && IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST)) {
870 be16_t max_size = htobe16(MIN(client->mtu - DHCP_IP_UDP_SIZE, (uint32_t) UINT16_MAX));
871 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
872 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
873 2, &max_size);
874 if (r < 0)
875 return r;
876 }
877
878 *_optlen = optlen;
879 *_optoffset = optoffset;
880 *ret = TAKE_PTR(packet);
881
882 return 0;
883 }
884
885 static int client_append_fqdn_option(
886 DHCPMessage *message,
887 size_t optlen,
888 size_t *optoffset,
889 const char *fqdn) {
890
891 uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
892 int r;
893
894 buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */
895 DHCP_FQDN_FLAG_E; /* Canonical wire format */
896 buffer[1] = 0; /* RCODE1 (deprecated) */
897 buffer[2] = 0; /* RCODE2 (deprecated) */
898
899 r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false);
900 if (r > 0)
901 r = dhcp_option_append(message, optlen, optoffset, 0,
902 SD_DHCP_OPTION_FQDN, 3 + r, buffer);
903
904 return r;
905 }
906
907 static int dhcp_client_send_raw(
908 sd_dhcp_client *client,
909 DHCPPacket *packet,
910 size_t len) {
911
912 dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port,
913 INADDR_BROADCAST, client->server_port, len, client->ip_service_type);
914
915 return dhcp_network_send_raw_socket(client->fd, &client->link,
916 packet, len);
917 }
918
919 static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) {
920 sd_dhcp_option *j;
921 int r;
922
923 assert(client);
924
925 if (client->hostname) {
926 /* According to RFC 4702 "clients that send the Client FQDN option in
927 their messages MUST NOT also send the Host Name option". Just send
928 one of the two depending on the hostname type.
929 */
930 if (dns_name_is_single_label(client->hostname)) {
931 /* it is unclear from RFC 2131 if client should send hostname in
932 DHCPDISCOVER but dhclient does and so we do as well
933 */
934 r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
935 SD_DHCP_OPTION_HOST_NAME,
936 strlen(client->hostname), client->hostname);
937 } else
938 r = client_append_fqdn_option(&packet->dhcp, optlen, optoffset,
939 client->hostname);
940 if (r < 0)
941 return r;
942 }
943
944 if (client->vendor_class_identifier) {
945 r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
946 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
947 strlen(client->vendor_class_identifier),
948 client->vendor_class_identifier);
949 if (r < 0)
950 return r;
951 }
952
953 if (client->mudurl) {
954 r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
955 SD_DHCP_OPTION_MUD_URL,
956 strlen(client->mudurl),
957 client->mudurl);
958 if (r < 0)
959 return r;
960 }
961
962 if (client->user_class) {
963 r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
964 SD_DHCP_OPTION_USER_CLASS,
965 strv_length(client->user_class),
966 client->user_class);
967 if (r < 0)
968 return r;
969 }
970
971 ORDERED_HASHMAP_FOREACH(j, client->extra_options) {
972 r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
973 j->option, j->length, j->data);
974 if (r < 0)
975 return r;
976 }
977
978 if (!ordered_hashmap_isempty(client->vendor_options)) {
979 r = dhcp_option_append(
980 &packet->dhcp, optlen, optoffset, 0,
981 SD_DHCP_OPTION_VENDOR_SPECIFIC,
982 ordered_hashmap_size(client->vendor_options), client->vendor_options);
983 if (r < 0)
984 return r;
985 }
986
987
988 return 0;
989 }
990
991 static int client_send_discover(sd_dhcp_client *client) {
992 _cleanup_free_ DHCPPacket *discover = NULL;
993 size_t optoffset, optlen;
994 int r;
995
996 assert(client);
997 assert(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_SELECTING));
998
999 r = client_message_init(client, &discover, DHCP_DISCOVER,
1000 &optlen, &optoffset);
1001 if (r < 0)
1002 return r;
1003
1004 /* the client may suggest values for the network address
1005 and lease time in the DHCPDISCOVER message. The client may include
1006 the ’requested IP address’ option to suggest that a particular IP
1007 address be assigned, and may include the ’IP address lease time’
1008 option to suggest the lease time it would like.
1009 */
1010 /* RFC7844 section 3:
1011 SHOULD NOT contain any other option. */
1012 if (!client->anonymize && client->last_addr != INADDR_ANY) {
1013 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
1014 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
1015 4, &client->last_addr);
1016 if (r < 0)
1017 return r;
1018 }
1019
1020 if (client->rapid_commit) {
1021 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
1022 SD_DHCP_OPTION_RAPID_COMMIT, 0, NULL);
1023 if (r < 0)
1024 return r;
1025 }
1026
1027 r = client_append_common_discover_request_options(client, discover, &optoffset, optlen);
1028 if (r < 0)
1029 return r;
1030
1031 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
1032 SD_DHCP_OPTION_END, 0, NULL);
1033 if (r < 0)
1034 return r;
1035
1036 /* We currently ignore:
1037 The client SHOULD wait a random time between one and ten seconds to
1038 desynchronize the use of DHCP at startup.
1039 */
1040 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
1041 if (r < 0)
1042 return r;
1043
1044 log_dhcp_client(client, "DISCOVER");
1045
1046 return 0;
1047 }
1048
1049 static int client_send_request(sd_dhcp_client *client) {
1050 _cleanup_free_ DHCPPacket *request = NULL;
1051 size_t optoffset, optlen;
1052 int r;
1053
1054 assert(client);
1055
1056 r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset);
1057 if (r < 0)
1058 return r;
1059
1060 switch (client->state) {
1061 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
1062 SELECTING should be REQUESTING)
1063 */
1064
1065 case DHCP_STATE_REQUESTING:
1066 /* Client inserts the address of the selected server in ’server
1067 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
1068 filled in with the yiaddr value from the chosen DHCPOFFER.
1069 */
1070
1071 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
1072 SD_DHCP_OPTION_SERVER_IDENTIFIER,
1073 4, &client->lease->server_address);
1074 if (r < 0)
1075 return r;
1076
1077 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
1078 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
1079 4, &client->lease->address);
1080 if (r < 0)
1081 return r;
1082
1083 break;
1084
1085 case DHCP_STATE_INIT_REBOOT:
1086 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1087 option MUST be filled in with client’s notion of its previously
1088 assigned address. ’ciaddr’ MUST be zero.
1089 */
1090 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
1091 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
1092 4, &client->last_addr);
1093 if (r < 0)
1094 return r;
1095 break;
1096
1097 case DHCP_STATE_RENEWING:
1098 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1099 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1100 client’s IP address.
1101 */
1102
1103 case DHCP_STATE_REBINDING:
1104 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
1105 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
1106 client’s IP address.
1107
1108 This message MUST be broadcast to the 0xffffffff IP broadcast address.
1109 */
1110 request->dhcp.ciaddr = client->lease->address;
1111
1112 break;
1113
1114 case DHCP_STATE_INIT:
1115 case DHCP_STATE_SELECTING:
1116 case DHCP_STATE_REBOOTING:
1117 case DHCP_STATE_BOUND:
1118 case DHCP_STATE_STOPPED:
1119 default:
1120 return -EINVAL;
1121 }
1122
1123 r = client_append_common_discover_request_options(client, request, &optoffset, optlen);
1124 if (r < 0)
1125 return r;
1126
1127 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
1128 SD_DHCP_OPTION_END, 0, NULL);
1129 if (r < 0)
1130 return r;
1131
1132 if (client->state == DHCP_STATE_RENEWING)
1133 r = dhcp_network_send_udp_socket(client->fd,
1134 client->lease->server_address,
1135 client->server_port,
1136 &request->dhcp,
1137 sizeof(DHCPMessage) + optoffset);
1138 else
1139 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
1140 if (r < 0)
1141 return r;
1142
1143 switch (client->state) {
1144
1145 case DHCP_STATE_REQUESTING:
1146 log_dhcp_client(client, "REQUEST (requesting)");
1147 break;
1148
1149 case DHCP_STATE_INIT_REBOOT:
1150 log_dhcp_client(client, "REQUEST (init-reboot)");
1151 break;
1152
1153 case DHCP_STATE_RENEWING:
1154 log_dhcp_client(client, "REQUEST (renewing)");
1155 break;
1156
1157 case DHCP_STATE_REBINDING:
1158 log_dhcp_client(client, "REQUEST (rebinding)");
1159 break;
1160
1161 default:
1162 log_dhcp_client(client, "REQUEST (invalid)");
1163 break;
1164 }
1165
1166 return 0;
1167 }
1168
1169 static int client_start(sd_dhcp_client *client);
1170
1171 static int client_timeout_resend(
1172 sd_event_source *s,
1173 uint64_t usec,
1174 void *userdata) {
1175
1176 sd_dhcp_client *client = ASSERT_PTR(userdata);
1177 DHCP_CLIENT_DONT_DESTROY(client);
1178 usec_t time_now, next_timeout;
1179 int r;
1180
1181 assert(s);
1182 assert(client->event);
1183
1184 r = sd_event_now(client->event, CLOCK_BOOTTIME, &time_now);
1185 if (r < 0)
1186 goto error;
1187
1188 switch (client->state) {
1189
1190 case DHCP_STATE_RENEWING:
1191 next_timeout = client_compute_reacquisition_timeout(time_now, client->t2_time);
1192 break;
1193
1194 case DHCP_STATE_REBINDING:
1195 next_timeout = client_compute_reacquisition_timeout(time_now, client->expire_time);
1196 break;
1197
1198 case DHCP_STATE_REBOOTING:
1199 /* start over as we did not receive a timely ack or nak */
1200 r = client_initialize(client);
1201 if (r < 0)
1202 goto error;
1203
1204 r = client_start(client);
1205 if (r < 0)
1206 goto error;
1207
1208 log_dhcp_client(client, "REBOOTED");
1209 return 0;
1210
1211 case DHCP_STATE_INIT:
1212 case DHCP_STATE_INIT_REBOOT:
1213 case DHCP_STATE_SELECTING:
1214 if (client->discover_attempt >= client->max_discover_attempts)
1215 goto error;
1216
1217 client->discover_attempt++;
1218 next_timeout = client_compute_request_timeout(time_now, client->discover_attempt);
1219 break;
1220 case DHCP_STATE_REQUESTING:
1221 case DHCP_STATE_BOUND:
1222 if (client->request_attempt >= client->max_request_attempts)
1223 goto error;
1224
1225 client->request_attempt++;
1226 next_timeout = client_compute_request_timeout(time_now, client->request_attempt);
1227 break;
1228
1229 case DHCP_STATE_STOPPED:
1230 r = -EINVAL;
1231 goto error;
1232
1233 default:
1234 assert_not_reached();
1235 }
1236
1237 r = event_reset_time(client->event, &client->timeout_resend,
1238 CLOCK_BOOTTIME,
1239 next_timeout, 10 * USEC_PER_MSEC,
1240 client_timeout_resend, client,
1241 client->event_priority, "dhcp4-resend-timer", true);
1242 if (r < 0)
1243 goto error;
1244
1245 switch (client->state) {
1246 case DHCP_STATE_INIT:
1247 r = client_send_discover(client);
1248 if (r >= 0) {
1249 client_set_state(client, DHCP_STATE_SELECTING);
1250 client->discover_attempt = 0;
1251 } else if (client->discover_attempt >= client->max_discover_attempts)
1252 goto error;
1253 break;
1254
1255 case DHCP_STATE_SELECTING:
1256 r = client_send_discover(client);
1257 if (r < 0 && client->discover_attempt >= client->max_discover_attempts)
1258 goto error;
1259 break;
1260
1261 case DHCP_STATE_INIT_REBOOT:
1262 case DHCP_STATE_REQUESTING:
1263 case DHCP_STATE_RENEWING:
1264 case DHCP_STATE_REBINDING:
1265 r = client_send_request(client);
1266 if (r < 0 && client->request_attempt >= client->max_request_attempts)
1267 goto error;
1268
1269 if (client->state == DHCP_STATE_INIT_REBOOT)
1270 client_set_state(client, DHCP_STATE_REBOOTING);
1271 break;
1272
1273 case DHCP_STATE_REBOOTING:
1274 case DHCP_STATE_BOUND:
1275 break;
1276
1277 case DHCP_STATE_STOPPED:
1278 default:
1279 r = -EINVAL;
1280 goto error;
1281 }
1282
1283 if (client->discover_attempt >= TRANSIENT_FAILURE_ATTEMPTS)
1284 client_notify(client, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE);
1285
1286 return 0;
1287
1288 error:
1289 /* Avoid REQUEST infinite loop. Per RFC 2131 section 3.1.5: if the client receives
1290 neither a DHCPACK or a DHCPNAK message after employing the retransmission algorithm,
1291 the client reverts to INIT state and restarts the initialization process */
1292 if (client->request_attempt >= client->max_request_attempts) {
1293 log_dhcp_client(client, "Max REQUEST attempts reached. Restarting...");
1294 client_restart(client);
1295 return 0;
1296 }
1297 client_stop(client, r);
1298
1299 /* Errors were dealt with when stopping the client, don't spill
1300 errors into the event loop handler */
1301 return 0;
1302 }
1303
1304 static int client_initialize_io_events(
1305 sd_dhcp_client *client,
1306 sd_event_io_handler_t io_callback) {
1307
1308 int r;
1309
1310 assert(client);
1311 assert(client->event);
1312
1313 r = sd_event_add_io(client->event, &client->receive_message,
1314 client->fd, EPOLLIN, io_callback,
1315 client);
1316 if (r < 0)
1317 goto error;
1318
1319 r = sd_event_source_set_priority(client->receive_message,
1320 client->event_priority);
1321 if (r < 0)
1322 goto error;
1323
1324 r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
1325 if (r < 0)
1326 goto error;
1327
1328 error:
1329 if (r < 0)
1330 client_stop(client, r);
1331
1332 return 0;
1333 }
1334
1335 static int client_initialize_time_events(sd_dhcp_client *client) {
1336 usec_t usec = 0;
1337 int r;
1338
1339 assert(client);
1340 assert(client->event);
1341
1342 (void) event_source_disable(client->timeout_ipv6_only_mode);
1343
1344 if (client->start_delay > 0) {
1345 assert_se(sd_event_now(client->event, CLOCK_BOOTTIME, &usec) >= 0);
1346 usec = usec_add(usec, client->start_delay);
1347 }
1348
1349 r = event_reset_time(client->event, &client->timeout_resend,
1350 CLOCK_BOOTTIME,
1351 usec, 0,
1352 client_timeout_resend, client,
1353 client->event_priority, "dhcp4-resend-timer", true);
1354 if (r < 0)
1355 client_stop(client, r);
1356
1357 return 0;
1358
1359 }
1360
1361 static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) {
1362 client_initialize_io_events(client, io_callback);
1363 client_initialize_time_events(client);
1364
1365 return 0;
1366 }
1367
1368 static int client_start_delayed(sd_dhcp_client *client) {
1369 int r;
1370
1371 assert_return(client, -EINVAL);
1372 assert_return(client->event, -EINVAL);
1373 assert_return(client->ifindex > 0, -EINVAL);
1374 assert_return(client->fd < 0, -EBUSY);
1375 assert_return(client->xid == 0, -EINVAL);
1376 assert_return(IN_SET(client->state, DHCP_STATE_STOPPED, DHCP_STATE_INIT_REBOOT), -EBUSY);
1377
1378 client->xid = random_u32();
1379
1380 r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
1381 &client->hw_addr, &client->bcast_addr,
1382 client->arp_type, client->port,
1383 client->socket_priority_set, client->socket_priority);
1384 if (r < 0) {
1385 client_stop(client, r);
1386 return r;
1387 }
1388 client->fd = r;
1389
1390 client->start_time = now(CLOCK_BOOTTIME);
1391
1392 if (client->state == DHCP_STATE_STOPPED)
1393 client->state = DHCP_STATE_INIT;
1394
1395 return client_initialize_events(client, client_receive_message_raw);
1396 }
1397
1398 static int client_start(sd_dhcp_client *client) {
1399 client->start_delay = 0;
1400 return client_start_delayed(client);
1401 }
1402
1403 static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
1404 sd_dhcp_client *client = userdata;
1405 DHCP_CLIENT_DONT_DESTROY(client);
1406
1407 log_dhcp_client(client, "EXPIRED");
1408
1409 client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
1410
1411 /* lease was lost, start over if not freed or stopped in callback */
1412 if (client->state != DHCP_STATE_STOPPED) {
1413 client_initialize(client);
1414 client_start(client);
1415 }
1416
1417 return 0;
1418 }
1419
1420 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
1421 sd_dhcp_client *client = ASSERT_PTR(userdata);
1422 DHCP_CLIENT_DONT_DESTROY(client);
1423 int r;
1424
1425 client->receive_message = sd_event_source_disable_unref(client->receive_message);
1426 client->fd = safe_close(client->fd);
1427
1428 client_set_state(client, DHCP_STATE_REBINDING);
1429 client->discover_attempt = 0;
1430 client->request_attempt = 0;
1431
1432 r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
1433 &client->hw_addr, &client->bcast_addr,
1434 client->arp_type, client->port,
1435 client->socket_priority_set, client->socket_priority);
1436 if (r < 0) {
1437 client_stop(client, r);
1438 return 0;
1439 }
1440 client->fd = r;
1441
1442 return client_initialize_events(client, client_receive_message_raw);
1443 }
1444
1445 static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
1446 sd_dhcp_client *client = userdata;
1447 DHCP_CLIENT_DONT_DESTROY(client);
1448
1449 if (client->lease)
1450 client_set_state(client, DHCP_STATE_RENEWING);
1451 else if (client->state != DHCP_STATE_INIT)
1452 client_set_state(client, DHCP_STATE_INIT_REBOOT);
1453 client->discover_attempt = 0;
1454 client->request_attempt = 0;
1455
1456 return client_initialize_time_events(client);
1457 }
1458
1459 static int client_parse_message(
1460 sd_dhcp_client *client,
1461 DHCPMessage *message,
1462 size_t len,
1463 sd_dhcp_lease **ret) {
1464
1465 _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1466 _cleanup_free_ char *error_message = NULL;
1467 int r;
1468
1469 assert(client);
1470 assert(message);
1471 assert(ret);
1472
1473 r = dhcp_lease_new(&lease);
1474 if (r < 0)
1475 return r;
1476
1477 if (sd_dhcp_client_id_is_set(&client->client_id)) {
1478 r = dhcp_lease_set_client_id(lease, &client->client_id);
1479 if (r < 0)
1480 return r;
1481 }
1482
1483 r = dhcp_option_parse(message, len, dhcp_lease_parse_options, lease, &error_message);
1484 if (r < 0)
1485 return log_dhcp_client_errno(client, r, "Failed to parse DHCP options, ignoring: %m");
1486
1487 switch (client->state) {
1488 case DHCP_STATE_SELECTING:
1489 if (r == DHCP_ACK) {
1490 if (!client->rapid_commit)
1491 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1492 "received unexpected ACK, ignoring.");
1493 if (!lease->rapid_commit)
1494 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1495 "received rapid ACK without Rapid Commit option, ignoring.");
1496 } else if (r == DHCP_OFFER) {
1497 if (lease->rapid_commit) {
1498 /* Some RFC incompliant servers provides an OFFER with a rapid commit option.
1499 * See https://github.com/systemd/systemd/issues/29904.
1500 * Let's support such servers gracefully. */
1501 log_dhcp_client(client, "received OFFER with Rapid Commit option, ignoring.");
1502 lease->rapid_commit = false;
1503 }
1504 if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0)
1505 lease->lifetime = client->fallback_lease_lifetime;
1506 } else
1507 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1508 "received unexpected message, ignoring.");
1509
1510 break;
1511
1512 case DHCP_STATE_REBOOTING:
1513 case DHCP_STATE_REQUESTING:
1514 case DHCP_STATE_RENEWING:
1515 case DHCP_STATE_REBINDING:
1516 if (r == DHCP_NAK) {
1517 if (client->lease && client->lease->server_address != lease->server_address)
1518 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1519 "NAK from unexpected server, ignoring: %s",
1520 strna(error_message));
1521 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
1522 "NAK: %s", strna(error_message));
1523 }
1524 if (r != DHCP_ACK)
1525 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1526 "received message was not an ACK, ignoring.");
1527 break;
1528
1529 default:
1530 assert_not_reached();
1531 }
1532
1533 lease->next_server = message->siaddr;
1534 lease->address = message->yiaddr;
1535
1536 if (lease->address == 0 ||
1537 lease->server_address == 0 ||
1538 lease->lifetime == 0)
1539 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1540 "received lease lacks address, server address or lease lifetime, ignoring.");
1541
1542 r = dhcp_lease_set_default_subnet_mask(lease);
1543 if (r < 0)
1544 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1545 "received lease lacks subnet mask, and a fallback one cannot be generated, ignoring.");
1546
1547 /* RFC 8925 section 3.2
1548 * If the client did not include the IPv6-Only Preferred option code in the Parameter Request List in
1549 * the DHCPDISCOVER or DHCPREQUEST message, it MUST ignore the IPv6-Only Preferred option in any
1550 * messages received from the server. */
1551 if (lease->ipv6_only_preferred_usec > 0 &&
1552 !client_request_contains(client, SD_DHCP_OPTION_IPV6_ONLY_PREFERRED)) {
1553 log_dhcp_client(client, "Received message with unrequested IPv6-only preferred option, ignoring the option.");
1554 lease->ipv6_only_preferred_usec = 0;
1555 }
1556
1557 *ret = TAKE_PTR(lease);
1558 return 0;
1559 }
1560
1561 static int client_handle_offer_or_rapid_ack(sd_dhcp_client *client, DHCPMessage *message, size_t len, const triple_timestamp *timestamp) {
1562 _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1563 int r;
1564
1565 assert(client);
1566 assert(message);
1567
1568 r = client_parse_message(client, message, len, &lease);
1569 if (r < 0)
1570 return r;
1571
1572 dhcp_lease_set_timestamp(lease, timestamp);
1573
1574 dhcp_lease_unref_and_replace(client->lease, lease);
1575
1576 if (client->lease->rapid_commit) {
1577 log_dhcp_client(client, "ACK");
1578 return SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1579 }
1580
1581 if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
1582 return -ENOMSG;
1583
1584 log_dhcp_client(client, "OFFER");
1585 return 0;
1586 }
1587
1588 static int client_enter_requesting_now(sd_dhcp_client *client) {
1589 assert(client);
1590
1591 client_set_state(client, DHCP_STATE_REQUESTING);
1592 client->discover_attempt = 0;
1593 client->request_attempt = 0;
1594
1595 return event_reset_time(client->event, &client->timeout_resend,
1596 CLOCK_BOOTTIME, 0, 0,
1597 client_timeout_resend, client,
1598 client->event_priority, "dhcp4-resend-timer",
1599 /* force_reset = */ true);
1600 }
1601
1602 static int client_enter_requesting_delayed(sd_event_source *s, uint64_t usec, void *userdata) {
1603 sd_dhcp_client *client = ASSERT_PTR(userdata);
1604 DHCP_CLIENT_DONT_DESTROY(client);
1605 int r;
1606
1607 r = client_enter_requesting_now(client);
1608 if (r < 0)
1609 client_stop(client, r);
1610
1611 return 0;
1612 }
1613
1614 static int client_enter_requesting(sd_dhcp_client *client) {
1615 assert(client);
1616 assert(client->lease);
1617
1618 (void) event_source_disable(client->timeout_resend);
1619
1620 if (client->lease->ipv6_only_preferred_usec > 0) {
1621 if (client->ipv6_acquired) {
1622 log_dhcp_client(client,
1623 "Received an OFFER with IPv6-only preferred option, and the host already acquired IPv6 connectivity, stopping DHCPv4 client.");
1624 return sd_dhcp_client_stop(client);
1625 }
1626
1627 log_dhcp_client(client,
1628 "Received an OFFER with IPv6-only preferred option, delaying to send REQUEST with %s.",
1629 FORMAT_TIMESPAN(client->lease->ipv6_only_preferred_usec, USEC_PER_SEC));
1630
1631 return event_reset_time_relative(client->event, &client->timeout_ipv6_only_mode,
1632 CLOCK_BOOTTIME,
1633 client->lease->ipv6_only_preferred_usec, 0,
1634 client_enter_requesting_delayed, client,
1635 client->event_priority, "dhcp4-ipv6-only-mode-timer",
1636 /* force_reset = */ true);
1637 }
1638
1639 return client_enter_requesting_now(client);
1640 }
1641
1642 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) {
1643 int r;
1644
1645 r = dhcp_option_parse(force, len, NULL, NULL, NULL);
1646 if (r != DHCP_FORCERENEW)
1647 return -ENOMSG;
1648
1649 #if 0
1650 log_dhcp_client(client, "FORCERENEW");
1651 return 0;
1652 #else
1653 /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP
1654 * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW
1655 * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */
1656 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
1657 "Received FORCERENEW, ignoring.");
1658 #endif
1659 }
1660
1661 static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) {
1662 if (a->address != b->address)
1663 return false;
1664
1665 if (a->subnet_mask != b->subnet_mask)
1666 return false;
1667
1668 if (a->router_size != b->router_size)
1669 return false;
1670
1671 for (size_t i = 0; i < a->router_size; i++)
1672 if (a->router[i].s_addr != b->router[i].s_addr)
1673 return false;
1674
1675 return true;
1676 }
1677
1678 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *message, size_t len, const triple_timestamp *timestamp) {
1679 _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1680 int r;
1681
1682 assert(client);
1683 assert(message);
1684
1685 r = client_parse_message(client, message, len, &lease);
1686 if (r < 0)
1687 return r;
1688
1689 dhcp_lease_set_timestamp(lease, timestamp);
1690
1691 if (!client->lease)
1692 r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1693 else if (lease_equal(client->lease, lease))
1694 r = SD_DHCP_CLIENT_EVENT_RENEW;
1695 else
1696 r = SD_DHCP_CLIENT_EVENT_IP_CHANGE;
1697
1698 dhcp_lease_unref_and_replace(client->lease, lease);
1699
1700 log_dhcp_client(client, "ACK");
1701 return r;
1702 }
1703
1704 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1705 usec_t time_now;
1706 int r;
1707
1708 assert(client);
1709 assert(client->event);
1710 assert(client->lease);
1711 assert(client->lease->lifetime > 0);
1712 assert(triple_timestamp_is_set(&client->lease->timestamp));
1713
1714 /* don't set timers for infinite leases */
1715 if (client->lease->lifetime == USEC_INFINITY) {
1716 (void) event_source_disable(client->timeout_t1);
1717 (void) event_source_disable(client->timeout_t2);
1718 (void) event_source_disable(client->timeout_expire);
1719
1720 return 0;
1721 }
1722
1723 r = sd_event_now(client->event, CLOCK_BOOTTIME, &time_now);
1724 if (r < 0)
1725 return r;
1726
1727 /* verify that 0 < t2 < lifetime */
1728 if (client->lease->t2 == 0 || client->lease->t2 >= client->lease->lifetime)
1729 client->lease->t2 = T2_DEFAULT(client->lease->lifetime);
1730 /* verify that 0 < t1 < lifetime */
1731 if (client->lease->t1 == 0 || client->lease->t1 >= client->lease->t2)
1732 client->lease->t1 = T1_DEFAULT(client->lease->lifetime);
1733 /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
1734 * could not evaluate to false if t1 >= t2; so setting t2 to T2_DEFAULT
1735 * guarantees t1 < t2. */
1736 if (client->lease->t1 >= client->lease->t2)
1737 client->lease->t2 = T2_DEFAULT(client->lease->lifetime);
1738
1739 assert(client->lease->t1 > 0);
1740 assert(client->lease->t1 < client->lease->t2);
1741 assert(client->lease->t2 < client->lease->lifetime);
1742
1743 r = sd_dhcp_lease_get_lifetime_timestamp(client->lease, CLOCK_BOOTTIME, &client->expire_time);
1744 if (r < 0)
1745 return r;
1746 r = sd_dhcp_lease_get_t1_timestamp(client->lease, CLOCK_BOOTTIME, &client->t1_time);
1747 if (r < 0)
1748 return r;
1749 r = sd_dhcp_lease_get_t2_timestamp(client->lease, CLOCK_BOOTTIME, &client->t2_time);
1750 if (r < 0)
1751 return r;
1752
1753 /* RFC2131 section 4.4.5:
1754 * Times T1 and T2 SHOULD be chosen with some random "fuzz".
1755 * Since the RFC doesn't specify here the exact 'fuzz' to use,
1756 * we use the range from section 4.1: -1 to +1 sec. */
1757 client->t1_time = usec_sub_signed(client->t1_time, RFC2131_RANDOM_FUZZ);
1758 client->t2_time = usec_sub_signed(client->t2_time, RFC2131_RANDOM_FUZZ);
1759
1760 /* after fuzzing, ensure t2 is still >= t1 */
1761 client->t2_time = MAX(client->t1_time, client->t2_time);
1762
1763 /* arm lifetime timeout */
1764 r = event_reset_time(client->event, &client->timeout_expire,
1765 CLOCK_BOOTTIME,
1766 client->expire_time, 10 * USEC_PER_MSEC,
1767 client_timeout_expire, client,
1768 client->event_priority, "dhcp4-lifetime", true);
1769 if (r < 0)
1770 return r;
1771
1772 /* don't arm earlier timeouts if this has already expired */
1773 if (client->expire_time <= time_now)
1774 return 0;
1775
1776 log_dhcp_client(client, "lease expires in %s",
1777 FORMAT_TIMESPAN(client->expire_time - time_now, USEC_PER_SEC));
1778
1779 /* arm T2 timeout */
1780 r = event_reset_time(client->event, &client->timeout_t2,
1781 CLOCK_BOOTTIME,
1782 client->t2_time, 10 * USEC_PER_MSEC,
1783 client_timeout_t2, client,
1784 client->event_priority, "dhcp4-t2-timeout", true);
1785 if (r < 0)
1786 return r;
1787
1788 /* don't arm earlier timeout if this has already expired */
1789 if (client->t2_time <= time_now)
1790 return 0;
1791
1792 log_dhcp_client(client, "T2 expires in %s",
1793 FORMAT_TIMESPAN(client->t2_time - time_now, USEC_PER_SEC));
1794
1795 /* arm T1 timeout */
1796 r = event_reset_time(client->event, &client->timeout_t1,
1797 CLOCK_BOOTTIME,
1798 client->t1_time, 10 * USEC_PER_MSEC,
1799 client_timeout_t1, client,
1800 client->event_priority, "dhcp4-t1-timer", true);
1801 if (r < 0)
1802 return r;
1803
1804 if (client->t1_time > time_now)
1805 log_dhcp_client(client, "T1 expires in %s",
1806 FORMAT_TIMESPAN(client->t1_time - time_now, USEC_PER_SEC));
1807
1808 return 0;
1809 }
1810
1811 static int client_enter_bound_now(sd_dhcp_client *client, int notify_event) {
1812 int r;
1813
1814 assert(client);
1815
1816 if (IN_SET(client->state, DHCP_STATE_REQUESTING, DHCP_STATE_REBOOTING))
1817 notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1818
1819 client_set_state(client, DHCP_STATE_BOUND);
1820 client->discover_attempt = 0;
1821 client->request_attempt = 0;
1822
1823 client->last_addr = client->lease->address;
1824
1825 r = client_set_lease_timeouts(client);
1826 if (r < 0)
1827 log_dhcp_client_errno(client, r, "could not set lease timeouts: %m");
1828
1829 r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port, client->ip_service_type);
1830 if (r < 0)
1831 return log_dhcp_client_errno(client, r, "could not bind UDP socket: %m");
1832
1833 client->receive_message = sd_event_source_disable_unref(client->receive_message);
1834 close_and_replace(client->fd, r);
1835 client_initialize_io_events(client, client_receive_message_udp);
1836
1837 client_notify(client, notify_event);
1838
1839 return 0;
1840 }
1841
1842 static int client_enter_bound_delayed(sd_event_source *s, uint64_t usec, void *userdata) {
1843 sd_dhcp_client *client = ASSERT_PTR(userdata);
1844 DHCP_CLIENT_DONT_DESTROY(client);
1845 int r;
1846
1847 r = client_enter_bound_now(client, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE);
1848 if (r < 0)
1849 client_stop(client, r);
1850
1851 return 0;
1852 }
1853
1854 static int client_enter_bound(sd_dhcp_client *client, int notify_event) {
1855 assert(client);
1856 assert(client->lease);
1857
1858 client->start_delay = 0;
1859 (void) event_source_disable(client->timeout_resend);
1860
1861 /* RFC 8925 section 3.2
1862 * If the client is in the INIT-REBOOT state, it SHOULD stop the DHCPv4 configuration process or
1863 * disable the IPv4 stack completely for V6ONLY_WAIT seconds or until the network attachment event,
1864 * whichever happens first.
1865 *
1866 * In the below, the condition uses REBOOTING, instead of INIT-REBOOT, as the client state has
1867 * already transitioned from INIT-REBOOT to REBOOTING after sending a DHCPREQUEST message. */
1868 if (client->state == DHCP_STATE_REBOOTING && client->lease->ipv6_only_preferred_usec > 0) {
1869 if (client->ipv6_acquired) {
1870 log_dhcp_client(client,
1871 "Received an ACK with IPv6-only preferred option, and the host already acquired IPv6 connectivity, stopping DHCPv4 client.");
1872 return sd_dhcp_client_stop(client);
1873 }
1874
1875 log_dhcp_client(client,
1876 "Received an ACK with IPv6-only preferred option, delaying to enter bound state with %s.",
1877 FORMAT_TIMESPAN(client->lease->ipv6_only_preferred_usec, USEC_PER_SEC));
1878
1879 return event_reset_time_relative(client->event, &client->timeout_ipv6_only_mode,
1880 CLOCK_BOOTTIME,
1881 client->lease->ipv6_only_preferred_usec, 0,
1882 client_enter_bound_delayed, client,
1883 client->event_priority, "dhcp4-ipv6-only-mode",
1884 /* force_reset = */ true);
1885 }
1886
1887 return client_enter_bound_now(client, notify_event);
1888 }
1889
1890 static int client_restart(sd_dhcp_client *client) {
1891 int r;
1892 assert(client);
1893
1894 client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
1895
1896 r = client_initialize(client);
1897 if (r < 0)
1898 return r;
1899
1900 r = client_start_delayed(client);
1901 if (r < 0)
1902 return r;
1903
1904 log_dhcp_client(client, "REBOOT in %s", FORMAT_TIMESPAN(client->start_delay, USEC_PER_SEC));
1905
1906 client->start_delay = CLAMP(client->start_delay * 2,
1907 RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC);
1908 return 0;
1909 }
1910
1911 static int client_verify_message_header(sd_dhcp_client *client, DHCPMessage *message, size_t len) {
1912 const uint8_t *expected_chaddr = NULL;
1913 uint8_t expected_hlen = 0;
1914
1915 assert(client);
1916 assert(message);
1917
1918 if (len < sizeof(DHCPMessage))
1919 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG),
1920 "Too small to be a DHCP message, ignoring.");
1921
1922 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE)
1923 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG),
1924 "Not a DHCP message, ignoring.");
1925
1926 if (message->op != BOOTREPLY)
1927 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG),
1928 "Not a BOOTREPLY message, ignoring.");
1929
1930 if (message->htype != client->arp_type)
1931 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG),
1932 "Packet type does not match client type, ignoring.");
1933
1934 if (client->arp_type == ARPHRD_ETHER) {
1935 expected_hlen = ETH_ALEN;
1936 expected_chaddr = client->hw_addr.bytes;
1937 }
1938
1939 if (message->hlen != expected_hlen)
1940 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG),
1941 "Received packet hlen (%u) does not match expected (%u), ignoring.",
1942 message->hlen, expected_hlen);
1943
1944 if (memcmp_safe(message->chaddr, expected_chaddr, expected_hlen))
1945 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG),
1946 "Received chaddr does not match expected, ignoring.");
1947
1948 if (client->state != DHCP_STATE_BOUND &&
1949 be32toh(message->xid) != client->xid)
1950 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1951 so ignore the xid in this case */
1952 return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EBADMSG),
1953 "Received xid (%u) does not match expected (%u), ignoring.",
1954 be32toh(message->xid), client->xid);
1955
1956 return 0;
1957 }
1958
1959 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, size_t len, const triple_timestamp *timestamp) {
1960 DHCP_CLIENT_DONT_DESTROY(client);
1961 int r;
1962
1963 assert(client);
1964 assert(message);
1965 assert(timestamp);
1966
1967 if (client_verify_message_header(client, message, len) < 0)
1968 return 0;
1969
1970 switch (client->state) {
1971 case DHCP_STATE_SELECTING:
1972
1973 r = client_handle_offer_or_rapid_ack(client, message, len, timestamp);
1974 if (ERRNO_IS_NEG_RESOURCE(r))
1975 return r;
1976 if (r == -EADDRNOTAVAIL)
1977 /* got a rapid NAK, let's restart the client */
1978 return client_restart(client);
1979 if (r < 0)
1980 return 0; /* invalid message, let's ignore it */
1981
1982 if (client->lease->rapid_commit)
1983 /* got a successful rapid commit */
1984 return client_enter_bound(client, r);
1985
1986 return client_enter_requesting(client);
1987
1988 case DHCP_STATE_REBOOTING:
1989 case DHCP_STATE_REQUESTING:
1990 case DHCP_STATE_RENEWING:
1991 case DHCP_STATE_REBINDING:
1992
1993 r = client_handle_ack(client, message, len, timestamp);
1994 if (ERRNO_IS_NEG_RESOURCE(r))
1995 return r;
1996 if (r == -EADDRNOTAVAIL)
1997 /* got a NAK, let's restart the client */
1998 return client_restart(client);
1999 if (r < 0)
2000 return 0; /* invalid message, let's ignore it */
2001
2002 return client_enter_bound(client, r);
2003
2004 case DHCP_STATE_BOUND:
2005 r = client_handle_forcerenew(client, message, len);
2006 if (ERRNO_IS_NEG_RESOURCE(r))
2007 return r;
2008 if (r < 0)
2009 return 0; /* invalid message, let's ignore it */
2010
2011 return client_timeout_t1(NULL, 0, client);
2012
2013 case DHCP_STATE_INIT:
2014 case DHCP_STATE_INIT_REBOOT:
2015 log_dhcp_client(client, "Unexpectedly receive message without sending any requests, ignoring.");
2016 return 0;
2017
2018 default:
2019 assert_not_reached();
2020 }
2021
2022 return 0;
2023 }
2024
2025 static int client_receive_message_udp(
2026 sd_event_source *s,
2027 int fd,
2028 uint32_t revents,
2029 void *userdata) {
2030
2031 sd_dhcp_client *client = ASSERT_PTR(userdata);
2032 _cleanup_free_ DHCPMessage *message = NULL;
2033 ssize_t len, buflen;
2034 /* This needs to be initialized with zero. See #20741. */
2035 CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL) control = {};
2036 struct iovec iov;
2037 struct msghdr msg = {
2038 .msg_iov = &iov,
2039 .msg_iovlen = 1,
2040 .msg_control = &control,
2041 .msg_controllen = sizeof(control),
2042 };
2043 int r;
2044
2045 assert(s);
2046
2047 buflen = next_datagram_size_fd(fd);
2048 if (ERRNO_IS_NEG_TRANSIENT(buflen) || ERRNO_IS_NEG_DISCONNECT(buflen))
2049 return 0;
2050 if (buflen < 0) {
2051 log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m");
2052 return 0;
2053 }
2054
2055 message = malloc0(buflen);
2056 if (!message)
2057 return -ENOMEM;
2058
2059 iov = IOVEC_MAKE(message, buflen);
2060
2061 len = recvmsg_safe(fd, &msg, MSG_DONTWAIT);
2062 if (ERRNO_IS_NEG_TRANSIENT(len) || ERRNO_IS_NEG_DISCONNECT(len))
2063 return 0;
2064 if (len < 0) {
2065 log_dhcp_client_errno(client, len, "Could not receive message from UDP socket, ignoring: %m");
2066 return 0;
2067 }
2068
2069 log_dhcp_client(client, "Received message from UDP socket, processing.");
2070 r = client_handle_message(client, message, len, TRIPLE_TIMESTAMP_FROM_CMSG(&msg));
2071 if (r < 0)
2072 client_stop(client, r);
2073
2074 return 0;
2075 }
2076
2077 static int client_receive_message_raw(
2078 sd_event_source *s,
2079 int fd,
2080 uint32_t revents,
2081 void *userdata) {
2082
2083 sd_dhcp_client *client = ASSERT_PTR(userdata);
2084 _cleanup_free_ DHCPPacket *packet = NULL;
2085 /* This needs to be initialized with zero. See #20741. */
2086 CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL +
2087 CMSG_SPACE(sizeof(struct tpacket_auxdata))) control = {};
2088 struct iovec iov = {};
2089 struct msghdr msg = {
2090 .msg_iov = &iov,
2091 .msg_iovlen = 1,
2092 .msg_control = &control,
2093 .msg_controllen = sizeof(control),
2094 };
2095 bool checksum = true;
2096 ssize_t buflen, len;
2097 int r;
2098
2099 assert(s);
2100
2101 buflen = next_datagram_size_fd(fd);
2102 if (ERRNO_IS_NEG_TRANSIENT(buflen) || ERRNO_IS_NEG_DISCONNECT(buflen))
2103 return 0;
2104 if (buflen < 0) {
2105 log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m");
2106 return 0;
2107 }
2108
2109 packet = malloc0(buflen);
2110 if (!packet)
2111 return -ENOMEM;
2112
2113 iov = IOVEC_MAKE(packet, buflen);
2114
2115 len = recvmsg_safe(fd, &msg, 0);
2116 if (ERRNO_IS_NEG_TRANSIENT(len) || ERRNO_IS_NEG_DISCONNECT(len))
2117 return 0;
2118 if (len < 0) {
2119 log_dhcp_client_errno(client, len, "Could not receive message from raw socket, ignoring: %m");
2120 return 0;
2121 }
2122
2123 struct tpacket_auxdata *aux = CMSG_FIND_DATA(&msg, SOL_PACKET, PACKET_AUXDATA, struct tpacket_auxdata);
2124 if (aux)
2125 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
2126
2127 if (dhcp_packet_verify_headers(packet, len, checksum, client->port) < 0)
2128 return 0;
2129
2130 len -= DHCP_IP_UDP_SIZE;
2131
2132 log_dhcp_client(client, "Received message from RAW socket, processing.");
2133 r = client_handle_message(client, &packet->dhcp, len, TRIPLE_TIMESTAMP_FROM_CMSG(&msg));
2134 if (r < 0)
2135 client_stop(client, r);
2136
2137 return 0;
2138 }
2139
2140 int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
2141 if (!sd_dhcp_client_is_running(client) || client->state != DHCP_STATE_BOUND)
2142 return 0; /* do nothing */
2143
2144 client->start_delay = 0;
2145 client->discover_attempt = 1;
2146 client->request_attempt = 1;
2147 client_set_state(client, DHCP_STATE_RENEWING);
2148
2149 return client_initialize_time_events(client);
2150 }
2151
2152 int sd_dhcp_client_is_running(sd_dhcp_client *client) {
2153 if (!client)
2154 return 0;
2155
2156 return client->state != DHCP_STATE_STOPPED;
2157 }
2158
2159 int sd_dhcp_client_start(sd_dhcp_client *client) {
2160 int r;
2161
2162 assert_return(client, -EINVAL);
2163
2164 /* Note, do not reset the flag in client_initialize(), as it is also called on expire. */
2165 client->ipv6_acquired = false;
2166
2167 r = client_initialize(client);
2168 if (r < 0)
2169 return r;
2170
2171 /* If no client identifier exists, construct an RFC 4361-compliant one */
2172 if (!sd_dhcp_client_id_is_set(&client->client_id)) {
2173 r = sd_dhcp_client_set_iaid_duid_en(client, /* iaid_set = */ false, /* iaid = */ 0);
2174 if (r < 0)
2175 return r;
2176 }
2177
2178 /* RFC7844 section 3.3:
2179 SHOULD perform a complete four-way handshake, starting with a
2180 DHCPDISCOVER, to obtain a new address lease. If the client can
2181 ascertain that this is exactly the same network to which it was
2182 previously connected, and if the link-layer address did not change,
2183 the client MAY issue a DHCPREQUEST to try to reclaim the current
2184 address. */
2185 if (client->last_addr && !client->anonymize)
2186 client_set_state(client, DHCP_STATE_INIT_REBOOT);
2187
2188 r = client_start(client);
2189 if (r >= 0)
2190 log_dhcp_client(client, "STARTED on ifindex %i", client->ifindex);
2191
2192 return r;
2193 }
2194
2195 int sd_dhcp_client_send_release(sd_dhcp_client *client) {
2196 _cleanup_free_ DHCPPacket *release = NULL;
2197 size_t optoffset, optlen;
2198 int r;
2199
2200 if (!sd_dhcp_client_is_running(client) || !client->lease)
2201 return 0; /* do nothing */
2202
2203 r = client_message_init(client, &release, DHCP_RELEASE, &optlen, &optoffset);
2204 if (r < 0)
2205 return r;
2206
2207 /* Fill up release IP and MAC */
2208 release->dhcp.ciaddr = client->lease->address;
2209 memcpy(&release->dhcp.chaddr, client->hw_addr.bytes, client->hw_addr.length);
2210
2211 r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
2212 SD_DHCP_OPTION_END, 0, NULL);
2213 if (r < 0)
2214 return r;
2215
2216 r = dhcp_network_send_udp_socket(client->fd,
2217 client->lease->server_address,
2218 client->server_port,
2219 &release->dhcp,
2220 sizeof(DHCPMessage) + optoffset);
2221 if (r < 0)
2222 return r;
2223
2224 log_dhcp_client(client, "RELEASE");
2225
2226 /* This function is mostly called when stopping daemon. Hence, do not call client_stop() or
2227 * client_restart(). Otherwise, the notification callback will be called again and we may easily
2228 * enter an infinite loop. */
2229 client_initialize(client);
2230 return 1; /* sent and stopped. */
2231 }
2232
2233 int sd_dhcp_client_send_decline(sd_dhcp_client *client) {
2234 _cleanup_free_ DHCPPacket *release = NULL;
2235 size_t optoffset, optlen;
2236 int r;
2237
2238 if (!sd_dhcp_client_is_running(client) || !client->lease)
2239 return 0; /* do nothing */
2240
2241 r = client_message_init(client, &release, DHCP_DECLINE, &optlen, &optoffset);
2242 if (r < 0)
2243 return r;
2244
2245 release->dhcp.ciaddr = client->lease->address;
2246 memcpy(&release->dhcp.chaddr, client->hw_addr.bytes, client->hw_addr.length);
2247
2248 r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
2249 SD_DHCP_OPTION_END, 0, NULL);
2250 if (r < 0)
2251 return r;
2252
2253 r = dhcp_network_send_udp_socket(client->fd,
2254 client->lease->server_address,
2255 client->server_port,
2256 &release->dhcp,
2257 sizeof(DHCPMessage) + optoffset);
2258 if (r < 0)
2259 return r;
2260
2261 log_dhcp_client(client, "DECLINE");
2262
2263 /* This function is mostly called when the acquired address conflicts with another host.
2264 * Restarting the daemon to acquire another address. */
2265 r = client_restart(client);
2266 if (r < 0)
2267 return r;
2268
2269 return 1; /* sent and restarted. */
2270 }
2271
2272 int sd_dhcp_client_stop(sd_dhcp_client *client) {
2273 if (!client)
2274 return 0;
2275
2276 DHCP_CLIENT_DONT_DESTROY(client);
2277
2278 client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
2279
2280 return 0;
2281 }
2282
2283 int sd_dhcp_client_set_ipv6_connectivity(sd_dhcp_client *client, int have) {
2284 if (!client)
2285 return 0;
2286
2287 /* We have already received a message with IPv6-Only preferred option, and are waiting for IPv6
2288 * connectivity or timeout, let's stop the client. */
2289 if (have && sd_event_source_get_enabled(client->timeout_ipv6_only_mode, NULL) > 0)
2290 return sd_dhcp_client_stop(client);
2291
2292 /* Otherwise, save that the host already has IPv6 connectivity. */
2293 client->ipv6_acquired = have;
2294 return 0;
2295 }
2296
2297 int sd_dhcp_client_interrupt_ipv6_only_mode(sd_dhcp_client *client) {
2298 assert_return(client, -EINVAL);
2299 assert_return(sd_dhcp_client_is_running(client), -ESTALE);
2300 assert_return(client->fd >= 0, -EINVAL);
2301
2302 if (sd_event_source_get_enabled(client->timeout_ipv6_only_mode, NULL) <= 0)
2303 return 0;
2304
2305 client_initialize(client);
2306 return client_start(client);
2307 }
2308
2309 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) {
2310 int r;
2311
2312 assert_return(client, -EINVAL);
2313 assert_return(!client->event, -EBUSY);
2314 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
2315
2316 if (event)
2317 client->event = sd_event_ref(event);
2318 else {
2319 r = sd_event_default(&client->event);
2320 if (r < 0)
2321 return 0;
2322 }
2323
2324 client->event_priority = priority;
2325
2326 return 0;
2327 }
2328
2329 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
2330 assert_return(client, -EINVAL);
2331 assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
2332
2333 client->event = sd_event_unref(client->event);
2334
2335 return 0;
2336 }
2337
2338 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
2339 assert_return(client, NULL);
2340
2341 return client->event;
2342 }
2343
2344 int sd_dhcp_client_attach_device(sd_dhcp_client *client, sd_device *dev) {
2345 assert_return(client, -EINVAL);
2346
2347 return device_unref_and_replace(client->dev, dev);
2348 }
2349
2350 static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
2351 if (!client)
2352 return NULL;
2353
2354 log_dhcp_client(client, "FREE");
2355
2356 client_initialize(client);
2357
2358 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
2359 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
2360 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
2361 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
2362
2363 sd_dhcp_client_detach_event(client);
2364
2365 sd_device_unref(client->dev);
2366
2367 set_free(client->req_opts);
2368 free(client->hostname);
2369 free(client->vendor_class_identifier);
2370 free(client->mudurl);
2371 client->user_class = strv_free(client->user_class);
2372 ordered_hashmap_free(client->extra_options);
2373 ordered_hashmap_free(client->vendor_options);
2374 free(client->ifname);
2375 return mfree(client);
2376 }
2377
2378 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
2379
2380 int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
2381 const uint8_t *opts;
2382 size_t n_opts;
2383 int r;
2384
2385 assert_return(ret, -EINVAL);
2386
2387 _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1);
2388 if (!client)
2389 return -ENOMEM;
2390
2391 *client = (sd_dhcp_client) {
2392 .n_ref = 1,
2393 .state = DHCP_STATE_STOPPED,
2394 .ifindex = -1,
2395 .fd = -EBADF,
2396 .mtu = DHCP_MIN_PACKET_SIZE,
2397 .port = DHCP_PORT_CLIENT,
2398 .server_port = DHCP_PORT_SERVER,
2399 .anonymize = !!anonymize,
2400 .max_discover_attempts = UINT64_MAX,
2401 .max_request_attempts = 5,
2402 .ip_service_type = -1,
2403 };
2404 /* NOTE: this could be moved to a function. */
2405 if (anonymize) {
2406 n_opts = ELEMENTSOF(default_req_opts_anonymize);
2407 opts = default_req_opts_anonymize;
2408 } else {
2409 n_opts = ELEMENTSOF(default_req_opts);
2410 opts = default_req_opts;
2411 }
2412
2413 for (size_t i = 0; i < n_opts; i++) {
2414 r = sd_dhcp_client_set_request_option(client, opts[i]);
2415 if (r < 0)
2416 return r;
2417 }
2418
2419 *ret = TAKE_PTR(client);
2420
2421 return 0;
2422 }
2423
2424 static const char* const dhcp_state_table[_DHCP_STATE_MAX] = {
2425 [DHCP_STATE_STOPPED] = "stopped",
2426 [DHCP_STATE_INIT] = "initialization",
2427 [DHCP_STATE_SELECTING] = "selecting",
2428 [DHCP_STATE_INIT_REBOOT] = "init-reboot",
2429 [DHCP_STATE_REBOOTING] = "rebooting",
2430 [DHCP_STATE_REQUESTING] = "requesting",
2431 [DHCP_STATE_BOUND] = "bound",
2432 [DHCP_STATE_RENEWING] = "renewing",
2433 [DHCP_STATE_REBINDING] = "rebinding",
2434 };
2435
2436 DEFINE_STRING_TABLE_LOOKUP_TO_STRING(dhcp_state, DHCPState);