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