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