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