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