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