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