]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-client.c
networkd: Allow DHCP4 client to set the number to attempt to reconfigure.
[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_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 void client_notify(sd_dhcp_client *client, int event) {
545 assert(client);
546
547 if (client->callback)
548 client->callback(client, event, client->userdata);
549 }
550
551 static int client_initialize(sd_dhcp_client *client) {
552 assert_return(client, -EINVAL);
553
554 client->receive_message = sd_event_source_unref(client->receive_message);
555
556 client->fd = asynchronous_close(client->fd);
557
558 (void) event_source_disable(client->timeout_resend);
559 (void) event_source_disable(client->timeout_t1);
560 (void) event_source_disable(client->timeout_t2);
561 (void) event_source_disable(client->timeout_expire);
562
563 client->attempt = 0;
564
565 client->state = DHCP_STATE_INIT;
566 client->xid = 0;
567
568 client->lease = sd_dhcp_lease_unref(client->lease);
569
570 return 0;
571 }
572
573 static void client_stop(sd_dhcp_client *client, int error) {
574 assert(client);
575
576 if (error < 0)
577 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
578 else if (error == SD_DHCP_CLIENT_EVENT_STOP)
579 log_dhcp_client(client, "STOPPED");
580 else
581 log_dhcp_client(client, "STOPPED: Unknown event");
582
583 client_notify(client, error);
584
585 client_initialize(client);
586 }
587
588 static int client_message_init(
589 sd_dhcp_client *client,
590 DHCPPacket **ret,
591 uint8_t type,
592 size_t *_optlen,
593 size_t *_optoffset) {
594
595 _cleanup_free_ DHCPPacket *packet = NULL;
596 size_t optlen, optoffset, size;
597 be16_t max_size;
598 usec_t time_now;
599 uint16_t secs;
600 int r;
601
602 assert(client);
603 assert(client->start_time);
604 assert(ret);
605 assert(_optlen);
606 assert(_optoffset);
607 assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST));
608
609 optlen = DHCP_MIN_OPTIONS_SIZE;
610 size = sizeof(DHCPPacket) + optlen;
611
612 packet = malloc0(size);
613 if (!packet)
614 return -ENOMEM;
615
616 r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
617 client->arp_type, optlen, &optoffset);
618 if (r < 0)
619 return r;
620
621 /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
622 refuse to issue an DHCP lease if 'secs' is set to zero */
623 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
624 if (r < 0)
625 return r;
626 assert(time_now >= client->start_time);
627
628 /* seconds between sending first and last DISCOVER
629 * must always be strictly positive to deal with broken servers */
630 secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
631 packet->dhcp.secs = htobe16(secs);
632
633 /* RFC2132 section 4.1
634 A client that cannot receive unicast IP datagrams until its protocol
635 software has been configured with an IP address SHOULD set the
636 BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
637 DHCPREQUEST messages that client sends. The BROADCAST bit will
638 provide a hint to the DHCP server and BOOTP relay agent to broadcast
639 any messages to the client on the client's subnet.
640
641 Note: some interfaces needs this to be enabled, but some networks
642 needs this to be disabled as broadcasts are filteretd, so this
643 needs to be configurable */
644 if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
645 packet->dhcp.flags = htobe16(0x8000);
646
647 /* RFC2132 section 4.1.1:
648 The client MUST include its hardware address in the ’chaddr’ field, if
649 necessary for delivery of DHCP reply messages. Non-Ethernet
650 interfaces will leave 'chaddr' empty and use the client identifier
651 instead (eg, RFC 4390 section 2.1).
652 */
653 if (client->arp_type == ARPHRD_ETHER)
654 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
655
656 /* If no client identifier exists, construct an RFC 4361-compliant one */
657 if (client->client_id_len == 0) {
658 size_t duid_len;
659
660 client->client_id.type = 255;
661
662 r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
663 true, &client->client_id.ns.iaid);
664 if (r < 0)
665 return r;
666
667 r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len);
668 if (r < 0)
669 return r;
670
671 client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
672 }
673
674 /* Some DHCP servers will refuse to issue an DHCP lease if the Client
675 Identifier option is not set */
676 if (client->client_id_len) {
677 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
678 SD_DHCP_OPTION_CLIENT_IDENTIFIER,
679 client->client_id_len,
680 &client->client_id);
681 if (r < 0)
682 return r;
683 }
684
685 /* RFC2131 section 3.5:
686 in its initial DHCPDISCOVER or DHCPREQUEST message, a
687 client may provide the server with a list of specific
688 parameters the client is interested in. If the client
689 includes a list of parameters in a DHCPDISCOVER message,
690 it MUST include that list in any subsequent DHCPREQUEST
691 messages.
692 */
693
694 /* RFC7844 section 3:
695 MAY contain the Parameter Request List option. */
696 /* NOTE: in case that there would be an option to do not send
697 * any PRL at all, the size should be checked before sending */
698 if (client->req_opts_size > 0) {
699 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
700 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
701 client->req_opts_size, client->req_opts);
702 if (r < 0)
703 return r;
704 }
705
706 /* RFC2131 section 3.5:
707 The client SHOULD include the ’maximum DHCP message size’ option to
708 let the server know how large the server may make its DHCP messages.
709
710 Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
711 than the defined default size unless the Maximum Message Size option
712 is explicitly set
713
714 RFC3442 "Requirements to Avoid Sizing Constraints":
715 Because a full routing table can be quite large, the standard 576
716 octet maximum size for a DHCP message may be too short to contain
717 some legitimate Classless Static Route options. Because of this,
718 clients implementing the Classless Static Route option SHOULD send a
719 Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
720 stack is capable of receiving larger IP datagrams. In this case, the
721 client SHOULD set the value of this option to at least the MTU of the
722 interface that the client is configuring. The client MAY set the
723 value of this option higher, up to the size of the largest UDP packet
724 it is prepared to accept. (Note that the value specified in the
725 Maximum DHCP Message Size option is the total maximum packet size,
726 including IP and UDP headers.)
727 */
728 /* RFC7844 section 3:
729 SHOULD NOT contain any other option. */
730 if (!client->anonymize) {
731 max_size = htobe16(size);
732 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
733 SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
734 2, &max_size);
735 if (r < 0)
736 return r;
737 }
738
739 *_optlen = optlen;
740 *_optoffset = optoffset;
741 *ret = TAKE_PTR(packet);
742
743 return 0;
744 }
745
746 static int client_append_fqdn_option(
747 DHCPMessage *message,
748 size_t optlen,
749 size_t *optoffset,
750 const char *fqdn) {
751
752 uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
753 int r;
754
755 buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */
756 DHCP_FQDN_FLAG_E; /* Canonical wire format */
757 buffer[1] = 0; /* RCODE1 (deprecated) */
758 buffer[2] = 0; /* RCODE2 (deprecated) */
759
760 r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false);
761 if (r > 0)
762 r = dhcp_option_append(message, optlen, optoffset, 0,
763 SD_DHCP_OPTION_FQDN, 3 + r, buffer);
764
765 return r;
766 }
767
768 static int dhcp_client_send_raw(
769 sd_dhcp_client *client,
770 DHCPPacket *packet,
771 size_t len) {
772
773 dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port,
774 INADDR_BROADCAST, DHCP_PORT_SERVER, len);
775
776 return dhcp_network_send_raw_socket(client->fd, &client->link,
777 packet, len);
778 }
779
780 static int client_send_discover(sd_dhcp_client *client) {
781 _cleanup_free_ DHCPPacket *discover = NULL;
782 size_t optoffset, optlen;
783 int r;
784
785 assert(client);
786 assert(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_SELECTING));
787
788 r = client_message_init(client, &discover, DHCP_DISCOVER,
789 &optlen, &optoffset);
790 if (r < 0)
791 return r;
792
793 /* the client may suggest values for the network address
794 and lease time in the DHCPDISCOVER message. The client may include
795 the ’requested IP address’ option to suggest that a particular IP
796 address be assigned, and may include the ’IP address lease time’
797 option to suggest the lease time it would like.
798 */
799 if (client->last_addr != INADDR_ANY) {
800 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
801 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
802 4, &client->last_addr);
803 if (r < 0)
804 return r;
805 }
806
807 if (client->hostname) {
808 /* According to RFC 4702 "clients that send the Client FQDN option in
809 their messages MUST NOT also send the Host Name option". Just send
810 one of the two depending on the hostname type.
811 */
812 if (dns_name_is_single_label(client->hostname)) {
813 /* it is unclear from RFC 2131 if client should send hostname in
814 DHCPDISCOVER but dhclient does and so we do as well
815 */
816 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
817 SD_DHCP_OPTION_HOST_NAME,
818 strlen(client->hostname), client->hostname);
819 } else
820 r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
821 client->hostname);
822 if (r < 0)
823 return r;
824 }
825
826 if (client->vendor_class_identifier) {
827 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
828 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
829 strlen(client->vendor_class_identifier),
830 client->vendor_class_identifier);
831 if (r < 0)
832 return r;
833 }
834
835 if (client->user_class) {
836 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
837 SD_DHCP_OPTION_USER_CLASS,
838 strv_length(client->user_class),
839 client->user_class);
840 if (r < 0)
841 return r;
842 }
843
844 r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
845 SD_DHCP_OPTION_END, 0, NULL);
846 if (r < 0)
847 return r;
848
849 /* We currently ignore:
850 The client SHOULD wait a random time between one and ten seconds to
851 desynchronize the use of DHCP at startup.
852 */
853 r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
854 if (r < 0)
855 return r;
856
857 log_dhcp_client(client, "DISCOVER");
858
859 return 0;
860 }
861
862 static int client_send_request(sd_dhcp_client *client) {
863 _cleanup_free_ DHCPPacket *request = NULL;
864 size_t optoffset, optlen;
865 int r;
866
867 assert(client);
868
869 r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset);
870 if (r < 0)
871 return r;
872
873 switch (client->state) {
874 /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
875 SELECTING should be REQUESTING)
876 */
877
878 case DHCP_STATE_REQUESTING:
879 /* Client inserts the address of the selected server in ’server
880 identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
881 filled in with the yiaddr value from the chosen DHCPOFFER.
882 */
883
884 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
885 SD_DHCP_OPTION_SERVER_IDENTIFIER,
886 4, &client->lease->server_address);
887 if (r < 0)
888 return r;
889
890 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
891 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
892 4, &client->lease->address);
893 if (r < 0)
894 return r;
895
896 break;
897
898 case DHCP_STATE_INIT_REBOOT:
899 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
900 option MUST be filled in with client’s notion of its previously
901 assigned address. ’ciaddr’ MUST be zero.
902 */
903 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
904 SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
905 4, &client->last_addr);
906 if (r < 0)
907 return r;
908 break;
909
910 case DHCP_STATE_RENEWING:
911 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
912 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
913 client’s IP address.
914 */
915
916 case DHCP_STATE_REBINDING:
917 /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
918 option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
919 client’s IP address.
920
921 This message MUST be broadcast to the 0xffffffff IP broadcast address.
922 */
923 request->dhcp.ciaddr = client->lease->address;
924
925 break;
926
927 case DHCP_STATE_INIT:
928 case DHCP_STATE_SELECTING:
929 case DHCP_STATE_REBOOTING:
930 case DHCP_STATE_BOUND:
931 case DHCP_STATE_STOPPED:
932 return -EINVAL;
933 }
934
935 if (client->hostname) {
936 if (dns_name_is_single_label(client->hostname))
937 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
938 SD_DHCP_OPTION_HOST_NAME,
939 strlen(client->hostname), client->hostname);
940 else
941 r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
942 client->hostname);
943 if (r < 0)
944 return r;
945 }
946
947 if (client->vendor_class_identifier) {
948 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
949 SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
950 strlen(client->vendor_class_identifier),
951 client->vendor_class_identifier);
952 if (r < 0)
953 return r;
954 }
955
956 r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
957 SD_DHCP_OPTION_END, 0, NULL);
958 if (r < 0)
959 return r;
960
961 if (client->state == DHCP_STATE_RENEWING) {
962 r = dhcp_network_send_udp_socket(client->fd,
963 client->lease->server_address,
964 DHCP_PORT_SERVER,
965 &request->dhcp,
966 sizeof(DHCPMessage) + optoffset);
967 } else {
968 r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
969 }
970 if (r < 0)
971 return r;
972
973 switch (client->state) {
974
975 case DHCP_STATE_REQUESTING:
976 log_dhcp_client(client, "REQUEST (requesting)");
977 break;
978
979 case DHCP_STATE_INIT_REBOOT:
980 log_dhcp_client(client, "REQUEST (init-reboot)");
981 break;
982
983 case DHCP_STATE_RENEWING:
984 log_dhcp_client(client, "REQUEST (renewing)");
985 break;
986
987 case DHCP_STATE_REBINDING:
988 log_dhcp_client(client, "REQUEST (rebinding)");
989 break;
990
991 default:
992 log_dhcp_client(client, "REQUEST (invalid)");
993 break;
994 }
995
996 return 0;
997 }
998
999 static int client_start(sd_dhcp_client *client);
1000
1001 static int client_timeout_resend(
1002 sd_event_source *s,
1003 uint64_t usec,
1004 void *userdata) {
1005
1006 sd_dhcp_client *client = userdata;
1007 DHCP_CLIENT_DONT_DESTROY(client);
1008 usec_t next_timeout = 0;
1009 uint64_t time_now;
1010 uint32_t time_left;
1011 int r;
1012
1013 assert(s);
1014 assert(client);
1015 assert(client->event);
1016
1017 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1018 if (r < 0)
1019 goto error;
1020
1021 switch (client->state) {
1022
1023 case DHCP_STATE_RENEWING:
1024
1025 time_left = (client->lease->t2 - client->lease->t1) / 2;
1026 if (time_left < 60)
1027 time_left = 60;
1028
1029 next_timeout = time_now + time_left * USEC_PER_SEC;
1030
1031 break;
1032
1033 case DHCP_STATE_REBINDING:
1034
1035 time_left = (client->lease->lifetime - client->lease->t2) / 2;
1036 if (time_left < 60)
1037 time_left = 60;
1038
1039 next_timeout = time_now + time_left * USEC_PER_SEC;
1040 break;
1041
1042 case DHCP_STATE_REBOOTING:
1043 /* start over as we did not receive a timely ack or nak */
1044 r = client_initialize(client);
1045 if (r < 0)
1046 goto error;
1047
1048 r = client_start(client);
1049 if (r < 0)
1050 goto error;
1051 else {
1052 log_dhcp_client(client, "REBOOTED");
1053 return 0;
1054 }
1055
1056 case DHCP_STATE_INIT:
1057 case DHCP_STATE_INIT_REBOOT:
1058 case DHCP_STATE_SELECTING:
1059 case DHCP_STATE_REQUESTING:
1060 case DHCP_STATE_BOUND:
1061
1062 if (client->attempt < client->max_attempts)
1063 client->attempt++;
1064 else
1065 goto error;
1066
1067 next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
1068
1069 break;
1070
1071 case DHCP_STATE_STOPPED:
1072 r = -EINVAL;
1073 goto error;
1074 }
1075
1076 next_timeout += (random_u32() & 0x1fffff);
1077
1078 r = event_reset_time(client->event, &client->timeout_resend,
1079 clock_boottime_or_monotonic(),
1080 next_timeout, 10 * USEC_PER_MSEC,
1081 client_timeout_resend, client,
1082 client->event_priority, "dhcp4-resend-timer", true);
1083 if (r < 0)
1084 goto error;
1085
1086 switch (client->state) {
1087 case DHCP_STATE_INIT:
1088 r = client_send_discover(client);
1089 if (r >= 0) {
1090 client->state = DHCP_STATE_SELECTING;
1091 client->attempt = 0;
1092 } else if (client->attempt >= client->max_attempts)
1093 goto error;
1094
1095 break;
1096
1097 case DHCP_STATE_SELECTING:
1098 r = client_send_discover(client);
1099 if (r < 0 && client->attempt >= client->max_attempts)
1100 goto error;
1101
1102 break;
1103
1104 case DHCP_STATE_INIT_REBOOT:
1105 case DHCP_STATE_REQUESTING:
1106 case DHCP_STATE_RENEWING:
1107 case DHCP_STATE_REBINDING:
1108 r = client_send_request(client);
1109 if (r < 0 && client->attempt >= client->max_attempts)
1110 goto error;
1111
1112 if (client->state == DHCP_STATE_INIT_REBOOT)
1113 client->state = DHCP_STATE_REBOOTING;
1114
1115 client->request_sent = time_now;
1116
1117 break;
1118
1119 case DHCP_STATE_REBOOTING:
1120 case DHCP_STATE_BOUND:
1121
1122 break;
1123
1124 case DHCP_STATE_STOPPED:
1125 r = -EINVAL;
1126 goto error;
1127 }
1128
1129 return 0;
1130
1131 error:
1132 client_stop(client, r);
1133
1134 /* Errors were dealt with when stopping the client, don't spill
1135 errors into the event loop handler */
1136 return 0;
1137 }
1138
1139 static int client_initialize_io_events(
1140 sd_dhcp_client *client,
1141 sd_event_io_handler_t io_callback) {
1142
1143 int r;
1144
1145 assert(client);
1146 assert(client->event);
1147
1148 r = sd_event_add_io(client->event, &client->receive_message,
1149 client->fd, EPOLLIN, io_callback,
1150 client);
1151 if (r < 0)
1152 goto error;
1153
1154 r = sd_event_source_set_priority(client->receive_message,
1155 client->event_priority);
1156 if (r < 0)
1157 goto error;
1158
1159 r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
1160 if (r < 0)
1161 goto error;
1162
1163 error:
1164 if (r < 0)
1165 client_stop(client, r);
1166
1167 return 0;
1168 }
1169
1170 static int client_initialize_time_events(sd_dhcp_client *client) {
1171 uint64_t usec = 0;
1172 int r;
1173
1174 assert(client);
1175 assert(client->event);
1176
1177 if (client->start_delay) {
1178 assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0);
1179 usec += client->start_delay;
1180 }
1181
1182 r = event_reset_time(client->event, &client->timeout_resend,
1183 clock_boottime_or_monotonic(),
1184 usec, 0,
1185 client_timeout_resend, client,
1186 client->event_priority, "dhcp4-resend-timer", true);
1187 if (r < 0)
1188 client_stop(client, r);
1189
1190 return 0;
1191
1192 }
1193
1194 static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) {
1195 client_initialize_io_events(client, io_callback);
1196 client_initialize_time_events(client);
1197
1198 return 0;
1199 }
1200
1201 static int client_start_delayed(sd_dhcp_client *client) {
1202 int r;
1203
1204 assert_return(client, -EINVAL);
1205 assert_return(client->event, -EINVAL);
1206 assert_return(client->ifindex > 0, -EINVAL);
1207 assert_return(client->fd < 0, -EBUSY);
1208 assert_return(client->xid == 0, -EINVAL);
1209 assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT), -EBUSY);
1210
1211 client->xid = random_u32();
1212
1213 r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
1214 client->xid, client->mac_addr,
1215 client->mac_addr_len, client->arp_type, client->port);
1216 if (r < 0) {
1217 client_stop(client, r);
1218 return r;
1219 }
1220 client->fd = r;
1221
1222 if (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT))
1223 client->start_time = now(clock_boottime_or_monotonic());
1224
1225 return client_initialize_events(client, client_receive_message_raw);
1226 }
1227
1228 static int client_start(sd_dhcp_client *client) {
1229 client->start_delay = 0;
1230 return client_start_delayed(client);
1231 }
1232
1233 static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
1234 sd_dhcp_client *client = userdata;
1235 DHCP_CLIENT_DONT_DESTROY(client);
1236
1237 log_dhcp_client(client, "EXPIRED");
1238
1239 client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
1240
1241 /* lease was lost, start over if not freed or stopped in callback */
1242 if (client->state != DHCP_STATE_STOPPED) {
1243 client_initialize(client);
1244 client_start(client);
1245 }
1246
1247 return 0;
1248 }
1249
1250 static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
1251 sd_dhcp_client *client = userdata;
1252 DHCP_CLIENT_DONT_DESTROY(client);
1253 int r;
1254
1255 assert(client);
1256
1257 client->receive_message = sd_event_source_unref(client->receive_message);
1258 client->fd = asynchronous_close(client->fd);
1259
1260 client->state = DHCP_STATE_REBINDING;
1261 client->attempt = 0;
1262
1263 r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
1264 client->xid, client->mac_addr,
1265 client->mac_addr_len, client->arp_type,
1266 client->port);
1267 if (r < 0) {
1268 client_stop(client, r);
1269 return 0;
1270 }
1271 client->fd = r;
1272
1273 return client_initialize_events(client, client_receive_message_raw);
1274 }
1275
1276 static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
1277 sd_dhcp_client *client = userdata;
1278 DHCP_CLIENT_DONT_DESTROY(client);
1279
1280 client->state = DHCP_STATE_RENEWING;
1281 client->attempt = 0;
1282
1283 return client_initialize_time_events(client);
1284 }
1285
1286 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) {
1287 _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1288 int r;
1289
1290 r = dhcp_lease_new(&lease);
1291 if (r < 0)
1292 return r;
1293
1294 if (client->client_id_len) {
1295 r = dhcp_lease_set_client_id(lease,
1296 (uint8_t *) &client->client_id,
1297 client->client_id_len);
1298 if (r < 0)
1299 return r;
1300 }
1301
1302 r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL);
1303 if (r != DHCP_OFFER) {
1304 log_dhcp_client(client, "received message was not an OFFER, ignoring");
1305 return -ENOMSG;
1306 }
1307
1308 lease->next_server = offer->siaddr;
1309 lease->address = offer->yiaddr;
1310
1311 if (lease->address == 0 ||
1312 lease->server_address == 0 ||
1313 lease->lifetime == 0) {
1314 log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring");
1315 return -ENOMSG;
1316 }
1317
1318 if (!lease->have_subnet_mask) {
1319 r = dhcp_lease_set_default_subnet_mask(lease);
1320 if (r < 0) {
1321 log_dhcp_client(client,
1322 "received lease lacks subnet mask, "
1323 "and a fallback one cannot be generated, ignoring");
1324 return -ENOMSG;
1325 }
1326 }
1327
1328 sd_dhcp_lease_unref(client->lease);
1329 client->lease = TAKE_PTR(lease);
1330
1331 log_dhcp_client(client, "OFFER");
1332
1333 return 0;
1334 }
1335
1336 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) {
1337 int r;
1338
1339 r = dhcp_option_parse(force, len, NULL, NULL, NULL);
1340 if (r != DHCP_FORCERENEW)
1341 return -ENOMSG;
1342
1343 log_dhcp_client(client, "FORCERENEW");
1344
1345 return 0;
1346 }
1347
1348 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) {
1349 _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
1350 _cleanup_free_ char *error_message = NULL;
1351 int r;
1352
1353 r = dhcp_lease_new(&lease);
1354 if (r < 0)
1355 return r;
1356
1357 if (client->client_id_len) {
1358 r = dhcp_lease_set_client_id(lease,
1359 (uint8_t *) &client->client_id,
1360 client->client_id_len);
1361 if (r < 0)
1362 return r;
1363 }
1364
1365 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message);
1366 if (r == DHCP_NAK) {
1367 log_dhcp_client(client, "NAK: %s", strna(error_message));
1368 return -EADDRNOTAVAIL;
1369 }
1370
1371 if (r != DHCP_ACK) {
1372 log_dhcp_client(client, "received message was not an ACK, ignoring");
1373 return -ENOMSG;
1374 }
1375
1376 lease->next_server = ack->siaddr;
1377
1378 lease->address = ack->yiaddr;
1379
1380 if (lease->address == INADDR_ANY ||
1381 lease->server_address == INADDR_ANY ||
1382 lease->lifetime == 0) {
1383 log_dhcp_client(client, "received lease lacks address, server "
1384 "address or lease lifetime, ignoring");
1385 return -ENOMSG;
1386 }
1387
1388 if (lease->subnet_mask == INADDR_ANY) {
1389 r = dhcp_lease_set_default_subnet_mask(lease);
1390 if (r < 0) {
1391 log_dhcp_client(client,
1392 "received lease lacks subnet mask, "
1393 "and a fallback one cannot be generated, ignoring");
1394 return -ENOMSG;
1395 }
1396 }
1397
1398 r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1399 if (client->lease) {
1400 if (client->lease->address != lease->address ||
1401 client->lease->subnet_mask != lease->subnet_mask ||
1402 client->lease->router != lease->router) {
1403 r = SD_DHCP_CLIENT_EVENT_IP_CHANGE;
1404 } else
1405 r = SD_DHCP_CLIENT_EVENT_RENEW;
1406
1407 client->lease = sd_dhcp_lease_unref(client->lease);
1408 }
1409
1410 client->lease = TAKE_PTR(lease);
1411
1412 log_dhcp_client(client, "ACK");
1413
1414 return r;
1415 }
1416
1417 static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) {
1418 assert(client);
1419 assert(client->request_sent);
1420 assert(lifetime > 0);
1421
1422 if (lifetime > 3)
1423 lifetime -= 3;
1424 else
1425 lifetime = 0;
1426
1427 return client->request_sent + (lifetime * USEC_PER_SEC * factor) +
1428 + (random_u32() & 0x1fffff);
1429 }
1430
1431 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1432 usec_t time_now;
1433 uint64_t lifetime_timeout;
1434 uint64_t t2_timeout;
1435 uint64_t t1_timeout;
1436 char time_string[FORMAT_TIMESPAN_MAX];
1437 int r;
1438
1439 assert(client);
1440 assert(client->event);
1441 assert(client->lease);
1442 assert(client->lease->lifetime);
1443
1444 /* don't set timers for infinite leases */
1445 if (client->lease->lifetime == 0xffffffff) {
1446 (void) event_source_disable(client->timeout_t1);
1447 (void) event_source_disable(client->timeout_t2);
1448 (void) event_source_disable(client->timeout_expire);
1449
1450 return 0;
1451 }
1452
1453 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1454 if (r < 0)
1455 return r;
1456 assert(client->request_sent <= time_now);
1457
1458 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1459 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1460 if (client->lease->t1 > 0 && client->lease->t2 > 0) {
1461 /* both T1 and T2 are given */
1462 if (client->lease->t1 < client->lease->t2 &&
1463 client->lease->t2 < client->lease->lifetime) {
1464 /* they are both valid */
1465 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1466 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1467 } else {
1468 /* discard both */
1469 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1470 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1471 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1472 client->lease->t1 = client->lease->lifetime / 2;
1473 }
1474 } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) {
1475 /* only T2 is given, and it is valid */
1476 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1477 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1478 client->lease->t1 = client->lease->lifetime / 2;
1479 if (t2_timeout <= t1_timeout) {
1480 /* the computed T1 would be invalid, so discard T2 */
1481 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1482 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1483 }
1484 } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) {
1485 /* only T1 is given, and it is valid */
1486 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1487 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1488 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1489 if (t2_timeout <= t1_timeout) {
1490 /* the computed T2 would be invalid, so discard T1 */
1491 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1492 client->lease->t2 = client->lease->lifetime / 2;
1493 }
1494 } else {
1495 /* fall back to the default timeouts */
1496 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1497 client->lease->t1 = client->lease->lifetime / 2;
1498 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1499 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1500 }
1501
1502 /* arm lifetime timeout */
1503 r = event_reset_time(client->event, &client->timeout_expire,
1504 clock_boottime_or_monotonic(),
1505 lifetime_timeout, 10 * USEC_PER_MSEC,
1506 client_timeout_expire, client,
1507 client->event_priority, "dhcp4-lifetime", true);
1508 if (r < 0)
1509 return r;
1510
1511 log_dhcp_client(client, "lease expires in %s",
1512 format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC));
1513
1514 /* don't arm earlier timeouts if this has already expired */
1515 if (lifetime_timeout <= time_now)
1516 return 0;
1517
1518 /* arm T2 timeout */
1519 r = event_reset_time(client->event, &client->timeout_t2,
1520 clock_boottime_or_monotonic(),
1521 t2_timeout, 10 * USEC_PER_MSEC,
1522 client_timeout_t2, client,
1523 client->event_priority, "dhcp4-t2-timeout", true);
1524 if (r < 0)
1525 return r;
1526
1527 log_dhcp_client(client, "T2 expires in %s",
1528 format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC));
1529
1530 /* don't arm earlier timeout if this has already expired */
1531 if (t2_timeout <= time_now)
1532 return 0;
1533
1534 /* arm T1 timeout */
1535 r = event_reset_time(client->event, &client->timeout_t1,
1536 clock_boottime_or_monotonic(),
1537 t1_timeout, 10 * USEC_PER_MSEC,
1538 client_timeout_t1, client,
1539 client->event_priority, "dhcp4-t1-timer", true);
1540 if (r < 0)
1541 return r;
1542
1543 log_dhcp_client(client, "T1 expires in %s",
1544 format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC));
1545
1546 return 0;
1547 }
1548
1549 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) {
1550 DHCP_CLIENT_DONT_DESTROY(client);
1551 char time_string[FORMAT_TIMESPAN_MAX];
1552 int r = 0, notify_event = 0;
1553
1554 assert(client);
1555 assert(client->event);
1556 assert(message);
1557
1558 switch (client->state) {
1559 case DHCP_STATE_SELECTING:
1560
1561 r = client_handle_offer(client, message, len);
1562 if (r >= 0) {
1563
1564 client->state = DHCP_STATE_REQUESTING;
1565 client->attempt = 0;
1566
1567 r = event_reset_time(client->event, &client->timeout_resend,
1568 clock_boottime_or_monotonic(),
1569 0, 0,
1570 client_timeout_resend, client,
1571 client->event_priority, "dhcp4-resend-timer", true);
1572 if (r < 0)
1573 goto error;
1574 } else if (r == -ENOMSG)
1575 /* invalid message, let's ignore it */
1576 return 0;
1577
1578 break;
1579
1580 case DHCP_STATE_REBOOTING:
1581 case DHCP_STATE_REQUESTING:
1582 case DHCP_STATE_RENEWING:
1583 case DHCP_STATE_REBINDING:
1584
1585 r = client_handle_ack(client, message, len);
1586 if (r >= 0) {
1587 client->start_delay = 0;
1588 (void) event_source_disable(client->timeout_resend);
1589 client->receive_message =
1590 sd_event_source_unref(client->receive_message);
1591 client->fd = asynchronous_close(client->fd);
1592
1593 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1594 DHCP_STATE_REBOOTING))
1595 notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1596 else if (r != SD_DHCP_CLIENT_EVENT_IP_ACQUIRE)
1597 notify_event = r;
1598
1599 client->state = DHCP_STATE_BOUND;
1600 client->attempt = 0;
1601
1602 client->last_addr = client->lease->address;
1603
1604 r = client_set_lease_timeouts(client);
1605 if (r < 0) {
1606 log_dhcp_client(client, "could not set lease timeouts");
1607 goto error;
1608 }
1609
1610 r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port);
1611 if (r < 0) {
1612 log_dhcp_client(client, "could not bind UDP socket");
1613 goto error;
1614 }
1615
1616 client->fd = r;
1617
1618 client_initialize_io_events(client, client_receive_message_udp);
1619
1620 if (notify_event) {
1621 client_notify(client, notify_event);
1622 if (client->state == DHCP_STATE_STOPPED)
1623 return 0;
1624 }
1625
1626 } else if (r == -EADDRNOTAVAIL) {
1627 /* got a NAK, let's restart the client */
1628 client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
1629
1630 r = client_initialize(client);
1631 if (r < 0)
1632 goto error;
1633
1634 r = client_start_delayed(client);
1635 if (r < 0)
1636 goto error;
1637
1638 log_dhcp_client(client, "REBOOT in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX,
1639 client->start_delay, USEC_PER_SEC));
1640
1641 client->start_delay = CLAMP(client->start_delay * 2,
1642 RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC);
1643
1644 return 0;
1645 } else if (r == -ENOMSG)
1646 /* invalid message, let's ignore it */
1647 return 0;
1648
1649 break;
1650
1651 case DHCP_STATE_BOUND:
1652 r = client_handle_forcerenew(client, message, len);
1653 if (r >= 0) {
1654 r = client_timeout_t1(NULL, 0, client);
1655 if (r < 0)
1656 goto error;
1657 } else if (r == -ENOMSG)
1658 /* invalid message, let's ignore it */
1659 return 0;
1660
1661 break;
1662
1663 case DHCP_STATE_INIT:
1664 case DHCP_STATE_INIT_REBOOT:
1665
1666 break;
1667
1668 case DHCP_STATE_STOPPED:
1669 r = -EINVAL;
1670 goto error;
1671 }
1672
1673 error:
1674 if (r < 0)
1675 client_stop(client, r);
1676
1677 return r;
1678 }
1679
1680 static int client_receive_message_udp(
1681 sd_event_source *s,
1682 int fd,
1683 uint32_t revents,
1684 void *userdata) {
1685
1686 sd_dhcp_client *client = userdata;
1687 _cleanup_free_ DHCPMessage *message = NULL;
1688 const uint8_t *expected_chaddr = NULL;
1689 uint8_t expected_hlen = 0;
1690 ssize_t len, buflen;
1691
1692 assert(s);
1693 assert(client);
1694
1695 buflen = next_datagram_size_fd(fd);
1696 if (buflen == -ENETDOWN) {
1697 /* the link is down. Don't return an error or the I/O event
1698 source will be disconnected and we won't be able to receive
1699 packets again when the link comes back. */
1700 return 0;
1701 }
1702 if (buflen < 0)
1703 return buflen;
1704
1705 message = malloc0(buflen);
1706 if (!message)
1707 return -ENOMEM;
1708
1709 len = recv(fd, message, buflen, 0);
1710 if (len < 0) {
1711 /* see comment above for why we shouldn't error out on ENETDOWN. */
1712 if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN))
1713 return 0;
1714
1715 return log_dhcp_client_errno(client, errno,
1716 "Could not receive message from UDP socket: %m");
1717 }
1718 if ((size_t) len < sizeof(DHCPMessage)) {
1719 log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
1720 return 0;
1721 }
1722
1723 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1724 log_dhcp_client(client, "Not a DHCP message: ignoring");
1725 return 0;
1726 }
1727
1728 if (message->op != BOOTREPLY) {
1729 log_dhcp_client(client, "Not a BOOTREPLY message: ignoring");
1730 return 0;
1731 }
1732
1733 if (message->htype != client->arp_type) {
1734 log_dhcp_client(client, "Packet type does not match client type");
1735 return 0;
1736 }
1737
1738 if (client->arp_type == ARPHRD_ETHER) {
1739 expected_hlen = ETH_ALEN;
1740 expected_chaddr = &client->mac_addr[0];
1741 }
1742
1743 if (message->hlen != expected_hlen) {
1744 log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen);
1745 return 0;
1746 }
1747
1748 if (expected_hlen > 0 && memcmp(&message->chaddr[0], expected_chaddr, expected_hlen)) {
1749 log_dhcp_client(client, "Received chaddr does not match expected: ignoring");
1750 return 0;
1751 }
1752
1753 if (client->state != DHCP_STATE_BOUND &&
1754 be32toh(message->xid) != client->xid) {
1755 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1756 so ignore the xid in this case */
1757 log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring",
1758 be32toh(message->xid), client->xid);
1759 return 0;
1760 }
1761
1762 return client_handle_message(client, message, len);
1763 }
1764
1765 static int client_receive_message_raw(
1766 sd_event_source *s,
1767 int fd,
1768 uint32_t revents,
1769 void *userdata) {
1770
1771 sd_dhcp_client *client = userdata;
1772 _cleanup_free_ DHCPPacket *packet = NULL;
1773 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1774 struct iovec iov = {};
1775 struct msghdr msg = {
1776 .msg_iov = &iov,
1777 .msg_iovlen = 1,
1778 .msg_control = cmsgbuf,
1779 .msg_controllen = sizeof(cmsgbuf),
1780 };
1781 struct cmsghdr *cmsg;
1782 bool checksum = true;
1783 ssize_t buflen, len;
1784 int r;
1785
1786 assert(s);
1787 assert(client);
1788
1789 buflen = next_datagram_size_fd(fd);
1790 if (buflen == -ENETDOWN)
1791 return 0;
1792 if (buflen < 0)
1793 return buflen;
1794
1795 packet = malloc0(buflen);
1796 if (!packet)
1797 return -ENOMEM;
1798
1799 iov = IOVEC_MAKE(packet, buflen);
1800
1801 len = recvmsg(fd, &msg, 0);
1802 if (len < 0) {
1803 if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN))
1804 return 0;
1805
1806 return log_dhcp_client_errno(client, errno,
1807 "Could not receive message from raw socket: %m");
1808 } else if ((size_t)len < sizeof(DHCPPacket))
1809 return 0;
1810
1811 CMSG_FOREACH(cmsg, &msg)
1812 if (cmsg->cmsg_level == SOL_PACKET &&
1813 cmsg->cmsg_type == PACKET_AUXDATA &&
1814 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1815 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1816
1817 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1818 break;
1819 }
1820
1821 r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
1822 if (r < 0)
1823 return 0;
1824
1825 len -= DHCP_IP_UDP_SIZE;
1826
1827 return client_handle_message(client, &packet->dhcp, len);
1828 }
1829
1830 int sd_dhcp_client_start(sd_dhcp_client *client) {
1831 int r;
1832
1833 assert_return(client, -EINVAL);
1834
1835 r = client_initialize(client);
1836 if (r < 0)
1837 return r;
1838
1839 /* RFC7844 section 3.3:
1840 SHOULD perform a complete four-way handshake, starting with a
1841 DHCPDISCOVER, to obtain a new address lease. If the client can
1842 ascertain that this is exactly the same network to which it was
1843 previously connected, and if the link-layer address did not change,
1844 the client MAY issue a DHCPREQUEST to try to reclaim the current
1845 address. */
1846 if (client->last_addr && !client->anonymize)
1847 client->state = DHCP_STATE_INIT_REBOOT;
1848
1849 r = client_start(client);
1850 if (r >= 0)
1851 log_dhcp_client(client, "STARTED on ifindex %i", client->ifindex);
1852
1853 return r;
1854 }
1855
1856 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1857 DHCP_CLIENT_DONT_DESTROY(client);
1858
1859 assert_return(client, -EINVAL);
1860
1861 client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
1862 client->state = DHCP_STATE_STOPPED;
1863
1864 return 0;
1865 }
1866
1867 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) {
1868 int r;
1869
1870 assert_return(client, -EINVAL);
1871 assert_return(!client->event, -EBUSY);
1872
1873 if (event)
1874 client->event = sd_event_ref(event);
1875 else {
1876 r = sd_event_default(&client->event);
1877 if (r < 0)
1878 return 0;
1879 }
1880
1881 client->event_priority = priority;
1882
1883 return 0;
1884 }
1885
1886 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1887 assert_return(client, -EINVAL);
1888
1889 client->event = sd_event_unref(client->event);
1890
1891 return 0;
1892 }
1893
1894 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1895 assert_return(client, NULL);
1896
1897 return client->event;
1898 }
1899
1900 static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
1901 assert(client);
1902
1903 log_dhcp_client(client, "FREE");
1904
1905 client->timeout_resend = sd_event_source_unref(client->timeout_resend);
1906 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1907 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1908 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1909
1910 client_initialize(client);
1911
1912 sd_dhcp_client_detach_event(client);
1913
1914 sd_dhcp_lease_unref(client->lease);
1915
1916 free(client->req_opts);
1917 free(client->hostname);
1918 free(client->vendor_class_identifier);
1919 client->user_class = strv_free(client->user_class);
1920 return mfree(client);
1921 }
1922
1923 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
1924
1925 int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
1926 _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
1927
1928 assert_return(ret, -EINVAL);
1929
1930 client = new(sd_dhcp_client, 1);
1931 if (!client)
1932 return -ENOMEM;
1933
1934 *client = (sd_dhcp_client) {
1935 .n_ref = 1,
1936 .state = DHCP_STATE_INIT,
1937 .ifindex = -1,
1938 .fd = -1,
1939 .mtu = DHCP_DEFAULT_MIN_SIZE,
1940 .port = DHCP_PORT_CLIENT,
1941 .anonymize = !!anonymize,
1942 .max_attempts = (uint64_t) -1,
1943 };
1944 /* NOTE: this could be moved to a function. */
1945 if (anonymize) {
1946 client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize);
1947 client->req_opts = memdup(default_req_opts_anonymize, client->req_opts_size);
1948 } else {
1949 client->req_opts_size = ELEMENTSOF(default_req_opts);
1950 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1951 }
1952 if (!client->req_opts)
1953 return -ENOMEM;
1954
1955 *ret = TAKE_PTR(client);
1956
1957 return 0;
1958 }