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