]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-client.c
Merge pull request #1831 from keszybz/todo-trimming
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp-client.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <net/ethernet.h>
22 #include <net/if_arp.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/ioctl.h>
27 #include <linux/if_infiniband.h>
28
29 #include "sd-dhcp-client.h"
30
31 #include "alloc-util.h"
32 #include "async.h"
33 #include "dhcp-identifier.h"
34 #include "dhcp-internal.h"
35 #include "dhcp-lease-internal.h"
36 #include "dhcp-protocol.h"
37 #include "random-util.h"
38 #include "string-util.h"
39 #include "util.h"
40
41 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
42 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
43
44 struct sd_dhcp_client {
45 unsigned n_ref;
46
47 DHCPState state;
48 sd_event *event;
49 int event_priority;
50 sd_event_source *timeout_resend;
51 int index;
52 int fd;
53 union sockaddr_union link;
54 sd_event_source *receive_message;
55 bool request_broadcast;
56 uint8_t *req_opts;
57 size_t req_opts_allocated;
58 size_t req_opts_size;
59 be32_t last_addr;
60 uint8_t mac_addr[MAX_MAC_ADDR_LEN];
61 size_t mac_addr_len;
62 uint16_t arp_type;
63 struct {
64 uint8_t type;
65 union {
66 struct {
67 /* 0: Generic (non-LL) (RFC 2132) */
68 uint8_t data[MAX_CLIENT_ID_LEN];
69 } _packed_ gen;
70 struct {
71 /* 1: Ethernet Link-Layer (RFC 2132) */
72 uint8_t haddr[ETH_ALEN];
73 } _packed_ eth;
74 struct {
75 /* 2 - 254: ARP/Link-Layer (RFC 2132) */
76 uint8_t haddr[0];
77 } _packed_ ll;
78 struct {
79 /* 255: Node-specific (RFC 4361) */
80 uint32_t iaid;
81 struct duid duid;
82 } _packed_ ns;
83 struct {
84 uint8_t data[MAX_CLIENT_ID_LEN];
85 } _packed_ raw;
86 };
87 } _packed_ client_id;
88 size_t client_id_len;
89 char *hostname;
90 char *vendor_class_identifier;
91 uint32_t mtu;
92 uint32_t xid;
93 usec_t start_time;
94 unsigned int attempt;
95 usec_t request_sent;
96 sd_event_source *timeout_t1;
97 sd_event_source *timeout_t2;
98 sd_event_source *timeout_expire;
99 sd_dhcp_client_cb_t cb;
100 void *userdata;
101 sd_dhcp_lease *lease;
102 };
103
104 static const uint8_t default_req_opts[] = {
105 DHCP_OPTION_SUBNET_MASK,
106 DHCP_OPTION_ROUTER,
107 DHCP_OPTION_HOST_NAME,
108 DHCP_OPTION_DOMAIN_NAME,
109 DHCP_OPTION_DOMAIN_NAME_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, SD_DHCP_CLIENT_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, SD_DHCP_CLIENT_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 = 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 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 == SD_DHCP_CLIENT_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, SD_DHCP_CLIENT_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 lease->address = offer->yiaddr;
1058
1059 if (lease->address == 0 ||
1060 lease->server_address == 0 ||
1061 lease->lifetime == 0) {
1062 log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring");
1063 return -ENOMSG;
1064 }
1065
1066 if (!lease->have_subnet_mask) {
1067 r = dhcp_lease_set_default_subnet_mask(lease);
1068 if (r < 0) {
1069 log_dhcp_client(client, "received lease lacks subnet "
1070 "mask, and a fallback one can not be "
1071 "generated, ignoring");
1072 return -ENOMSG;
1073 }
1074 }
1075
1076 sd_dhcp_lease_unref(client->lease);
1077 client->lease = lease;
1078 lease = NULL;
1079
1080 log_dhcp_client(client, "OFFER");
1081
1082 return 0;
1083 }
1084
1085 static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
1086 size_t len) {
1087 int r;
1088
1089 r = dhcp_option_parse(force, len, NULL, NULL);
1090 if (r != DHCP_FORCERENEW)
1091 return -ENOMSG;
1092
1093 log_dhcp_client(client, "FORCERENEW");
1094
1095 return 0;
1096 }
1097
1098 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
1099 size_t len) {
1100 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
1101 int r;
1102
1103 r = dhcp_lease_new(&lease);
1104 if (r < 0)
1105 return r;
1106
1107 if (client->client_id_len) {
1108 r = dhcp_lease_set_client_id(lease,
1109 (uint8_t *) &client->client_id,
1110 client->client_id_len);
1111 if (r < 0)
1112 return r;
1113 }
1114
1115 r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
1116 if (r == DHCP_NAK) {
1117 log_dhcp_client(client, "NAK");
1118 return -EADDRNOTAVAIL;
1119 }
1120
1121 if (r != DHCP_ACK) {
1122 log_dhcp_client(client, "received message was not an ACK, ignoring");
1123 return -ENOMSG;
1124 }
1125
1126 lease->next_server = ack->siaddr;
1127
1128 lease->address = ack->yiaddr;
1129
1130 if (lease->address == INADDR_ANY ||
1131 lease->server_address == INADDR_ANY ||
1132 lease->lifetime == 0) {
1133 log_dhcp_client(client, "received lease lacks address, server "
1134 "address or lease lifetime, ignoring");
1135 return -ENOMSG;
1136 }
1137
1138 if (lease->subnet_mask == INADDR_ANY) {
1139 r = dhcp_lease_set_default_subnet_mask(lease);
1140 if (r < 0) {
1141 log_dhcp_client(client, "received lease lacks subnet "
1142 "mask, and a fallback one can not be "
1143 "generated, ignoring");
1144 return -ENOMSG;
1145 }
1146 }
1147
1148 r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1149 if (client->lease) {
1150 if (client->lease->address != lease->address ||
1151 client->lease->subnet_mask != lease->subnet_mask ||
1152 client->lease->router != lease->router) {
1153 r = SD_DHCP_CLIENT_EVENT_IP_CHANGE;
1154 } else
1155 r = SD_DHCP_CLIENT_EVENT_RENEW;
1156
1157 client->lease = sd_dhcp_lease_unref(client->lease);
1158 }
1159
1160 client->lease = lease;
1161 lease = NULL;
1162
1163 log_dhcp_client(client, "ACK");
1164
1165 return r;
1166 }
1167
1168 static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) {
1169 assert(client);
1170 assert(client->request_sent);
1171 assert(lifetime > 0);
1172
1173 if (lifetime > 3)
1174 lifetime -= 3;
1175 else
1176 lifetime = 0;
1177
1178 return client->request_sent + (lifetime * USEC_PER_SEC * factor) +
1179 + (random_u32() & 0x1fffff);
1180 }
1181
1182 static int client_set_lease_timeouts(sd_dhcp_client *client) {
1183 usec_t time_now;
1184 uint64_t lifetime_timeout;
1185 uint64_t t2_timeout;
1186 uint64_t t1_timeout;
1187 char time_string[FORMAT_TIMESPAN_MAX];
1188 int r;
1189
1190 assert(client);
1191 assert(client->event);
1192 assert(client->lease);
1193 assert(client->lease->lifetime);
1194
1195 client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
1196 client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
1197 client->timeout_expire = sd_event_source_unref(client->timeout_expire);
1198
1199 /* don't set timers for infinite leases */
1200 if (client->lease->lifetime == 0xffffffff)
1201 return 0;
1202
1203 r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
1204 if (r < 0)
1205 return r;
1206 assert(client->request_sent <= time_now);
1207
1208 /* convert the various timeouts from relative (secs) to absolute (usecs) */
1209 lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
1210 if (client->lease->t1 > 0 && client->lease->t2 > 0) {
1211 /* both T1 and T2 are given */
1212 if (client->lease->t1 < client->lease->t2 &&
1213 client->lease->t2 < client->lease->lifetime) {
1214 /* they are both valid */
1215 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1216 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1217 } else {
1218 /* discard both */
1219 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1220 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1221 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1222 client->lease->t1 = client->lease->lifetime / 2;
1223 }
1224 } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) {
1225 /* only T2 is given, and it is valid */
1226 t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
1227 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1228 client->lease->t1 = client->lease->lifetime / 2;
1229 if (t2_timeout <= t1_timeout) {
1230 /* the computed T1 would be invalid, so discard T2 */
1231 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1232 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1233 }
1234 } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) {
1235 /* only T1 is given, and it is valid */
1236 t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
1237 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1238 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1239 if (t2_timeout <= t1_timeout) {
1240 /* the computed T2 would be invalid, so discard T1 */
1241 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1242 client->lease->t2 = client->lease->lifetime / 2;
1243 }
1244 } else {
1245 /* fall back to the default timeouts */
1246 t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
1247 client->lease->t1 = client->lease->lifetime / 2;
1248 t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
1249 client->lease->t2 = (client->lease->lifetime * 7) / 8;
1250 }
1251
1252 /* arm lifetime timeout */
1253 r = sd_event_add_time(client->event, &client->timeout_expire,
1254 clock_boottime_or_monotonic(),
1255 lifetime_timeout, 10 * USEC_PER_MSEC,
1256 client_timeout_expire, client);
1257 if (r < 0)
1258 return r;
1259
1260 r = sd_event_source_set_priority(client->timeout_expire,
1261 client->event_priority);
1262 if (r < 0)
1263 return r;
1264
1265 r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
1266 if (r < 0)
1267 return r;
1268
1269 log_dhcp_client(client, "lease expires in %s",
1270 format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC));
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, t2_timeout - time_now, USEC_PER_SEC));
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, t1_timeout - time_now, USEC_PER_SEC));
1322
1323 return 0;
1324 }
1325
1326 static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
1327 int len) {
1328 DHCP_CLIENT_DONT_DESTROY(client);
1329 int r = 0, notify_event = 0;
1330
1331 assert(client);
1332 assert(client->event);
1333 assert(message);
1334
1335 switch (client->state) {
1336 case DHCP_STATE_SELECTING:
1337
1338 r = client_handle_offer(client, message, len);
1339 if (r >= 0) {
1340
1341 client->timeout_resend =
1342 sd_event_source_unref(client->timeout_resend);
1343
1344 client->state = DHCP_STATE_REQUESTING;
1345 client->attempt = 1;
1346
1347 r = sd_event_add_time(client->event,
1348 &client->timeout_resend,
1349 clock_boottime_or_monotonic(),
1350 0, 0,
1351 client_timeout_resend, client);
1352 if (r < 0)
1353 goto error;
1354
1355 r = sd_event_source_set_priority(client->timeout_resend,
1356 client->event_priority);
1357 if (r < 0)
1358 goto error;
1359
1360 r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
1361 if (r < 0)
1362 goto error;
1363 } else if (r == -ENOMSG)
1364 /* invalid message, let's ignore it */
1365 return 0;
1366
1367 break;
1368
1369 case DHCP_STATE_REBOOTING:
1370 case DHCP_STATE_REQUESTING:
1371 case DHCP_STATE_RENEWING:
1372 case DHCP_STATE_REBINDING:
1373
1374 r = client_handle_ack(client, message, len);
1375 if (r >= 0) {
1376 client->timeout_resend =
1377 sd_event_source_unref(client->timeout_resend);
1378 client->receive_message =
1379 sd_event_source_unref(client->receive_message);
1380 client->fd = asynchronous_close(client->fd);
1381
1382 if (IN_SET(client->state, DHCP_STATE_REQUESTING,
1383 DHCP_STATE_REBOOTING))
1384 notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
1385 else if (r != SD_DHCP_CLIENT_EVENT_IP_ACQUIRE)
1386 notify_event = r;
1387
1388 client->state = DHCP_STATE_BOUND;
1389 client->attempt = 1;
1390
1391 client->last_addr = client->lease->address;
1392
1393 r = client_set_lease_timeouts(client);
1394 if (r < 0) {
1395 log_dhcp_client(client, "could not set lease timeouts");
1396 goto error;
1397 }
1398
1399 r = dhcp_network_bind_udp_socket(client->lease->address,
1400 DHCP_PORT_CLIENT);
1401 if (r < 0) {
1402 log_dhcp_client(client, "could not bind UDP socket");
1403 goto error;
1404 }
1405
1406 client->fd = r;
1407
1408 client_initialize_io_events(client, client_receive_message_udp);
1409
1410 if (notify_event) {
1411 client_notify(client, notify_event);
1412 if (client->state == DHCP_STATE_STOPPED)
1413 return 0;
1414 }
1415
1416 } else if (r == -EADDRNOTAVAIL) {
1417 /* got a NAK, let's restart the client */
1418 client->timeout_resend =
1419 sd_event_source_unref(client->timeout_resend);
1420
1421 r = client_initialize(client);
1422 if (r < 0)
1423 goto error;
1424
1425 r = client_start(client);
1426 if (r < 0)
1427 goto error;
1428
1429 log_dhcp_client(client, "REBOOTED");
1430
1431 return 0;
1432 } else if (r == -ENOMSG)
1433 /* invalid message, let's ignore it */
1434 return 0;
1435
1436 break;
1437
1438 case DHCP_STATE_BOUND:
1439 r = client_handle_forcerenew(client, message, len);
1440 if (r >= 0) {
1441 r = client_timeout_t1(NULL, 0, client);
1442 if (r < 0)
1443 goto error;
1444 } else if (r == -ENOMSG)
1445 /* invalid message, let's ignore it */
1446 return 0;
1447
1448 break;
1449
1450 case DHCP_STATE_INIT:
1451 case DHCP_STATE_INIT_REBOOT:
1452
1453 break;
1454
1455 case DHCP_STATE_STOPPED:
1456 r = -EINVAL;
1457 goto error;
1458 }
1459
1460 error:
1461 if (r < 0)
1462 client_stop(client, r);
1463
1464 return r;
1465 }
1466
1467 static int client_receive_message_udp(sd_event_source *s, int fd,
1468 uint32_t revents, void *userdata) {
1469 sd_dhcp_client *client = userdata;
1470 _cleanup_free_ DHCPMessage *message = NULL;
1471 int buflen = 0, len, r;
1472 const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
1473 const struct ether_addr *expected_chaddr = NULL;
1474 uint8_t expected_hlen = 0;
1475
1476 assert(s);
1477 assert(client);
1478
1479 r = ioctl(fd, FIONREAD, &buflen);
1480 if (r < 0)
1481 return r;
1482
1483 if (buflen < 0)
1484 /* this can't be right */
1485 return -EIO;
1486
1487 message = malloc0(buflen);
1488 if (!message)
1489 return -ENOMEM;
1490
1491 len = read(fd, message, buflen);
1492 if (len < 0) {
1493 log_dhcp_client(client, "could not receive message from UDP "
1494 "socket: %m");
1495 return 0;
1496 } else if ((size_t)len < sizeof(DHCPMessage)) {
1497 log_dhcp_client(client, "too small to be a DHCP message: ignoring");
1498 return 0;
1499 }
1500
1501 if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
1502 log_dhcp_client(client, "not a DHCP message: ignoring");
1503 return 0;
1504 }
1505
1506 if (message->op != BOOTREPLY) {
1507 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
1508 return 0;
1509 }
1510
1511 if (message->htype != client->arp_type) {
1512 log_dhcp_client(client, "packet type does not match client type");
1513 return 0;
1514 }
1515
1516 if (client->arp_type == ARPHRD_ETHER) {
1517 expected_hlen = ETH_ALEN;
1518 expected_chaddr = (const struct ether_addr *) &client->mac_addr;
1519 } else {
1520 /* Non-Ethernet links expect zero chaddr */
1521 expected_hlen = 0;
1522 expected_chaddr = &zero_mac;
1523 }
1524
1525 if (message->hlen != expected_hlen) {
1526 log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
1527 return 0;
1528 }
1529
1530 if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
1531 log_dhcp_client(client, "received chaddr does not match "
1532 "expected: ignoring");
1533 return 0;
1534 }
1535
1536 if (client->state != DHCP_STATE_BOUND &&
1537 be32toh(message->xid) != client->xid) {
1538 /* in BOUND state, we may receive FORCERENEW with xid set by server,
1539 so ignore the xid in this case */
1540 log_dhcp_client(client, "received xid (%u) does not match "
1541 "expected (%u): ignoring",
1542 be32toh(message->xid), client->xid);
1543 return 0;
1544 }
1545
1546 return client_handle_message(client, message, len);
1547 }
1548
1549 static int client_receive_message_raw(sd_event_source *s, int fd,
1550 uint32_t revents, void *userdata) {
1551 sd_dhcp_client *client = userdata;
1552 _cleanup_free_ DHCPPacket *packet = NULL;
1553 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1554 struct iovec iov = {};
1555 struct msghdr msg = {
1556 .msg_iov = &iov,
1557 .msg_iovlen = 1,
1558 .msg_control = cmsgbuf,
1559 .msg_controllen = sizeof(cmsgbuf),
1560 };
1561 struct cmsghdr *cmsg;
1562 bool checksum = true;
1563 int buflen = 0, len, r;
1564
1565 assert(s);
1566 assert(client);
1567
1568 r = ioctl(fd, FIONREAD, &buflen);
1569 if (r < 0)
1570 return r;
1571
1572 if (buflen < 0)
1573 /* this can't be right */
1574 return -EIO;
1575
1576 packet = malloc0(buflen);
1577 if (!packet)
1578 return -ENOMEM;
1579
1580 iov.iov_base = packet;
1581 iov.iov_len = buflen;
1582
1583 len = recvmsg(fd, &msg, 0);
1584 if (len < 0) {
1585 log_dhcp_client(client, "could not receive message from raw "
1586 "socket: %m");
1587 return 0;
1588 } else if ((size_t)len < sizeof(DHCPPacket))
1589 return 0;
1590
1591 CMSG_FOREACH(cmsg, &msg) {
1592 if (cmsg->cmsg_level == SOL_PACKET &&
1593 cmsg->cmsg_type == PACKET_AUXDATA &&
1594 cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) {
1595 struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg);
1596
1597 checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
1598 break;
1599 }
1600 }
1601
1602 r = dhcp_packet_verify_headers(packet, len, checksum);
1603 if (r < 0)
1604 return 0;
1605
1606 len -= DHCP_IP_UDP_SIZE;
1607
1608 return client_handle_message(client, &packet->dhcp, len);
1609 }
1610
1611 int sd_dhcp_client_start(sd_dhcp_client *client) {
1612 int r;
1613
1614 assert_return(client, -EINVAL);
1615
1616 r = client_initialize(client);
1617 if (r < 0)
1618 return r;
1619
1620 if (client->last_addr)
1621 client->state = DHCP_STATE_INIT_REBOOT;
1622
1623 r = client_start(client);
1624 if (r >= 0)
1625 log_dhcp_client(client, "STARTED on ifindex %i", client->index);
1626
1627 return r;
1628 }
1629
1630 int sd_dhcp_client_stop(sd_dhcp_client *client) {
1631 DHCP_CLIENT_DONT_DESTROY(client);
1632
1633 assert_return(client, -EINVAL);
1634
1635 client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
1636 client->state = DHCP_STATE_STOPPED;
1637
1638 return 0;
1639 }
1640
1641 int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event,
1642 int priority) {
1643 int r;
1644
1645 assert_return(client, -EINVAL);
1646 assert_return(!client->event, -EBUSY);
1647
1648 if (event)
1649 client->event = sd_event_ref(event);
1650 else {
1651 r = sd_event_default(&client->event);
1652 if (r < 0)
1653 return 0;
1654 }
1655
1656 client->event_priority = priority;
1657
1658 return 0;
1659 }
1660
1661 int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
1662 assert_return(client, -EINVAL);
1663
1664 client->event = sd_event_unref(client->event);
1665
1666 return 0;
1667 }
1668
1669 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
1670 if (!client)
1671 return NULL;
1672
1673 return client->event;
1674 }
1675
1676 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
1677
1678 if (!client)
1679 return NULL;
1680
1681 assert(client->n_ref >= 1);
1682 client->n_ref++;
1683
1684 return client;
1685 }
1686
1687 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
1688
1689 if (!client)
1690 return NULL;
1691
1692 assert(client->n_ref >= 1);
1693 client->n_ref--;
1694
1695 if (client->n_ref > 0)
1696 return NULL;
1697
1698 log_dhcp_client(client, "FREE");
1699
1700 client_initialize(client);
1701
1702 client->receive_message = sd_event_source_unref(client->receive_message);
1703
1704 sd_dhcp_client_detach_event(client);
1705
1706 sd_dhcp_lease_unref(client->lease);
1707
1708 free(client->req_opts);
1709 free(client->hostname);
1710 free(client->vendor_class_identifier);
1711 free(client);
1712
1713 return NULL;
1714 }
1715
1716 int sd_dhcp_client_new(sd_dhcp_client **ret) {
1717 _cleanup_dhcp_client_unref_ sd_dhcp_client *client = NULL;
1718
1719 assert_return(ret, -EINVAL);
1720
1721 client = new0(sd_dhcp_client, 1);
1722 if (!client)
1723 return -ENOMEM;
1724
1725 client->n_ref = 1;
1726 client->state = DHCP_STATE_INIT;
1727 client->index = -1;
1728 client->fd = -1;
1729 client->attempt = 1;
1730 client->mtu = DHCP_DEFAULT_MIN_SIZE;
1731
1732 client->req_opts_size = ELEMENTSOF(default_req_opts);
1733
1734 client->req_opts = memdup(default_req_opts, client->req_opts_size);
1735 if (!client->req_opts)
1736 return -ENOMEM;
1737
1738 *ret = client;
1739 client = NULL;
1740
1741 return 0;
1742 }