1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright (C) 2013 Intel Corporation. All rights reserved.
6 Copyright (C) 2014 Tom Gundersen
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/ioctl.h>
24 #include "sd-dhcp-server.h"
26 #include "alloc-util.h"
27 #include "dhcp-internal.h"
28 #include "dhcp-server-internal.h"
30 #include "in-addr-util.h"
31 #include "siphash24.h"
32 #include "string-util.h"
33 #include "unaligned.h"
35 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
36 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
38 static void dhcp_lease_free(DHCPLease
*lease
) {
42 free(lease
->client_id
.data
);
46 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
47 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
48 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
49 * accidentally hand it out */
50 int sd_dhcp_server_configure_pool(sd_dhcp_server
*server
, struct in_addr
*address
, unsigned char prefixlen
, uint32_t offset
, uint32_t size
) {
51 struct in_addr netmask_addr
;
53 uint32_t server_off
, broadcast_off
, size_max
;
55 assert_return(server
, -EINVAL
);
56 assert_return(address
, -EINVAL
);
57 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
58 assert_return(prefixlen
<= 32, -ERANGE
);
60 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
61 netmask
= netmask_addr
.s_addr
;
63 server_off
= be32toh(address
->s_addr
& ~netmask
);
64 broadcast_off
= be32toh(~netmask
);
66 /* the server address cannot be the subnet address */
67 assert_return(server_off
!= 0, -ERANGE
);
69 /* nor the broadcast address */
70 assert_return(server_off
!= broadcast_off
, -ERANGE
);
72 /* 0 offset means we should set a default, we skip the first (subnet) address
73 and take the next one */
77 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
78 - offset
/* exclude the addresses before the offset */
79 - 1; /* exclude the last (broadcast) address */
81 /* The pool must contain at least one address */
82 assert_return(size_max
>= 1, -ERANGE
);
85 assert_return(size
<= size_max
, -ERANGE
);
89 if (server
->address
!= address
->s_addr
|| server
->netmask
!= netmask
|| server
->pool_size
!= size
|| server
->pool_offset
!= offset
) {
92 free(server
->bound_leases
);
93 server
->bound_leases
= new0(DHCPLease
*, size
);
94 if (!server
->bound_leases
)
97 server
->pool_offset
= offset
;
98 server
->pool_size
= size
;
100 server
->address
= address
->s_addr
;
101 server
->netmask
= netmask
;
102 server
->subnet
= address
->s_addr
& netmask
;
104 if (server_off
>= offset
&& server_off
- offset
< size
)
105 server
->bound_leases
[server_off
- offset
] = &server
->invalid_lease
;
107 /* Drop any leases associated with the old address range */
108 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
109 dhcp_lease_free(lease
);
115 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
116 assert_return(server
, false);
118 return !!server
->receive_message
;
121 sd_dhcp_server
*sd_dhcp_server_ref(sd_dhcp_server
*server
) {
126 assert(server
->n_ref
>= 1);
132 void client_id_hash_func(const void *p
, struct siphash
*state
) {
133 const DHCPClientId
*id
= p
;
139 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
140 siphash24_compress(id
->data
, id
->length
, state
);
143 int client_id_compare_func(const void *_a
, const void *_b
) {
144 const DHCPClientId
*a
, *b
;
149 assert(!a
->length
|| a
->data
);
150 assert(!b
->length
|| b
->data
);
152 if (a
->length
!= b
->length
)
153 return a
->length
< b
->length
? -1 : 1;
155 return memcmp(a
->data
, b
->data
, a
->length
);
158 static const struct hash_ops client_id_hash_ops
= {
159 .hash
= client_id_hash_func
,
160 .compare
= client_id_compare_func
163 sd_dhcp_server
*sd_dhcp_server_unref(sd_dhcp_server
*server
) {
169 assert(server
->n_ref
>= 1);
172 if (server
->n_ref
> 0)
175 log_dhcp_server(server
, "UNREF");
177 sd_dhcp_server_stop(server
);
179 sd_event_unref(server
->event
);
181 free(server
->timezone
);
185 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
186 dhcp_lease_free(lease
);
187 hashmap_free(server
->leases_by_client_id
);
189 free(server
->bound_leases
);
190 return mfree(server
);
193 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
194 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
196 assert_return(ret
, -EINVAL
);
197 assert_return(ifindex
> 0, -EINVAL
);
199 server
= new0(sd_dhcp_server
, 1);
206 server
->address
= htobe32(INADDR_ANY
);
207 server
->netmask
= htobe32(INADDR_ANY
);
208 server
->ifindex
= ifindex
;
210 server
->leases_by_client_id
= hashmap_new(&client_id_hash_ops
);
211 if (!server
->leases_by_client_id
)
214 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
215 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
223 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
226 assert_return(server
, -EINVAL
);
227 assert_return(!server
->event
, -EBUSY
);
230 server
->event
= sd_event_ref(event
);
232 r
= sd_event_default(&server
->event
);
237 server
->event_priority
= priority
;
242 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
243 assert_return(server
, -EINVAL
);
245 server
->event
= sd_event_unref(server
->event
);
250 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
251 assert_return(server
, NULL
);
253 return server
->event
;
256 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
257 assert_return(server
, -EINVAL
);
259 server
->receive_message
=
260 sd_event_source_unref(server
->receive_message
);
262 server
->fd_raw
= safe_close(server
->fd_raw
);
263 server
->fd
= safe_close(server
->fd
);
265 log_dhcp_server(server
, "STOPPED");
270 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
271 DHCPPacket
*packet
, size_t len
) {
272 union sockaddr_union link
= {
273 .ll
.sll_family
= AF_PACKET
,
274 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
275 .ll
.sll_ifindex
= server
->ifindex
,
276 .ll
.sll_halen
= ETH_ALEN
,
280 assert(server
->ifindex
> 0);
281 assert(server
->address
);
283 assert(len
> sizeof(DHCPPacket
));
285 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
287 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
289 DHCP_PORT_CLIENT
, len
);
291 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
294 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
295 uint16_t destination_port
,
296 DHCPMessage
*message
, size_t len
) {
297 union sockaddr_union dest
= {
298 .in
.sin_family
= AF_INET
,
299 .in
.sin_port
= htobe16(destination_port
),
300 .in
.sin_addr
.s_addr
= destination
,
306 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
307 struct msghdr msg
= {
309 .msg_namelen
= sizeof(dest
.in
),
312 .msg_control
= cmsgbuf
,
313 .msg_controllen
= sizeof(cmsgbuf
),
315 struct cmsghdr
*cmsg
;
316 struct in_pktinfo
*pktinfo
;
320 assert(server
->fd
> 0);
322 assert(len
> sizeof(DHCPMessage
));
324 cmsg
= CMSG_FIRSTHDR(&msg
);
327 cmsg
->cmsg_level
= IPPROTO_IP
;
328 cmsg
->cmsg_type
= IP_PKTINFO
;
329 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
331 /* we attach source interface and address info to the message
332 rather than binding the socket. This will be mostly useful
333 when we gain support for arbitrary number of server addresses
335 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
338 pktinfo
->ipi_ifindex
= server
->ifindex
;
339 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
341 r
= sendmsg(server
->fd
, &msg
, 0);
348 static bool requested_broadcast(DHCPRequest
*req
) {
351 return req
->message
->flags
& htobe16(0x8000);
354 int dhcp_server_send_packet(sd_dhcp_server
*server
,
355 DHCPRequest
*req
, DHCPPacket
*packet
,
356 int type
, size_t optoffset
) {
357 be32_t destination
= INADDR_ANY
;
358 uint16_t destination_port
= DHCP_PORT_CLIENT
;
363 assert(req
->max_optlen
);
364 assert(optoffset
<= req
->max_optlen
);
367 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
368 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
369 4, &server
->address
);
373 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
374 SD_DHCP_OPTION_END
, 0, NULL
);
378 /* RFC 2131 Section 4.1
380 If the ’giaddr’ field in a DHCP message from a client is non-zero,
381 the server sends any return messages to the ’DHCP server’ port on the
382 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
383 field is zero and the ’ciaddr’ field is nonzero, then the server
384 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
385 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
386 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
387 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
388 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
389 messages to the client’s hardware address and ’yiaddr’ address. In
390 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
391 messages to 0xffffffff.
395 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
396 different subnet. The server MUST set the broadcast bit in the
397 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
398 client, because the client may not have a correct network address
399 or subnet mask, and the client may not be answering ARP requests.
401 if (req
->message
->giaddr
) {
402 destination
= req
->message
->giaddr
;
403 destination_port
= DHCP_PORT_SERVER
;
404 if (type
== DHCP_NAK
)
405 packet
->dhcp
.flags
= htobe16(0x8000);
406 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
407 destination
= req
->message
->ciaddr
;
409 if (destination
!= INADDR_ANY
)
410 return dhcp_server_send_udp(server
, destination
,
411 destination_port
, &packet
->dhcp
,
412 sizeof(DHCPMessage
) + optoffset
);
413 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
414 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
415 destination_port
, &packet
->dhcp
,
416 sizeof(DHCPMessage
) + optoffset
);
418 /* we cannot send UDP packet to specific MAC address when the
419 address is not yet configured, so must fall back to raw
421 return dhcp_server_send_unicast_raw(server
, packet
,
422 sizeof(DHCPPacket
) + optoffset
);
425 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
426 uint8_t type
, size_t *_optoffset
,
428 _cleanup_free_ DHCPPacket
*packet
= NULL
;
429 size_t optoffset
= 0;
435 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
437 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
441 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
442 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
443 req
->max_optlen
, &optoffset
);
447 packet
->dhcp
.flags
= req
->message
->flags
;
448 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
449 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
451 *_optoffset
= optoffset
;
458 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
460 _cleanup_free_ DHCPPacket
*packet
= NULL
;
465 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
469 packet
->dhcp
.yiaddr
= address
;
471 lease_time
= htobe32(req
->lifetime
);
472 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
473 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
478 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
479 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
483 if (server
->emit_router
) {
484 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
485 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
490 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
497 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
499 _cleanup_free_ DHCPPacket
*packet
= NULL
;
504 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
508 packet
->dhcp
.yiaddr
= address
;
510 lease_time
= htobe32(req
->lifetime
);
511 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
512 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
517 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
518 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
522 if (server
->emit_router
) {
523 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
524 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
529 if (server
->n_dns
> 0) {
530 r
= dhcp_option_append(
531 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
532 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
533 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
538 if (server
->n_ntp
> 0) {
539 r
= dhcp_option_append(
540 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
541 SD_DHCP_OPTION_NTP_SERVER
,
542 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
547 if (server
->timezone
) {
548 r
= dhcp_option_append(
549 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
550 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
551 strlen(server
->timezone
), server
->timezone
);
556 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
563 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
564 _cleanup_free_ DHCPPacket
*packet
= NULL
;
568 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
572 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
575 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
576 be32_t gateway
, uint8_t chaddr
[]) {
577 _cleanup_free_ DHCPPacket
*packet
= NULL
;
578 size_t optoffset
= 0;
582 assert(address
!= INADDR_ANY
);
585 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
589 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
590 DHCP_FORCERENEW
, ARPHRD_ETHER
,
591 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
595 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
596 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
600 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
602 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
604 sizeof(DHCPMessage
) + optoffset
);
611 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
612 DHCPRequest
*req
= userdata
;
617 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
619 req
->lifetime
= unaligned_read_be32(option
);
622 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
624 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
627 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
629 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
632 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
636 data
= memdup(option
, len
);
640 free(req
->client_id
.data
);
641 req
->client_id
.data
= data
;
642 req
->client_id
.length
= len
;
646 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
648 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
649 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
657 static void dhcp_request_free(DHCPRequest
*req
) {
661 free(req
->client_id
.data
);
665 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
666 #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
668 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
672 req
->message
= message
;
674 /* set client id based on MAC address if client did not send an explicit
676 if (!req
->client_id
.data
) {
679 data
= malloc0(ETH_ALEN
+ 1);
683 ((uint8_t*) data
)[0] = 0x01;
684 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
686 req
->client_id
.length
= ETH_ALEN
+ 1;
687 req
->client_id
.data
= data
;
690 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
691 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
693 if (req
->lifetime
<= 0)
694 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
696 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
697 req
->lifetime
= server
->max_lease_time
;
702 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
705 if (!server
->pool_size
)
708 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
709 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
712 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
715 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
717 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
719 _cleanup_dhcp_request_free_ DHCPRequest
*req
= NULL
;
720 _cleanup_free_
char *error_message
= NULL
;
721 DHCPLease
*existing_lease
;
727 if (message
->op
!= BOOTREQUEST
||
728 message
->htype
!= ARPHRD_ETHER
||
729 message
->hlen
!= ETHER_ADDR_LEN
)
732 req
= new0(DHCPRequest
, 1);
736 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
740 r
= ensure_sane_request(server
, req
, message
);
742 /* this only fails on critical errors */
745 existing_lease
= hashmap_get(server
->leases_by_client_id
,
750 case DHCP_DISCOVER
: {
751 be32_t address
= INADDR_ANY
;
754 log_dhcp_server(server
, "DISCOVER (0x%x)",
755 be32toh(req
->message
->xid
));
757 if (!server
->pool_size
)
758 /* no pool allocated */
761 /* for now pick a random free address from the pool */
763 address
= existing_lease
->address
;
765 struct siphash state
;
769 /* even with no persistence of leases, we try to offer the same client
770 the same IP address. we do this by using the hash of the client id
771 as the offset into the pool of leases when finding the next free one */
773 siphash24_init(&state
, HASH_KEY
.bytes
);
774 client_id_hash_func(&req
->client_id
, &state
);
775 hash
= htole64(siphash24_finalize(&state
));
776 next_offer
= hash
% server
->pool_size
;
778 for (i
= 0; i
< server
->pool_size
; i
++) {
779 if (!server
->bound_leases
[next_offer
]) {
780 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
783 next_offer
= (next_offer
+ 1) % server
->pool_size
;
787 if (address
== INADDR_ANY
)
788 /* no free addresses left */
791 r
= server_send_offer(server
, req
, address
);
793 /* this only fails on critical errors */
794 log_dhcp_server(server
, "could not send offer: %s",
798 log_dhcp_server(server
, "OFFER (0x%x)",
799 be32toh(req
->message
->xid
));
806 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
808 /* TODO: make sure we don't offer this address again */
814 bool init_reboot
= false;
817 /* see RFC 2131, section 4.3.2 */
819 if (req
->server_id
) {
820 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
821 be32toh(req
->message
->xid
));
824 if (req
->server_id
!= server
->address
)
825 /* client did not pick us */
828 if (req
->message
->ciaddr
)
829 /* this MUST be zero */
832 if (!req
->requested_ip
)
833 /* this must be filled in with the yiaddr
834 from the chosen OFFER */
837 address
= req
->requested_ip
;
838 } else if (req
->requested_ip
) {
839 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
840 be32toh(req
->message
->xid
));
843 if (req
->message
->ciaddr
)
844 /* this MUST be zero */
847 /* TODO: check more carefully if IP is correct */
848 address
= req
->requested_ip
;
851 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
852 be32toh(req
->message
->xid
));
854 /* REBINDING / RENEWING */
855 if (!req
->message
->ciaddr
)
856 /* this MUST be filled in with clients IP address */
859 address
= req
->message
->ciaddr
;
862 pool_offset
= get_pool_offset(server
, address
);
864 /* verify that the requested address is from the pool, and either
865 owned by the current client or free */
866 if (pool_offset
>= 0 &&
867 server
->bound_leases
[pool_offset
] == existing_lease
) {
871 if (!existing_lease
) {
872 lease
= new0(DHCPLease
, 1);
875 lease
->address
= address
;
876 lease
->client_id
.data
= memdup(req
->client_id
.data
,
877 req
->client_id
.length
);
878 if (!lease
->client_id
.data
) {
882 lease
->client_id
.length
= req
->client_id
.length
;
883 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
885 lease
->gateway
= req
->message
->giaddr
;
887 lease
= existing_lease
;
889 r
= sd_event_now(server
->event
,
890 clock_boottime_or_monotonic(),
894 dhcp_lease_free(lease
);
898 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
900 r
= server_send_ack(server
, req
, address
);
902 /* this only fails on critical errors */
903 log_dhcp_server(server
, "could not send ack: %s",
907 dhcp_lease_free(lease
);
911 log_dhcp_server(server
, "ACK (0x%x)",
912 be32toh(req
->message
->xid
));
914 server
->bound_leases
[pool_offset
] = lease
;
915 hashmap_put(server
->leases_by_client_id
,
916 &lease
->client_id
, lease
);
920 } else if (init_reboot
) {
921 r
= server_send_nak(server
, req
);
923 /* this only fails on critical errors */
924 log_dhcp_server(server
, "could not send nak: %s",
928 log_dhcp_server(server
, "NAK (0x%x)",
929 be32toh(req
->message
->xid
));
940 log_dhcp_server(server
, "RELEASE (0x%x)",
941 be32toh(req
->message
->xid
));
946 if (existing_lease
->address
!= req
->message
->ciaddr
)
949 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
953 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
954 server
->bound_leases
[pool_offset
] = NULL
;
955 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
956 dhcp_lease_free(existing_lease
);
967 static int server_receive_message(sd_event_source
*s
, int fd
,
968 uint32_t revents
, void *userdata
) {
969 _cleanup_free_ DHCPMessage
*message
= NULL
;
970 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
971 sd_dhcp_server
*server
= userdata
;
972 struct iovec iov
= {};
973 struct msghdr msg
= {
976 .msg_control
= cmsgbuf
,
977 .msg_controllen
= sizeof(cmsgbuf
),
979 struct cmsghdr
*cmsg
;
984 buflen
= next_datagram_size_fd(fd
);
988 message
= malloc(buflen
);
992 iov
.iov_base
= message
;
993 iov
.iov_len
= buflen
;
995 len
= recvmsg(fd
, &msg
, 0);
997 if (IN_SET(errno
, EAGAIN
, EINTR
))
1001 } else if ((size_t)len
< sizeof(DHCPMessage
))
1004 CMSG_FOREACH(cmsg
, &msg
) {
1005 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
1006 cmsg
->cmsg_type
== IP_PKTINFO
&&
1007 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
1008 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
1010 /* TODO figure out if this can be done as a filter on
1011 * the socket, like for IPv6 */
1012 if (server
->ifindex
!= info
->ipi_ifindex
)
1019 return dhcp_server_handle_message(server
, message
, (size_t)len
);
1022 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1025 assert_return(server
, -EINVAL
);
1026 assert_return(server
->event
, -EINVAL
);
1027 assert_return(!server
->receive_message
, -EBUSY
);
1028 assert_return(server
->fd_raw
== -1, -EBUSY
);
1029 assert_return(server
->fd
== -1, -EBUSY
);
1030 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1032 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1035 sd_dhcp_server_stop(server
);
1040 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
);
1042 sd_dhcp_server_stop(server
);
1047 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1048 server
->fd
, EPOLLIN
,
1049 server_receive_message
, server
);
1051 sd_dhcp_server_stop(server
);
1055 r
= sd_event_source_set_priority(server
->receive_message
,
1056 server
->event_priority
);
1058 sd_dhcp_server_stop(server
);
1062 log_dhcp_server(server
, "STARTED");
1067 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1071 assert_return(server
, -EINVAL
);
1072 assert(server
->bound_leases
);
1074 for (i
= 0; i
< server
->pool_size
; i
++) {
1075 DHCPLease
*lease
= server
->bound_leases
[i
];
1077 if (!lease
|| lease
== &server
->invalid_lease
)
1080 r
= server_send_forcerenew(server
, lease
->address
,
1086 log_dhcp_server(server
, "FORCERENEW");
1092 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1095 assert_return(server
, -EINVAL
);
1096 assert_return(timezone_is_valid(tz
), -EINVAL
);
1098 if (streq_ptr(tz
, server
->timezone
))
1101 r
= free_and_strdup(&server
->timezone
, tz
);
1108 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1109 assert_return(server
, -EINVAL
);
1111 if (t
== server
->max_lease_time
)
1114 server
->max_lease_time
= t
;
1118 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1119 assert_return(server
, -EINVAL
);
1121 if (t
== server
->default_lease_time
)
1124 server
->default_lease_time
= t
;
1128 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1129 assert_return(server
, -EINVAL
);
1130 assert_return(dns
|| n
<= 0, -EINVAL
);
1132 if (server
->n_dns
== n
&&
1133 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1137 server
->dns
= mfree(server
->dns
);
1142 c
= newdup(struct in_addr
, dns
, n
);
1154 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1155 assert_return(server
, -EINVAL
);
1156 assert_return(ntp
|| n
<= 0, -EINVAL
);
1158 if (server
->n_ntp
== n
&&
1159 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1163 server
->ntp
= mfree(server
->ntp
);
1168 c
= newdup(struct in_addr
, ntp
, n
);
1180 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1181 assert_return(server
, -EINVAL
);
1183 if (enabled
== server
->emit_router
)
1186 server
->emit_router
= enabled
;