]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-server.c
Merge pull request #6975 from sourcejedi/logind_pid_0_v2
[thirdparty/systemd.git] / src / libsystemd-network / sd-dhcp-server.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5 Copyright (C) 2014 Tom Gundersen
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <sys/ioctl.h>
22
23 #include "sd-dhcp-server.h"
24
25 #include "alloc-util.h"
26 #include "dhcp-internal.h"
27 #include "dhcp-server-internal.h"
28 #include "fd-util.h"
29 #include "in-addr-util.h"
30 #include "siphash24.h"
31 #include "string-util.h"
32 #include "unaligned.h"
33
34 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
35 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
36
37 static void dhcp_lease_free(DHCPLease *lease) {
38 if (!lease)
39 return;
40
41 free(lease->client_id.data);
42 free(lease);
43 }
44
45 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
46 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
47 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
48 * accidentally hand it out */
49 int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size) {
50 struct in_addr netmask_addr;
51 be32_t netmask;
52 uint32_t server_off, broadcast_off, size_max;
53
54 assert_return(server, -EINVAL);
55 assert_return(address, -EINVAL);
56 assert_return(address->s_addr != INADDR_ANY, -EINVAL);
57 assert_return(prefixlen <= 32, -ERANGE);
58
59 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr, prefixlen));
60 netmask = netmask_addr.s_addr;
61
62 server_off = be32toh(address->s_addr & ~netmask);
63 broadcast_off = be32toh(~netmask);
64
65 /* the server address cannot be the subnet address */
66 assert_return(server_off != 0, -ERANGE);
67
68 /* nor the broadcast address */
69 assert_return(server_off != broadcast_off, -ERANGE);
70
71 /* 0 offset means we should set a default, we skip the first (subnet) address
72 and take the next one */
73 if (offset == 0)
74 offset = 1;
75
76 size_max = (broadcast_off + 1) /* the number of addresses in the subnet */
77 - offset /* exclude the addresses before the offset */
78 - 1; /* exclude the last (broadcast) address */
79
80 /* The pool must contain at least one address */
81 assert_return(size_max >= 1, -ERANGE);
82
83 if (size != 0)
84 assert_return(size <= size_max, -ERANGE);
85 else
86 size = size_max;
87
88 if (server->address != address->s_addr || server->netmask != netmask || server->pool_size != size || server->pool_offset != offset) {
89 DHCPLease *lease;
90
91 free(server->bound_leases);
92 server->bound_leases = new0(DHCPLease*, size);
93 if (!server->bound_leases)
94 return -ENOMEM;
95
96 server->pool_offset = offset;
97 server->pool_size = size;
98
99 server->address = address->s_addr;
100 server->netmask = netmask;
101 server->subnet = address->s_addr & netmask;
102
103 if (server_off >= offset && server_off - offset < size)
104 server->bound_leases[server_off - offset] = &server->invalid_lease;
105
106 /* Drop any leases associated with the old address range */
107 while ((lease = hashmap_steal_first(server->leases_by_client_id)))
108 dhcp_lease_free(lease);
109 }
110
111 return 0;
112 }
113
114 int sd_dhcp_server_is_running(sd_dhcp_server *server) {
115 assert_return(server, false);
116
117 return !!server->receive_message;
118 }
119
120 sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) {
121
122 if (!server)
123 return NULL;
124
125 assert(server->n_ref >= 1);
126 server->n_ref++;
127
128 return server;
129 }
130
131 void client_id_hash_func(const void *p, struct siphash *state) {
132 const DHCPClientId *id = p;
133
134 assert(id);
135 assert(id->length);
136 assert(id->data);
137
138 siphash24_compress(&id->length, sizeof(id->length), state);
139 siphash24_compress(id->data, id->length, state);
140 }
141
142 int client_id_compare_func(const void *_a, const void *_b) {
143 const DHCPClientId *a, *b;
144
145 a = _a;
146 b = _b;
147
148 assert(!a->length || a->data);
149 assert(!b->length || b->data);
150
151 if (a->length != b->length)
152 return a->length < b->length ? -1 : 1;
153
154 return memcmp(a->data, b->data, a->length);
155 }
156
157 static const struct hash_ops client_id_hash_ops = {
158 .hash = client_id_hash_func,
159 .compare = client_id_compare_func
160 };
161
162 sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
163 DHCPLease *lease;
164
165 if (!server)
166 return NULL;
167
168 assert(server->n_ref >= 1);
169 server->n_ref--;
170
171 if (server->n_ref > 0)
172 return NULL;
173
174 log_dhcp_server(server, "UNREF");
175
176 sd_dhcp_server_stop(server);
177
178 sd_event_unref(server->event);
179
180 free(server->timezone);
181 free(server->dns);
182 free(server->ntp);
183
184 while ((lease = hashmap_steal_first(server->leases_by_client_id)))
185 dhcp_lease_free(lease);
186 hashmap_free(server->leases_by_client_id);
187
188 free(server->bound_leases);
189 return mfree(server);
190 }
191
192 int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
193 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
194
195 assert_return(ret, -EINVAL);
196 assert_return(ifindex > 0, -EINVAL);
197
198 server = new0(sd_dhcp_server, 1);
199 if (!server)
200 return -ENOMEM;
201
202 server->n_ref = 1;
203 server->fd_raw = -1;
204 server->fd = -1;
205 server->address = htobe32(INADDR_ANY);
206 server->netmask = htobe32(INADDR_ANY);
207 server->ifindex = ifindex;
208
209 server->leases_by_client_id = hashmap_new(&client_id_hash_ops);
210 if (!server->leases_by_client_id)
211 return -ENOMEM;
212
213 server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC);
214 server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC);
215
216 *ret = server;
217 server = NULL;
218
219 return 0;
220 }
221
222 int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int64_t priority) {
223 int r;
224
225 assert_return(server, -EINVAL);
226 assert_return(!server->event, -EBUSY);
227
228 if (event)
229 server->event = sd_event_ref(event);
230 else {
231 r = sd_event_default(&server->event);
232 if (r < 0)
233 return r;
234 }
235
236 server->event_priority = priority;
237
238 return 0;
239 }
240
241 int sd_dhcp_server_detach_event(sd_dhcp_server *server) {
242 assert_return(server, -EINVAL);
243
244 server->event = sd_event_unref(server->event);
245
246 return 0;
247 }
248
249 sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) {
250 assert_return(server, NULL);
251
252 return server->event;
253 }
254
255 int sd_dhcp_server_stop(sd_dhcp_server *server) {
256 assert_return(server, -EINVAL);
257
258 server->receive_message =
259 sd_event_source_unref(server->receive_message);
260
261 server->fd_raw = safe_close(server->fd_raw);
262 server->fd = safe_close(server->fd);
263
264 log_dhcp_server(server, "STOPPED");
265
266 return 0;
267 }
268
269 static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,
270 DHCPPacket *packet, size_t len) {
271 union sockaddr_union link = {
272 .ll.sll_family = AF_PACKET,
273 .ll.sll_protocol = htobe16(ETH_P_IP),
274 .ll.sll_ifindex = server->ifindex,
275 .ll.sll_halen = ETH_ALEN,
276 };
277
278 assert(server);
279 assert(server->ifindex > 0);
280 assert(server->address);
281 assert(packet);
282 assert(len > sizeof(DHCPPacket));
283
284 memcpy(&link.ll.sll_addr, &packet->dhcp.chaddr, ETH_ALEN);
285
286 dhcp_packet_append_ip_headers(packet, server->address, DHCP_PORT_SERVER,
287 packet->dhcp.yiaddr,
288 DHCP_PORT_CLIENT, len);
289
290 return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len);
291 }
292
293 static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
294 uint16_t destination_port,
295 DHCPMessage *message, size_t len) {
296 union sockaddr_union dest = {
297 .in.sin_family = AF_INET,
298 .in.sin_port = htobe16(destination_port),
299 .in.sin_addr.s_addr = destination,
300 };
301 struct iovec iov = {
302 .iov_base = message,
303 .iov_len = len,
304 };
305 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))] = {};
306 struct msghdr msg = {
307 .msg_name = &dest,
308 .msg_namelen = sizeof(dest.in),
309 .msg_iov = &iov,
310 .msg_iovlen = 1,
311 .msg_control = cmsgbuf,
312 .msg_controllen = sizeof(cmsgbuf),
313 };
314 struct cmsghdr *cmsg;
315 struct in_pktinfo *pktinfo;
316 int r;
317
318 assert(server);
319 assert(server->fd > 0);
320 assert(message);
321 assert(len > sizeof(DHCPMessage));
322
323 cmsg = CMSG_FIRSTHDR(&msg);
324 assert(cmsg);
325
326 cmsg->cmsg_level = IPPROTO_IP;
327 cmsg->cmsg_type = IP_PKTINFO;
328 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
329
330 /* we attach source interface and address info to the message
331 rather than binding the socket. This will be mostly useful
332 when we gain support for arbitrary number of server addresses
333 */
334 pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
335 assert(pktinfo);
336
337 pktinfo->ipi_ifindex = server->ifindex;
338 pktinfo->ipi_spec_dst.s_addr = server->address;
339
340 r = sendmsg(server->fd, &msg, 0);
341 if (r < 0)
342 return -errno;
343
344 return 0;
345 }
346
347 static bool requested_broadcast(DHCPRequest *req) {
348 assert(req);
349
350 return req->message->flags & htobe16(0x8000);
351 }
352
353 int dhcp_server_send_packet(sd_dhcp_server *server,
354 DHCPRequest *req, DHCPPacket *packet,
355 int type, size_t optoffset) {
356 be32_t destination = INADDR_ANY;
357 uint16_t destination_port = DHCP_PORT_CLIENT;
358 int r;
359
360 assert(server);
361 assert(req);
362 assert(req->max_optlen);
363 assert(optoffset <= req->max_optlen);
364 assert(packet);
365
366 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
367 SD_DHCP_OPTION_SERVER_IDENTIFIER,
368 4, &server->address);
369 if (r < 0)
370 return r;
371
372 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
373 SD_DHCP_OPTION_END, 0, NULL);
374 if (r < 0)
375 return r;
376
377 /* RFC 2131 Section 4.1
378
379 If the ’giaddr’ field in a DHCP message from a client is non-zero,
380 the server sends any return messages to the ’DHCP server’ port on the
381 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
382 field is zero and the ’ciaddr’ field is nonzero, then the server
383 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
384 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
385 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
386 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
387 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
388 messages to the client’s hardware address and ’yiaddr’ address. In
389 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
390 messages to 0xffffffff.
391
392 Section 4.3.2
393
394 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
395 different subnet. The server MUST set the broadcast bit in the
396 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
397 client, because the client may not have a correct network address
398 or subnet mask, and the client may not be answering ARP requests.
399 */
400 if (req->message->giaddr) {
401 destination = req->message->giaddr;
402 destination_port = DHCP_PORT_SERVER;
403 if (type == DHCP_NAK)
404 packet->dhcp.flags = htobe16(0x8000);
405 } else if (req->message->ciaddr && type != DHCP_NAK)
406 destination = req->message->ciaddr;
407
408 if (destination != INADDR_ANY)
409 return dhcp_server_send_udp(server, destination,
410 destination_port, &packet->dhcp,
411 sizeof(DHCPMessage) + optoffset);
412 else if (requested_broadcast(req) || type == DHCP_NAK)
413 return dhcp_server_send_udp(server, INADDR_BROADCAST,
414 destination_port, &packet->dhcp,
415 sizeof(DHCPMessage) + optoffset);
416 else
417 /* we cannot send UDP packet to specific MAC address when the
418 address is not yet configured, so must fall back to raw
419 packets */
420 return dhcp_server_send_unicast_raw(server, packet,
421 sizeof(DHCPPacket) + optoffset);
422 }
423
424 static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
425 uint8_t type, size_t *_optoffset,
426 DHCPRequest *req) {
427 _cleanup_free_ DHCPPacket *packet = NULL;
428 size_t optoffset = 0;
429 int r;
430
431 assert(server);
432 assert(ret);
433 assert(_optoffset);
434 assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK));
435
436 packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
437 if (!packet)
438 return -ENOMEM;
439
440 r = dhcp_message_init(&packet->dhcp, BOOTREPLY,
441 be32toh(req->message->xid), type, ARPHRD_ETHER,
442 req->max_optlen, &optoffset);
443 if (r < 0)
444 return r;
445
446 packet->dhcp.flags = req->message->flags;
447 packet->dhcp.giaddr = req->message->giaddr;
448 memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN);
449
450 *_optoffset = optoffset;
451 *ret = packet;
452 packet = NULL;
453
454 return 0;
455 }
456
457 static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req,
458 be32_t address) {
459 _cleanup_free_ DHCPPacket *packet = NULL;
460 size_t offset;
461 be32_t lease_time;
462 int r;
463
464 r = server_message_init(server, &packet, DHCP_OFFER, &offset, req);
465 if (r < 0)
466 return r;
467
468 packet->dhcp.yiaddr = address;
469
470 lease_time = htobe32(req->lifetime);
471 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
472 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
473 &lease_time);
474 if (r < 0)
475 return r;
476
477 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
478 SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
479 if (r < 0)
480 return r;
481
482 if (server->emit_router) {
483 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
484 SD_DHCP_OPTION_ROUTER, 4, &server->address);
485 if (r < 0)
486 return r;
487 }
488
489 r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset);
490 if (r < 0)
491 return r;
492
493 return 0;
494 }
495
496 static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
497 be32_t address) {
498 _cleanup_free_ DHCPPacket *packet = NULL;
499 size_t offset;
500 be32_t lease_time;
501 int r;
502
503 r = server_message_init(server, &packet, DHCP_ACK, &offset, req);
504 if (r < 0)
505 return r;
506
507 packet->dhcp.yiaddr = address;
508
509 lease_time = htobe32(req->lifetime);
510 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
511 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
512 &lease_time);
513 if (r < 0)
514 return r;
515
516 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
517 SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
518 if (r < 0)
519 return r;
520
521 if (server->emit_router) {
522 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
523 SD_DHCP_OPTION_ROUTER, 4, &server->address);
524 if (r < 0)
525 return r;
526 }
527
528 if (server->n_dns > 0) {
529 r = dhcp_option_append(
530 &packet->dhcp, req->max_optlen, &offset, 0,
531 SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
532 sizeof(struct in_addr) * server->n_dns, server->dns);
533 if (r < 0)
534 return r;
535 }
536
537 if (server->n_ntp > 0) {
538 r = dhcp_option_append(
539 &packet->dhcp, req->max_optlen, &offset, 0,
540 SD_DHCP_OPTION_NTP_SERVER,
541 sizeof(struct in_addr) * server->n_ntp, server->ntp);
542 if (r < 0)
543 return r;
544 }
545
546 if (server->timezone) {
547 r = dhcp_option_append(
548 &packet->dhcp, req->max_optlen, &offset, 0,
549 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE,
550 strlen(server->timezone), server->timezone);
551 if (r < 0)
552 return r;
553 }
554
555 r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset);
556 if (r < 0)
557 return r;
558
559 return 0;
560 }
561
562 static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) {
563 _cleanup_free_ DHCPPacket *packet = NULL;
564 size_t offset;
565 int r;
566
567 r = server_message_init(server, &packet, DHCP_NAK, &offset, req);
568 if (r < 0)
569 return r;
570
571 return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
572 }
573
574 static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
575 be32_t gateway, uint8_t chaddr[]) {
576 _cleanup_free_ DHCPPacket *packet = NULL;
577 size_t optoffset = 0;
578 int r;
579
580 assert(server);
581 assert(address != INADDR_ANY);
582 assert(chaddr);
583
584 packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE);
585 if (!packet)
586 return -ENOMEM;
587
588 r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0,
589 DHCP_FORCERENEW, ARPHRD_ETHER,
590 DHCP_MIN_OPTIONS_SIZE, &optoffset);
591 if (r < 0)
592 return r;
593
594 r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE,
595 &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL);
596 if (r < 0)
597 return r;
598
599 memcpy(&packet->dhcp.chaddr, chaddr, ETH_ALEN);
600
601 r = dhcp_server_send_udp(server, address, DHCP_PORT_CLIENT,
602 &packet->dhcp,
603 sizeof(DHCPMessage) + optoffset);
604 if (r < 0)
605 return r;
606
607 return 0;
608 }
609
610 static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) {
611 DHCPRequest *req = userdata;
612
613 assert(req);
614
615 switch(code) {
616 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
617 if (len == 4)
618 req->lifetime = unaligned_read_be32(option);
619
620 break;
621 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS:
622 if (len == 4)
623 memcpy(&req->requested_ip, option, sizeof(be32_t));
624
625 break;
626 case SD_DHCP_OPTION_SERVER_IDENTIFIER:
627 if (len == 4)
628 memcpy(&req->server_id, option, sizeof(be32_t));
629
630 break;
631 case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
632 if (len >= 2) {
633 uint8_t *data;
634
635 data = memdup(option, len);
636 if (!data)
637 return -ENOMEM;
638
639 free(req->client_id.data);
640 req->client_id.data = data;
641 req->client_id.length = len;
642 }
643
644 break;
645 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE:
646
647 if (len == 2 && unaligned_read_be16(option) >= sizeof(DHCPPacket))
648 req->max_optlen = unaligned_read_be16(option) - sizeof(DHCPPacket);
649
650 break;
651 }
652
653 return 0;
654 }
655
656 static void dhcp_request_free(DHCPRequest *req) {
657 if (!req)
658 return;
659
660 free(req->client_id.data);
661 free(req);
662 }
663
664 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
665 #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
666
667 static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) {
668 assert(req);
669 assert(message);
670
671 req->message = message;
672
673 /* set client id based on MAC address if client did not send an explicit
674 one */
675 if (!req->client_id.data) {
676 void *data;
677
678 data = malloc0(ETH_ALEN + 1);
679 if (!data)
680 return -ENOMEM;
681
682 ((uint8_t*) data)[0] = 0x01;
683 memcpy((uint8_t*) data + 1, &message->chaddr, ETH_ALEN);
684
685 req->client_id.length = ETH_ALEN + 1;
686 req->client_id.data = data;
687 }
688
689 if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE)
690 req->max_optlen = DHCP_MIN_OPTIONS_SIZE;
691
692 if (req->lifetime <= 0)
693 req->lifetime = MAX(1ULL, server->default_lease_time);
694
695 if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time)
696 req->lifetime = server->max_lease_time;
697
698 return 0;
699 }
700
701 static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
702 assert(server);
703
704 if (!server->pool_size)
705 return -EINVAL;
706
707 if (be32toh(requested_ip) < (be32toh(server->subnet) | server->pool_offset) ||
708 be32toh(requested_ip) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size)))
709 return -ERANGE;
710
711 return be32toh(requested_ip & ~server->netmask) - server->pool_offset;
712 }
713
714 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
715
716 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
717 size_t length) {
718 _cleanup_dhcp_request_free_ DHCPRequest *req = NULL;
719 _cleanup_free_ char *error_message = NULL;
720 DHCPLease *existing_lease;
721 int type, r;
722
723 assert(server);
724 assert(message);
725
726 if (message->op != BOOTREQUEST ||
727 message->htype != ARPHRD_ETHER ||
728 message->hlen != ETHER_ADDR_LEN)
729 return 0;
730
731 req = new0(DHCPRequest, 1);
732 if (!req)
733 return -ENOMEM;
734
735 type = dhcp_option_parse(message, length, parse_request, req, &error_message);
736 if (type < 0)
737 return 0;
738
739 r = ensure_sane_request(server, req, message);
740 if (r < 0)
741 /* this only fails on critical errors */
742 return r;
743
744 existing_lease = hashmap_get(server->leases_by_client_id,
745 &req->client_id);
746
747 switch(type) {
748
749 case DHCP_DISCOVER: {
750 be32_t address = INADDR_ANY;
751 unsigned i;
752
753 log_dhcp_server(server, "DISCOVER (0x%x)",
754 be32toh(req->message->xid));
755
756 if (!server->pool_size)
757 /* no pool allocated */
758 return 0;
759
760 /* for now pick a random free address from the pool */
761 if (existing_lease)
762 address = existing_lease->address;
763 else {
764 struct siphash state;
765 uint64_t hash;
766 uint32_t next_offer;
767
768 /* even with no persistence of leases, we try to offer the same client
769 the same IP address. we do this by using the hash of the client id
770 as the offset into the pool of leases when finding the next free one */
771
772 siphash24_init(&state, HASH_KEY.bytes);
773 client_id_hash_func(&req->client_id, &state);
774 hash = htole64(siphash24_finalize(&state));
775 next_offer = hash % server->pool_size;
776
777 for (i = 0; i < server->pool_size; i++) {
778 if (!server->bound_leases[next_offer]) {
779 address = server->subnet | htobe32(server->pool_offset + next_offer);
780 break;
781 } else
782 next_offer = (next_offer + 1) % server->pool_size;
783 }
784 }
785
786 if (address == INADDR_ANY)
787 /* no free addresses left */
788 return 0;
789
790 r = server_send_offer(server, req, address);
791 if (r < 0) {
792 /* this only fails on critical errors */
793 log_dhcp_server(server, "could not send offer: %s",
794 strerror(-r));
795 return r;
796 } else {
797 log_dhcp_server(server, "OFFER (0x%x)",
798 be32toh(req->message->xid));
799 return DHCP_OFFER;
800 }
801
802 break;
803 }
804 case DHCP_DECLINE:
805 log_dhcp_server(server, "DECLINE (0x%x): %s", be32toh(req->message->xid), strna(error_message));
806
807 /* TODO: make sure we don't offer this address again */
808
809 return 1;
810
811 case DHCP_REQUEST: {
812 be32_t address;
813 bool init_reboot = false;
814 int pool_offset;
815
816 /* see RFC 2131, section 4.3.2 */
817
818 if (req->server_id) {
819 log_dhcp_server(server, "REQUEST (selecting) (0x%x)",
820 be32toh(req->message->xid));
821
822 /* SELECTING */
823 if (req->server_id != server->address)
824 /* client did not pick us */
825 return 0;
826
827 if (req->message->ciaddr)
828 /* this MUST be zero */
829 return 0;
830
831 if (!req->requested_ip)
832 /* this must be filled in with the yiaddr
833 from the chosen OFFER */
834 return 0;
835
836 address = req->requested_ip;
837 } else if (req->requested_ip) {
838 log_dhcp_server(server, "REQUEST (init-reboot) (0x%x)",
839 be32toh(req->message->xid));
840
841 /* INIT-REBOOT */
842 if (req->message->ciaddr)
843 /* this MUST be zero */
844 return 0;
845
846 /* TODO: check more carefully if IP is correct */
847 address = req->requested_ip;
848 init_reboot = true;
849 } else {
850 log_dhcp_server(server, "REQUEST (rebinding/renewing) (0x%x)",
851 be32toh(req->message->xid));
852
853 /* REBINDING / RENEWING */
854 if (!req->message->ciaddr)
855 /* this MUST be filled in with clients IP address */
856 return 0;
857
858 address = req->message->ciaddr;
859 }
860
861 pool_offset = get_pool_offset(server, address);
862
863 /* verify that the requested address is from the pool, and either
864 owned by the current client or free */
865 if (pool_offset >= 0 &&
866 server->bound_leases[pool_offset] == existing_lease) {
867 DHCPLease *lease;
868 usec_t time_now = 0;
869
870 if (!existing_lease) {
871 lease = new0(DHCPLease, 1);
872 if (!lease)
873 return -ENOMEM;
874 lease->address = address;
875 lease->client_id.data = memdup(req->client_id.data,
876 req->client_id.length);
877 if (!lease->client_id.data) {
878 free(lease);
879 return -ENOMEM;
880 }
881 lease->client_id.length = req->client_id.length;
882 memcpy(&lease->chaddr, &req->message->chaddr,
883 ETH_ALEN);
884 lease->gateway = req->message->giaddr;
885 } else
886 lease = existing_lease;
887
888 r = sd_event_now(server->event,
889 clock_boottime_or_monotonic(),
890 &time_now);
891 if (r < 0) {
892 if (!existing_lease)
893 dhcp_lease_free(lease);
894 return r;
895 }
896
897 lease->expiration = req->lifetime * USEC_PER_SEC + time_now;
898
899 r = server_send_ack(server, req, address);
900 if (r < 0) {
901 /* this only fails on critical errors */
902 log_dhcp_server(server, "could not send ack: %s",
903 strerror(-r));
904
905 if (!existing_lease)
906 dhcp_lease_free(lease);
907
908 return r;
909 } else {
910 log_dhcp_server(server, "ACK (0x%x)",
911 be32toh(req->message->xid));
912
913 server->bound_leases[pool_offset] = lease;
914 hashmap_put(server->leases_by_client_id,
915 &lease->client_id, lease);
916
917 return DHCP_ACK;
918 }
919 } else if (init_reboot) {
920 r = server_send_nak(server, req);
921 if (r < 0) {
922 /* this only fails on critical errors */
923 log_dhcp_server(server, "could not send nak: %s",
924 strerror(-r));
925 return r;
926 } else {
927 log_dhcp_server(server, "NAK (0x%x)",
928 be32toh(req->message->xid));
929 return DHCP_NAK;
930 }
931 }
932
933 break;
934 }
935
936 case DHCP_RELEASE: {
937 int pool_offset;
938
939 log_dhcp_server(server, "RELEASE (0x%x)",
940 be32toh(req->message->xid));
941
942 if (!existing_lease)
943 return 0;
944
945 if (existing_lease->address != req->message->ciaddr)
946 return 0;
947
948 pool_offset = get_pool_offset(server, req->message->ciaddr);
949 if (pool_offset < 0)
950 return 0;
951
952 if (server->bound_leases[pool_offset] == existing_lease) {
953 server->bound_leases[pool_offset] = NULL;
954 hashmap_remove(server->leases_by_client_id, existing_lease);
955 dhcp_lease_free(existing_lease);
956
957 return 1;
958 } else
959 return 0;
960 }
961 }
962
963 return 0;
964 }
965
966 static int server_receive_message(sd_event_source *s, int fd,
967 uint32_t revents, void *userdata) {
968 _cleanup_free_ DHCPMessage *message = NULL;
969 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))];
970 sd_dhcp_server *server = userdata;
971 struct iovec iov = {};
972 struct msghdr msg = {
973 .msg_iov = &iov,
974 .msg_iovlen = 1,
975 .msg_control = cmsgbuf,
976 .msg_controllen = sizeof(cmsgbuf),
977 };
978 struct cmsghdr *cmsg;
979 ssize_t buflen, len;
980
981 assert(server);
982
983 buflen = next_datagram_size_fd(fd);
984 if (buflen < 0)
985 return buflen;
986
987 message = malloc(buflen);
988 if (!message)
989 return -ENOMEM;
990
991 iov.iov_base = message;
992 iov.iov_len = buflen;
993
994 len = recvmsg(fd, &msg, 0);
995 if (len < 0) {
996 if (IN_SET(errno, EAGAIN, EINTR))
997 return 0;
998
999 return -errno;
1000 } else if ((size_t)len < sizeof(DHCPMessage))
1001 return 0;
1002
1003 CMSG_FOREACH(cmsg, &msg) {
1004 if (cmsg->cmsg_level == IPPROTO_IP &&
1005 cmsg->cmsg_type == IP_PKTINFO &&
1006 cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) {
1007 struct in_pktinfo *info = (struct in_pktinfo*)CMSG_DATA(cmsg);
1008
1009 /* TODO figure out if this can be done as a filter on
1010 * the socket, like for IPv6 */
1011 if (server->ifindex != info->ipi_ifindex)
1012 return 0;
1013
1014 break;
1015 }
1016 }
1017
1018 return dhcp_server_handle_message(server, message, (size_t)len);
1019 }
1020
1021 int sd_dhcp_server_start(sd_dhcp_server *server) {
1022 int r;
1023
1024 assert_return(server, -EINVAL);
1025 assert_return(server->event, -EINVAL);
1026 assert_return(!server->receive_message, -EBUSY);
1027 assert_return(server->fd_raw == -1, -EBUSY);
1028 assert_return(server->fd == -1, -EBUSY);
1029 assert_return(server->address != htobe32(INADDR_ANY), -EUNATCH);
1030
1031 r = socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
1032 if (r < 0) {
1033 r = -errno;
1034 sd_dhcp_server_stop(server);
1035 return r;
1036 }
1037 server->fd_raw = r;
1038
1039 r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER);
1040 if (r < 0) {
1041 sd_dhcp_server_stop(server);
1042 return r;
1043 }
1044 server->fd = r;
1045
1046 r = sd_event_add_io(server->event, &server->receive_message,
1047 server->fd, EPOLLIN,
1048 server_receive_message, server);
1049 if (r < 0) {
1050 sd_dhcp_server_stop(server);
1051 return r;
1052 }
1053
1054 r = sd_event_source_set_priority(server->receive_message,
1055 server->event_priority);
1056 if (r < 0) {
1057 sd_dhcp_server_stop(server);
1058 return r;
1059 }
1060
1061 log_dhcp_server(server, "STARTED");
1062
1063 return 0;
1064 }
1065
1066 int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
1067 unsigned i;
1068 int r = 0;
1069
1070 assert_return(server, -EINVAL);
1071 assert(server->bound_leases);
1072
1073 for (i = 0; i < server->pool_size; i++) {
1074 DHCPLease *lease = server->bound_leases[i];
1075
1076 if (!lease || lease == &server->invalid_lease)
1077 continue;
1078
1079 r = server_send_forcerenew(server, lease->address,
1080 lease->gateway,
1081 lease->chaddr);
1082 if (r < 0)
1083 return r;
1084 else
1085 log_dhcp_server(server, "FORCERENEW");
1086 }
1087
1088 return r;
1089 }
1090
1091 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) {
1092 int r;
1093
1094 assert_return(server, -EINVAL);
1095 assert_return(timezone_is_valid(tz), -EINVAL);
1096
1097 if (streq_ptr(tz, server->timezone))
1098 return 0;
1099
1100 r = free_and_strdup(&server->timezone, tz);
1101 if (r < 0)
1102 return r;
1103
1104 return 1;
1105 }
1106
1107 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) {
1108 assert_return(server, -EINVAL);
1109
1110 if (t == server->max_lease_time)
1111 return 0;
1112
1113 server->max_lease_time = t;
1114 return 1;
1115 }
1116
1117 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) {
1118 assert_return(server, -EINVAL);
1119
1120 if (t == server->default_lease_time)
1121 return 0;
1122
1123 server->default_lease_time = t;
1124 return 1;
1125 }
1126
1127 int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) {
1128 assert_return(server, -EINVAL);
1129 assert_return(dns || n <= 0, -EINVAL);
1130
1131 if (server->n_dns == n &&
1132 memcmp(server->dns, dns, sizeof(struct in_addr) * n) == 0)
1133 return 0;
1134
1135 if (n <= 0) {
1136 server->dns = mfree(server->dns);
1137 server->n_dns = 0;
1138 } else {
1139 struct in_addr *c;
1140
1141 c = newdup(struct in_addr, dns, n);
1142 if (!c)
1143 return -ENOMEM;
1144
1145 free(server->dns);
1146 server->dns = c;
1147 server->n_dns = n;
1148 }
1149
1150 return 1;
1151 }
1152
1153 int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) {
1154 assert_return(server, -EINVAL);
1155 assert_return(ntp || n <= 0, -EINVAL);
1156
1157 if (server->n_ntp == n &&
1158 memcmp(server->ntp, ntp, sizeof(struct in_addr) * n) == 0)
1159 return 0;
1160
1161 if (n <= 0) {
1162 server->ntp = mfree(server->ntp);
1163 server->n_ntp = 0;
1164 } else {
1165 struct in_addr *c;
1166
1167 c = newdup(struct in_addr, ntp, n);
1168 if (!c)
1169 return -ENOMEM;
1170
1171 free(server->ntp);
1172 server->ntp = c;
1173 server->n_ntp = n;
1174 }
1175
1176 return 1;
1177 }
1178
1179 int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
1180 assert_return(server, -EINVAL);
1181
1182 if (enabled == server->emit_router)
1183 return 0;
1184
1185 server->emit_router = enabled;
1186
1187 return 1;
1188 }