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