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