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