]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-client.c
Merge pull request #13554 from keur/systemctl_status_timer
[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 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 if (!client)
2051 return NULL;
2052
2053 log_dhcp_client(client, "FREE");
2054
2055 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
2056 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
2057 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
2058 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
2059
2060 client_initialize(client);
2061
2062 sd_dhcp_client_detach_event(client);
2063
2064 sd_dhcp_lease_unref(client->lease);
2065
2066 free(client->req_opts);
2067 free(client->hostname);
2068 free(client->vendor_class_identifier);
2069 client->user_class = strv_free(client->user_class);
2070 ordered_hashmap_free(client->options);
2071 return mfree(client);
2072 }
2073
2074 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
2075
2076 int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
2077 assert_return(ret, -EINVAL);
2078
2079 _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1);
2080 if (!client)
2081 return -ENOMEM;
2082
2083 *client = (sd_dhcp_client) {
2084 .n_ref = 1,
2085 .state = DHCP_STATE_INIT,
2086 .ifindex = -1,
2087 .fd = -1,
2088 .mtu = DHCP_DEFAULT_MIN_SIZE,
2089 .port = DHCP_PORT_CLIENT,
2090 .anonymize = !!anonymize,
2091 .max_attempts = (uint64_t) -1,
2092 .ip_service_type = -1,
2093 };
2094 /* NOTE: this could be moved to a function. */
2095 if (anonymize) {
2096 client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize);
2097 client->req_opts = memdup(default_req_opts_anonymize, client->req_opts_size);
2098 } else {
2099 client->req_opts_size = ELEMENTSOF(default_req_opts);
2100 client->req_opts = memdup(default_req_opts, client->req_opts_size);
2101 }
2102 if (!client->req_opts)
2103 return -ENOMEM;
2104
2105 *ret = TAKE_PTR(client);
2106
2107 return 0;
2108 }