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