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