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