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