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