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