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