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