]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/sd-dhcp-server.c
tree-wide: fix spelling errors
[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 #include "sd-id128.h"
10
11 #include "alloc-util.h"
12 #include "dhcp-internal.h"
13 #include "dhcp-server-internal.h"
14 #include "fd-util.h"
15 #include "in-addr-util.h"
16 #include "io-util.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 free(server->sip);
143 free(server->pop3_server);
144 free(server->smtp_server);
145
146 hashmap_free(server->leases_by_client_id);
147
148 ordered_hashmap_free(server->extra_options);
149 ordered_hashmap_free(server->vendor_options);
150
151 free(server->bound_leases);
152 return mfree(server);
153 }
154
155 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server, sd_dhcp_server, dhcp_server_free);
156
157 int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
158 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
159
160 assert_return(ret, -EINVAL);
161 assert_return(ifindex > 0, -EINVAL);
162
163 server = new0(sd_dhcp_server, 1);
164 if (!server)
165 return -ENOMEM;
166
167 server->n_ref = 1;
168 server->fd_raw = -1;
169 server->fd = -1;
170 server->address = htobe32(INADDR_ANY);
171 server->netmask = htobe32(INADDR_ANY);
172 server->ifindex = ifindex;
173
174 server->leases_by_client_id = hashmap_new(&dhcp_lease_hash_ops);
175 if (!server->leases_by_client_id)
176 return -ENOMEM;
177
178 server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC);
179 server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC);
180
181 *ret = TAKE_PTR(server);
182
183 return 0;
184 }
185
186 int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int64_t priority) {
187 int r;
188
189 assert_return(server, -EINVAL);
190 assert_return(!server->event, -EBUSY);
191
192 if (event)
193 server->event = sd_event_ref(event);
194 else {
195 r = sd_event_default(&server->event);
196 if (r < 0)
197 return r;
198 }
199
200 server->event_priority = priority;
201
202 return 0;
203 }
204
205 int sd_dhcp_server_detach_event(sd_dhcp_server *server) {
206 assert_return(server, -EINVAL);
207
208 server->event = sd_event_unref(server->event);
209
210 return 0;
211 }
212
213 sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) {
214 assert_return(server, NULL);
215
216 return server->event;
217 }
218
219 int sd_dhcp_server_stop(sd_dhcp_server *server) {
220 assert_return(server, -EINVAL);
221
222 server->receive_message =
223 sd_event_source_unref(server->receive_message);
224
225 server->fd_raw = safe_close(server->fd_raw);
226 server->fd = safe_close(server->fd);
227
228 log_dhcp_server(server, "STOPPED");
229
230 return 0;
231 }
232
233 static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,
234 DHCPPacket *packet, size_t len) {
235 union sockaddr_union link = {
236 .ll.sll_family = AF_PACKET,
237 .ll.sll_protocol = htobe16(ETH_P_IP),
238 .ll.sll_ifindex = server->ifindex,
239 .ll.sll_halen = ETH_ALEN,
240 };
241
242 assert(server);
243 assert(server->ifindex > 0);
244 assert(server->address);
245 assert(packet);
246 assert(len > sizeof(DHCPPacket));
247
248 memcpy(&link.ll.sll_addr, &packet->dhcp.chaddr, ETH_ALEN);
249
250 dhcp_packet_append_ip_headers(packet, server->address, DHCP_PORT_SERVER,
251 packet->dhcp.yiaddr,
252 DHCP_PORT_CLIENT, len, -1);
253
254 return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len);
255 }
256
257 static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
258 uint16_t destination_port,
259 DHCPMessage *message, size_t len) {
260 union sockaddr_union dest = {
261 .in.sin_family = AF_INET,
262 .in.sin_port = htobe16(destination_port),
263 .in.sin_addr.s_addr = destination,
264 };
265 struct iovec iov = {
266 .iov_base = message,
267 .iov_len = len,
268 };
269 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))] = {};
270 struct msghdr msg = {
271 .msg_name = &dest,
272 .msg_namelen = sizeof(dest.in),
273 .msg_iov = &iov,
274 .msg_iovlen = 1,
275 .msg_control = cmsgbuf,
276 .msg_controllen = sizeof(cmsgbuf),
277 };
278 struct cmsghdr *cmsg;
279 struct in_pktinfo *pktinfo;
280
281 assert(server);
282 assert(server->fd >= 0);
283 assert(message);
284 assert(len > sizeof(DHCPMessage));
285
286 cmsg = CMSG_FIRSTHDR(&msg);
287 assert(cmsg);
288
289 cmsg->cmsg_level = IPPROTO_IP;
290 cmsg->cmsg_type = IP_PKTINFO;
291 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
292
293 /* we attach source interface and address info to the message
294 rather than binding the socket. This will be mostly useful
295 when we gain support for arbitrary number of server addresses
296 */
297 pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
298 assert(pktinfo);
299
300 pktinfo->ipi_ifindex = server->ifindex;
301 pktinfo->ipi_spec_dst.s_addr = server->address;
302
303 if (sendmsg(server->fd, &msg, 0) < 0)
304 return -errno;
305
306 return 0;
307 }
308
309 static bool requested_broadcast(DHCPRequest *req) {
310 assert(req);
311
312 return req->message->flags & htobe16(0x8000);
313 }
314
315 int dhcp_server_send_packet(sd_dhcp_server *server,
316 DHCPRequest *req, DHCPPacket *packet,
317 int type, size_t optoffset) {
318 be32_t destination = INADDR_ANY;
319 uint16_t destination_port = DHCP_PORT_CLIENT;
320 int r;
321
322 assert(server);
323 assert(req);
324 assert(req->max_optlen);
325 assert(optoffset <= req->max_optlen);
326 assert(packet);
327
328 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
329 SD_DHCP_OPTION_SERVER_IDENTIFIER,
330 4, &server->address);
331 if (r < 0)
332 return r;
333
334 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0,
335 SD_DHCP_OPTION_END, 0, NULL);
336 if (r < 0)
337 return r;
338
339 /* RFC 2131 Section 4.1
340
341 If the ’giaddr’ field in a DHCP message from a client is non-zero,
342 the server sends any return messages to the ’DHCP server’ port on the
343 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
344 field is zero and the ’ciaddr’ field is nonzero, then the server
345 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
346 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
347 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
348 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
349 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
350 messages to the client’s hardware address and ’yiaddr’ address. In
351 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
352 messages to 0xffffffff.
353
354 Section 4.3.2
355
356 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
357 different subnet. The server MUST set the broadcast bit in the
358 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
359 client, because the client may not have a correct network address
360 or subnet mask, and the client may not be answering ARP requests.
361 */
362 if (req->message->giaddr) {
363 destination = req->message->giaddr;
364 destination_port = DHCP_PORT_SERVER;
365 if (type == DHCP_NAK)
366 packet->dhcp.flags = htobe16(0x8000);
367 } else if (req->message->ciaddr && type != DHCP_NAK)
368 destination = req->message->ciaddr;
369
370 if (destination != INADDR_ANY)
371 return dhcp_server_send_udp(server, destination,
372 destination_port, &packet->dhcp,
373 sizeof(DHCPMessage) + optoffset);
374 else if (requested_broadcast(req) || type == DHCP_NAK)
375 return dhcp_server_send_udp(server, INADDR_BROADCAST,
376 destination_port, &packet->dhcp,
377 sizeof(DHCPMessage) + optoffset);
378 else
379 /* we cannot send UDP packet to specific MAC address when the
380 address is not yet configured, so must fall back to raw
381 packets */
382 return dhcp_server_send_unicast_raw(server, packet,
383 sizeof(DHCPPacket) + optoffset);
384 }
385
386 static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
387 uint8_t type, size_t *_optoffset,
388 DHCPRequest *req) {
389 _cleanup_free_ DHCPPacket *packet = NULL;
390 size_t optoffset = 0;
391 int r;
392
393 assert(server);
394 assert(ret);
395 assert(_optoffset);
396 assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK));
397
398 packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
399 if (!packet)
400 return -ENOMEM;
401
402 r = dhcp_message_init(&packet->dhcp, BOOTREPLY,
403 be32toh(req->message->xid), type, ARPHRD_ETHER,
404 req->max_optlen, &optoffset);
405 if (r < 0)
406 return r;
407
408 packet->dhcp.flags = req->message->flags;
409 packet->dhcp.giaddr = req->message->giaddr;
410 memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN);
411
412 *_optoffset = optoffset;
413 *ret = TAKE_PTR(packet);
414
415 return 0;
416 }
417
418 static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req,
419 be32_t address) {
420 _cleanup_free_ DHCPPacket *packet = NULL;
421 size_t offset;
422 be32_t lease_time;
423 int r;
424
425 r = server_message_init(server, &packet, DHCP_OFFER, &offset, req);
426 if (r < 0)
427 return r;
428
429 packet->dhcp.yiaddr = address;
430
431 lease_time = htobe32(req->lifetime);
432 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
433 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
434 &lease_time);
435 if (r < 0)
436 return r;
437
438 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
439 SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
440 if (r < 0)
441 return r;
442
443 if (server->emit_router) {
444 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
445 SD_DHCP_OPTION_ROUTER, 4, &server->address);
446 if (r < 0)
447 return r;
448 }
449
450 r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset);
451 if (r < 0)
452 return r;
453
454 return 0;
455 }
456
457 static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
458 be32_t address) {
459 _cleanup_free_ DHCPPacket *packet = NULL;
460 be32_t lease_time;
461 sd_dhcp_option *j;
462 Iterator i;
463 size_t offset;
464 int r;
465
466 r = server_message_init(server, &packet, DHCP_ACK, &offset, req);
467 if (r < 0)
468 return r;
469
470 packet->dhcp.yiaddr = address;
471
472 lease_time = htobe32(req->lifetime);
473 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
474 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
475 &lease_time);
476 if (r < 0)
477 return r;
478
479 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
480 SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
481 if (r < 0)
482 return r;
483
484 if (server->emit_router) {
485 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
486 SD_DHCP_OPTION_ROUTER, 4, &server->address);
487 if (r < 0)
488 return r;
489 }
490
491 if (server->n_dns > 0) {
492 r = dhcp_option_append(
493 &packet->dhcp, req->max_optlen, &offset, 0,
494 SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
495 sizeof(struct in_addr) * server->n_dns, server->dns);
496 if (r < 0)
497 return r;
498 }
499
500 if (server->n_ntp > 0) {
501 r = dhcp_option_append(
502 &packet->dhcp, req->max_optlen, &offset, 0,
503 SD_DHCP_OPTION_NTP_SERVER,
504 sizeof(struct in_addr) * server->n_ntp, server->ntp);
505 if (r < 0)
506 return r;
507 }
508
509 if (server->n_sip > 0) {
510 r = dhcp_option_append(
511 &packet->dhcp, req->max_optlen, &offset, 0,
512 SD_DHCP_OPTION_SIP_SERVER,
513 sizeof(struct in_addr) * server->n_sip, server->sip);
514 if (r < 0)
515 return r;
516 }
517
518 if (server->n_pop3_server > 0) {
519 r = dhcp_option_append(
520 &packet->dhcp, req->max_optlen, &offset, 0,
521 SD_DHCP_OPTION_POP3_SERVER,
522 sizeof(struct in_addr) * server->n_pop3_server, server->pop3_server);
523 if (r < 0)
524 return r;
525 }
526
527 if (server->n_smtp_server > 0) {
528 r = dhcp_option_append(
529 &packet->dhcp, req->max_optlen, &offset, 0,
530 SD_DHCP_OPTION_SMTP_SERVER,
531 sizeof(struct in_addr) * server->n_smtp_server, server->smtp_server);
532 if (r < 0)
533 return r;
534 }
535
536 if (server->timezone) {
537 r = dhcp_option_append(
538 &packet->dhcp, req->max_optlen, &offset, 0,
539 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE,
540 strlen(server->timezone), server->timezone);
541 if (r < 0)
542 return r;
543 }
544
545 ORDERED_HASHMAP_FOREACH(j, server->extra_options, i) {
546 r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
547 j->option, j->length, j->data);
548 if (r < 0)
549 return r;
550 }
551
552 if (!ordered_hashmap_isempty(server->vendor_options)) {
553 r = dhcp_option_append(
554 &packet->dhcp, req->max_optlen, &offset, 0,
555 SD_DHCP_OPTION_VENDOR_SPECIFIC,
556 ordered_hashmap_size(server->vendor_options), server->vendor_options);
557 if (r < 0)
558 return r;
559 }
560
561 r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset);
562 if (r < 0)
563 return r;
564
565 return 0;
566 }
567
568 static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) {
569 _cleanup_free_ DHCPPacket *packet = NULL;
570 size_t offset;
571 int r;
572
573 r = server_message_init(server, &packet, DHCP_NAK, &offset, req);
574 if (r < 0)
575 return r;
576
577 return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
578 }
579
580 static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
581 be32_t gateway, uint8_t chaddr[]) {
582 _cleanup_free_ DHCPPacket *packet = NULL;
583 size_t optoffset = 0;
584 int r;
585
586 assert(server);
587 assert(address != INADDR_ANY);
588 assert(chaddr);
589
590 packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE);
591 if (!packet)
592 return -ENOMEM;
593
594 r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0,
595 DHCP_FORCERENEW, ARPHRD_ETHER,
596 DHCP_MIN_OPTIONS_SIZE, &optoffset);
597 if (r < 0)
598 return r;
599
600 r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE,
601 &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL);
602 if (r < 0)
603 return r;
604
605 memcpy(&packet->dhcp.chaddr, chaddr, ETH_ALEN);
606
607 r = dhcp_server_send_udp(server, address, DHCP_PORT_CLIENT,
608 &packet->dhcp,
609 sizeof(DHCPMessage) + optoffset);
610 if (r < 0)
611 return r;
612
613 return 0;
614 }
615
616 static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) {
617 DHCPRequest *req = userdata;
618
619 assert(req);
620
621 switch(code) {
622 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
623 if (len == 4)
624 req->lifetime = unaligned_read_be32(option);
625
626 break;
627 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS:
628 if (len == 4)
629 memcpy(&req->requested_ip, option, sizeof(be32_t));
630
631 break;
632 case SD_DHCP_OPTION_SERVER_IDENTIFIER:
633 if (len == 4)
634 memcpy(&req->server_id, option, sizeof(be32_t));
635
636 break;
637 case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
638 if (len >= 2) {
639 uint8_t *data;
640
641 data = memdup(option, len);
642 if (!data)
643 return -ENOMEM;
644
645 free(req->client_id.data);
646 req->client_id.data = data;
647 req->client_id.length = len;
648 }
649
650 break;
651 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE:
652
653 if (len == 2 && unaligned_read_be16(option) >= sizeof(DHCPPacket))
654 req->max_optlen = unaligned_read_be16(option) - sizeof(DHCPPacket);
655
656 break;
657 }
658
659 return 0;
660 }
661
662 static void dhcp_request_free(DHCPRequest *req) {
663 if (!req)
664 return;
665
666 free(req->client_id.data);
667 free(req);
668 }
669
670 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
671
672 static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) {
673 assert(req);
674 assert(message);
675
676 req->message = message;
677
678 /* set client id based on MAC address if client did not send an explicit
679 one */
680 if (!req->client_id.data) {
681 void *data;
682
683 data = malloc0(ETH_ALEN + 1);
684 if (!data)
685 return -ENOMEM;
686
687 ((uint8_t*) data)[0] = 0x01;
688 memcpy((uint8_t*) data + 1, &message->chaddr, ETH_ALEN);
689
690 req->client_id.length = ETH_ALEN + 1;
691 req->client_id.data = data;
692 }
693
694 if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE)
695 req->max_optlen = DHCP_MIN_OPTIONS_SIZE;
696
697 if (req->lifetime <= 0)
698 req->lifetime = MAX(1ULL, server->default_lease_time);
699
700 if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time)
701 req->lifetime = server->max_lease_time;
702
703 return 0;
704 }
705
706 static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
707 assert(server);
708
709 if (!server->pool_size)
710 return -EINVAL;
711
712 if (be32toh(requested_ip) < (be32toh(server->subnet) | server->pool_offset) ||
713 be32toh(requested_ip) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size)))
714 return -ERANGE;
715
716 return be32toh(requested_ip & ~server->netmask) - server->pool_offset;
717 }
718
719 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
720
721 int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
722 size_t length) {
723 _cleanup_(dhcp_request_freep) DHCPRequest *req = NULL;
724 _cleanup_free_ char *error_message = NULL;
725 DHCPLease *existing_lease;
726 int type, r;
727
728 assert(server);
729 assert(message);
730
731 if (message->op != BOOTREQUEST ||
732 message->htype != ARPHRD_ETHER ||
733 message->hlen != ETHER_ADDR_LEN)
734 return 0;
735
736 req = new0(DHCPRequest, 1);
737 if (!req)
738 return -ENOMEM;
739
740 type = dhcp_option_parse(message, length, parse_request, req, &error_message);
741 if (type < 0)
742 return 0;
743
744 r = ensure_sane_request(server, req, message);
745 if (r < 0)
746 /* this only fails on critical errors */
747 return r;
748
749 existing_lease = hashmap_get(server->leases_by_client_id,
750 &req->client_id);
751
752 switch(type) {
753
754 case DHCP_DISCOVER: {
755 be32_t address = INADDR_ANY;
756 unsigned i;
757
758 log_dhcp_server(server, "DISCOVER (0x%x)",
759 be32toh(req->message->xid));
760
761 if (!server->pool_size)
762 /* no pool allocated */
763 return 0;
764
765 /* for now pick a random free address from the pool */
766 if (existing_lease)
767 address = existing_lease->address;
768 else {
769 struct siphash state;
770 uint64_t hash;
771 uint32_t next_offer;
772
773 /* even with no persistence of leases, we try to offer the same client
774 the same IP address. we do this by using the hash of the client id
775 as the offset into the pool of leases when finding the next free one */
776
777 siphash24_init(&state, HASH_KEY.bytes);
778 client_id_hash_func(&req->client_id, &state);
779 hash = htole64(siphash24_finalize(&state));
780 next_offer = hash % server->pool_size;
781
782 for (i = 0; i < server->pool_size; i++) {
783 if (!server->bound_leases[next_offer]) {
784 address = server->subnet | htobe32(server->pool_offset + next_offer);
785 break;
786 }
787
788 next_offer = (next_offer + 1) % server->pool_size;
789 }
790 }
791
792 if (address == INADDR_ANY)
793 /* no free addresses left */
794 return 0;
795
796 r = server_send_offer(server, req, address);
797 if (r < 0)
798 /* this only fails on critical errors */
799 return log_dhcp_server_errno(server, r, "Could not send offer: %m");
800
801 log_dhcp_server(server, "OFFER (0x%x)", be32toh(req->message->xid));
802 return DHCP_OFFER;
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_errno(server, r, "Could not send ack: %m");
903
904 if (!existing_lease)
905 dhcp_lease_free(lease);
906
907 return r;
908 } else {
909 log_dhcp_server(server, "ACK (0x%x)",
910 be32toh(req->message->xid));
911
912 server->bound_leases[pool_offset] = lease;
913 hashmap_put(server->leases_by_client_id,
914 &lease->client_id, lease);
915
916 return DHCP_ACK;
917 }
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 return log_dhcp_server_errno(server, r, "Could not send nak: %m");
924
925 log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid));
926 return DHCP_NAK;
927 }
928
929 break;
930 }
931
932 case DHCP_RELEASE: {
933 int pool_offset;
934
935 log_dhcp_server(server, "RELEASE (0x%x)",
936 be32toh(req->message->xid));
937
938 if (!existing_lease)
939 return 0;
940
941 if (existing_lease->address != req->message->ciaddr)
942 return 0;
943
944 pool_offset = get_pool_offset(server, req->message->ciaddr);
945 if (pool_offset < 0)
946 return 0;
947
948 if (server->bound_leases[pool_offset] == existing_lease) {
949 server->bound_leases[pool_offset] = NULL;
950 hashmap_remove(server->leases_by_client_id, existing_lease);
951 dhcp_lease_free(existing_lease);
952 }
953
954 return 0;
955 }}
956
957 return 0;
958 }
959
960 static int server_receive_message(sd_event_source *s, int fd,
961 uint32_t revents, void *userdata) {
962 _cleanup_free_ DHCPMessage *message = NULL;
963 uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))];
964 sd_dhcp_server *server = userdata;
965 struct iovec iov = {};
966 struct msghdr msg = {
967 .msg_iov = &iov,
968 .msg_iovlen = 1,
969 .msg_control = cmsgbuf,
970 .msg_controllen = sizeof(cmsgbuf),
971 };
972 struct cmsghdr *cmsg;
973 ssize_t buflen, len;
974 int r;
975
976 assert(server);
977
978 buflen = next_datagram_size_fd(fd);
979 if (buflen < 0)
980 return buflen;
981
982 message = malloc(buflen);
983 if (!message)
984 return -ENOMEM;
985
986 iov = IOVEC_MAKE(message, buflen);
987
988 len = recvmsg(fd, &msg, 0);
989 if (len < 0) {
990 if (IN_SET(errno, EAGAIN, EINTR))
991 return 0;
992
993 return -errno;
994 }
995 if ((size_t)len < sizeof(DHCPMessage))
996 return 0;
997
998 CMSG_FOREACH(cmsg, &msg) {
999 if (cmsg->cmsg_level == IPPROTO_IP &&
1000 cmsg->cmsg_type == IP_PKTINFO &&
1001 cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) {
1002 struct in_pktinfo *info = (struct in_pktinfo*)CMSG_DATA(cmsg);
1003
1004 /* TODO figure out if this can be done as a filter on
1005 * the socket, like for IPv6 */
1006 if (server->ifindex != info->ipi_ifindex)
1007 return 0;
1008
1009 break;
1010 }
1011 }
1012
1013 r = dhcp_server_handle_message(server, message, (size_t) len);
1014 if (r < 0)
1015 log_dhcp_server_errno(server, r, "Couldn't process incoming message: %m");
1016
1017 return 0;
1018 }
1019
1020 int sd_dhcp_server_start(sd_dhcp_server *server) {
1021 int r;
1022
1023 assert_return(server, -EINVAL);
1024 assert_return(server->event, -EINVAL);
1025 assert_return(!server->receive_message, -EBUSY);
1026 assert_return(server->fd_raw < 0, -EBUSY);
1027 assert_return(server->fd < 0, -EBUSY);
1028 assert_return(server->address != htobe32(INADDR_ANY), -EUNATCH);
1029
1030 r = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
1031 if (r < 0) {
1032 r = -errno;
1033 sd_dhcp_server_stop(server);
1034 return r;
1035 }
1036 server->fd_raw = r;
1037
1038 r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER, -1);
1039 if (r < 0) {
1040 sd_dhcp_server_stop(server);
1041 return r;
1042 }
1043 server->fd = r;
1044
1045 r = sd_event_add_io(server->event, &server->receive_message,
1046 server->fd, EPOLLIN,
1047 server_receive_message, server);
1048 if (r < 0) {
1049 sd_dhcp_server_stop(server);
1050 return r;
1051 }
1052
1053 r = sd_event_source_set_priority(server->receive_message,
1054 server->event_priority);
1055 if (r < 0) {
1056 sd_dhcp_server_stop(server);
1057 return r;
1058 }
1059
1060 log_dhcp_server(server, "STARTED");
1061
1062 return 0;
1063 }
1064
1065 int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
1066 unsigned i;
1067 int r = 0;
1068
1069 assert_return(server, -EINVAL);
1070 assert(server->bound_leases);
1071
1072 for (i = 0; i < server->pool_size; i++) {
1073 DHCPLease *lease = server->bound_leases[i];
1074
1075 if (!lease || lease == &server->invalid_lease)
1076 continue;
1077
1078 r = server_send_forcerenew(server, lease->address,
1079 lease->gateway,
1080 lease->chaddr);
1081 if (r < 0)
1082 return r;
1083
1084 log_dhcp_server(server, "FORCERENEW");
1085 }
1086
1087 return r;
1088 }
1089
1090 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) {
1091 int r;
1092
1093 assert_return(server, -EINVAL);
1094 assert_return(timezone_is_valid(tz, LOG_DEBUG), -EINVAL);
1095
1096 if (streq_ptr(tz, server->timezone))
1097 return 0;
1098
1099 r = free_and_strdup(&server->timezone, tz);
1100 if (r < 0)
1101 return r;
1102
1103 return 1;
1104 }
1105
1106 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) {
1107 assert_return(server, -EINVAL);
1108
1109 if (t == server->max_lease_time)
1110 return 0;
1111
1112 server->max_lease_time = t;
1113 return 1;
1114 }
1115
1116 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) {
1117 assert_return(server, -EINVAL);
1118
1119 if (t == server->default_lease_time)
1120 return 0;
1121
1122 server->default_lease_time = t;
1123 return 1;
1124 }
1125
1126 int sd_dhcp_server_set_servers(
1127 sd_dhcp_server *server,
1128 sd_dhcp_lease_info what,
1129 const struct in_addr addresses[],
1130 unsigned n_addresses) {
1131
1132 assert_return(server, -EINVAL);
1133 assert_return(addresses || n_addresses == 0, -EINVAL);
1134
1135 struct in_addr **a;
1136 unsigned *n_a;
1137
1138 switch (what) {
1139 case SD_DHCP_LEASE_DNS_SERVERS:
1140 a = &server->dns;
1141 n_a = &server->n_dns;
1142 break;
1143
1144 case SD_DHCP_LEASE_NTP_SERVERS:
1145 a = &server->ntp;
1146 n_a = &server->n_ntp;
1147 break;
1148
1149 case SD_DHCP_LEASE_SIP_SERVERS:
1150 a = &server->sip;
1151 n_a = &server->n_sip;
1152 break;
1153
1154 case SD_DHCP_LEASE_POP3_SERVERS:
1155 a = &server->pop3_server;
1156 n_a = &server->n_pop3_server;
1157 break;
1158
1159 case SD_DHCP_LEASE_SMTP_SERVERS:
1160 a = &server->smtp_server;
1161 n_a = &server->n_smtp_server;
1162 break;
1163
1164 default:
1165 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO),
1166 "Unknown DHCP lease info item %d.", what);
1167 }
1168
1169 if (*n_a == n_addresses &&
1170 memcmp(*a, addresses, sizeof(struct in_addr) * n_addresses) == 0)
1171 return 0;
1172
1173 struct in_addr *c = NULL;
1174
1175 if (n_addresses > 0) {
1176 c = newdup(struct in_addr, addresses, n_addresses);
1177 if (!c)
1178 return -ENOMEM;
1179 }
1180
1181 free(*a);
1182 *a = c;
1183 *n_a = n_addresses;
1184 return 1;
1185 }
1186
1187 int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) {
1188 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_DNS_SERVERS, dns, n);
1189 }
1190 int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) {
1191 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_NTP_SERVERS, ntp, n);
1192 }
1193 int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n) {
1194 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_SIP_SERVERS, sip, n);
1195 }
1196 int sd_dhcp_server_set_pop3_server(sd_dhcp_server *server, const struct in_addr pop3[], unsigned n) {
1197 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_POP3_SERVERS, pop3, n);
1198 }
1199 int sd_dhcp_server_set_smtp_server(sd_dhcp_server *server, const struct in_addr smtp[], unsigned n) {
1200 return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_SMTP_SERVERS, smtp, n);
1201 }
1202
1203 int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
1204 assert_return(server, -EINVAL);
1205
1206 if (enabled == server->emit_router)
1207 return 0;
1208
1209 server->emit_router = enabled;
1210
1211 return 1;
1212 }
1213
1214 int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v) {
1215 int r;
1216
1217 assert_return(server, -EINVAL);
1218 assert_return(v, -EINVAL);
1219
1220 r = ordered_hashmap_ensure_allocated(&server->extra_options, &dhcp_option_hash_ops);
1221 if (r < 0)
1222 return r;
1223
1224 r = ordered_hashmap_put(server->extra_options, UINT_TO_PTR(v->option), v);
1225 if (r < 0)
1226 return r;
1227
1228 sd_dhcp_option_ref(v);
1229 return 0;
1230 }
1231
1232 int sd_dhcp_server_add_vendor_option(sd_dhcp_server *server, sd_dhcp_option *v) {
1233 int r;
1234
1235 assert_return(server, -EINVAL);
1236 assert_return(v, -EINVAL);
1237
1238 r = ordered_hashmap_ensure_allocated(&server->vendor_options, &dhcp_option_hash_ops);
1239 if (r < 0)
1240 return -ENOMEM;
1241
1242 r = ordered_hashmap_put(server->vendor_options, v, v);
1243 if (r < 0)
1244 return r;
1245
1246 sd_dhcp_option_ref(v);
1247
1248 return 1;
1249 }