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