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