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