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