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