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