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