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