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
11 #include "sd-dhcp-server.h"
13 #include "alloc-util.h"
14 #include "dhcp-internal.h"
15 #include "dhcp-server-internal.h"
17 #include "in-addr-util.h"
19 #include "siphash24.h"
20 #include "string-util.h"
21 #include "unaligned.h"
23 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
24 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
26 static void dhcp_lease_free(DHCPLease
*lease
) {
30 free(lease
->client_id
.data
);
34 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
35 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
36 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
37 * accidentally hand it out */
38 int sd_dhcp_server_configure_pool(sd_dhcp_server
*server
, struct in_addr
*address
, unsigned char prefixlen
, uint32_t offset
, uint32_t size
) {
39 struct in_addr netmask_addr
;
41 uint32_t server_off
, broadcast_off
, size_max
;
43 assert_return(server
, -EINVAL
);
44 assert_return(address
, -EINVAL
);
45 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
46 assert_return(prefixlen
<= 32, -ERANGE
);
48 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
49 netmask
= netmask_addr
.s_addr
;
51 server_off
= be32toh(address
->s_addr
& ~netmask
);
52 broadcast_off
= be32toh(~netmask
);
54 /* the server address cannot be the subnet address */
55 assert_return(server_off
!= 0, -ERANGE
);
57 /* nor the broadcast address */
58 assert_return(server_off
!= broadcast_off
, -ERANGE
);
60 /* 0 offset means we should set a default, we skip the first (subnet) address
61 and take the next one */
65 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
66 - offset
/* exclude the addresses before the offset */
67 - 1; /* exclude the last (broadcast) address */
69 /* The pool must contain at least one address */
70 assert_return(size_max
>= 1, -ERANGE
);
73 assert_return(size
<= size_max
, -ERANGE
);
77 if (server
->address
!= address
->s_addr
|| server
->netmask
!= netmask
|| server
->pool_size
!= size
|| server
->pool_offset
!= offset
) {
79 free(server
->bound_leases
);
80 server
->bound_leases
= new0(DHCPLease
*, size
);
81 if (!server
->bound_leases
)
84 server
->pool_offset
= offset
;
85 server
->pool_size
= size
;
87 server
->address
= address
->s_addr
;
88 server
->netmask
= netmask
;
89 server
->subnet
= address
->s_addr
& netmask
;
91 if (server_off
>= offset
&& server_off
- offset
< size
)
92 server
->bound_leases
[server_off
- offset
] = &server
->invalid_lease
;
94 /* Drop any leases associated with the old address range */
95 hashmap_clear_with_destructor(server
->leases_by_client_id
, dhcp_lease_free
);
101 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
102 assert_return(server
, false);
104 return !!server
->receive_message
;
107 sd_dhcp_server
*sd_dhcp_server_ref(sd_dhcp_server
*server
) {
112 assert(server
->n_ref
>= 1);
118 void client_id_hash_func(const void *p
, struct siphash
*state
) {
119 const DHCPClientId
*id
= p
;
125 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
126 siphash24_compress(id
->data
, id
->length
, state
);
129 int client_id_compare_func(const void *_a
, const void *_b
) {
130 const DHCPClientId
*a
, *b
;
135 assert(!a
->length
|| a
->data
);
136 assert(!b
->length
|| b
->data
);
138 if (a
->length
!= b
->length
)
139 return a
->length
< b
->length
? -1 : 1;
141 return memcmp(a
->data
, b
->data
, a
->length
);
144 static const struct hash_ops client_id_hash_ops
= {
145 .hash
= client_id_hash_func
,
146 .compare
= client_id_compare_func
149 sd_dhcp_server
*sd_dhcp_server_unref(sd_dhcp_server
*server
) {
155 assert(server
->n_ref
>= 1);
158 if (server
->n_ref
> 0)
161 log_dhcp_server(server
, "UNREF");
163 sd_dhcp_server_stop(server
);
165 sd_event_unref(server
->event
);
167 free(server
->timezone
);
171 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
172 dhcp_lease_free(lease
);
173 hashmap_free(server
->leases_by_client_id
);
175 free(server
->bound_leases
);
176 return mfree(server
);
179 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
180 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
182 assert_return(ret
, -EINVAL
);
183 assert_return(ifindex
> 0, -EINVAL
);
185 server
= new0(sd_dhcp_server
, 1);
192 server
->address
= htobe32(INADDR_ANY
);
193 server
->netmask
= htobe32(INADDR_ANY
);
194 server
->ifindex
= ifindex
;
196 server
->leases_by_client_id
= hashmap_new(&client_id_hash_ops
);
197 if (!server
->leases_by_client_id
)
200 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
201 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
203 *ret
= TAKE_PTR(server
);
208 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
211 assert_return(server
, -EINVAL
);
212 assert_return(!server
->event
, -EBUSY
);
215 server
->event
= sd_event_ref(event
);
217 r
= sd_event_default(&server
->event
);
222 server
->event_priority
= priority
;
227 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
228 assert_return(server
, -EINVAL
);
230 server
->event
= sd_event_unref(server
->event
);
235 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
236 assert_return(server
, NULL
);
238 return server
->event
;
241 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
242 assert_return(server
, -EINVAL
);
244 server
->receive_message
=
245 sd_event_source_unref(server
->receive_message
);
247 server
->fd_raw
= safe_close(server
->fd_raw
);
248 server
->fd
= safe_close(server
->fd
);
250 log_dhcp_server(server
, "STOPPED");
255 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
256 DHCPPacket
*packet
, size_t len
) {
257 union sockaddr_union link
= {
258 .ll
.sll_family
= AF_PACKET
,
259 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
260 .ll
.sll_ifindex
= server
->ifindex
,
261 .ll
.sll_halen
= ETH_ALEN
,
265 assert(server
->ifindex
> 0);
266 assert(server
->address
);
268 assert(len
> sizeof(DHCPPacket
));
270 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
272 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
274 DHCP_PORT_CLIENT
, len
);
276 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
279 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
280 uint16_t destination_port
,
281 DHCPMessage
*message
, size_t len
) {
282 union sockaddr_union dest
= {
283 .in
.sin_family
= AF_INET
,
284 .in
.sin_port
= htobe16(destination_port
),
285 .in
.sin_addr
.s_addr
= destination
,
291 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
292 struct msghdr msg
= {
294 .msg_namelen
= sizeof(dest
.in
),
297 .msg_control
= cmsgbuf
,
298 .msg_controllen
= sizeof(cmsgbuf
),
300 struct cmsghdr
*cmsg
;
301 struct in_pktinfo
*pktinfo
;
304 assert(server
->fd
>= 0);
306 assert(len
> sizeof(DHCPMessage
));
308 cmsg
= CMSG_FIRSTHDR(&msg
);
311 cmsg
->cmsg_level
= IPPROTO_IP
;
312 cmsg
->cmsg_type
= IP_PKTINFO
;
313 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
315 /* we attach source interface and address info to the message
316 rather than binding the socket. This will be mostly useful
317 when we gain support for arbitrary number of server addresses
319 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
322 pktinfo
->ipi_ifindex
= server
->ifindex
;
323 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
325 if (sendmsg(server
->fd
, &msg
, 0) < 0)
331 static bool requested_broadcast(DHCPRequest
*req
) {
334 return req
->message
->flags
& htobe16(0x8000);
337 int dhcp_server_send_packet(sd_dhcp_server
*server
,
338 DHCPRequest
*req
, DHCPPacket
*packet
,
339 int type
, size_t optoffset
) {
340 be32_t destination
= INADDR_ANY
;
341 uint16_t destination_port
= DHCP_PORT_CLIENT
;
346 assert(req
->max_optlen
);
347 assert(optoffset
<= req
->max_optlen
);
350 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
351 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
352 4, &server
->address
);
356 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
357 SD_DHCP_OPTION_END
, 0, NULL
);
361 /* RFC 2131 Section 4.1
363 If the ’giaddr’ field in a DHCP message from a client is non-zero,
364 the server sends any return messages to the ’DHCP server’ port on the
365 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
366 field is zero and the ’ciaddr’ field is nonzero, then the server
367 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
368 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
369 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
370 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
371 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
372 messages to the client’s hardware address and ’yiaddr’ address. In
373 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
374 messages to 0xffffffff.
378 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
379 different subnet. The server MUST set the broadcast bit in the
380 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
381 client, because the client may not have a correct network address
382 or subnet mask, and the client may not be answering ARP requests.
384 if (req
->message
->giaddr
) {
385 destination
= req
->message
->giaddr
;
386 destination_port
= DHCP_PORT_SERVER
;
387 if (type
== DHCP_NAK
)
388 packet
->dhcp
.flags
= htobe16(0x8000);
389 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
390 destination
= req
->message
->ciaddr
;
392 if (destination
!= INADDR_ANY
)
393 return dhcp_server_send_udp(server
, destination
,
394 destination_port
, &packet
->dhcp
,
395 sizeof(DHCPMessage
) + optoffset
);
396 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
397 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
398 destination_port
, &packet
->dhcp
,
399 sizeof(DHCPMessage
) + optoffset
);
401 /* we cannot send UDP packet to specific MAC address when the
402 address is not yet configured, so must fall back to raw
404 return dhcp_server_send_unicast_raw(server
, packet
,
405 sizeof(DHCPPacket
) + optoffset
);
408 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
409 uint8_t type
, size_t *_optoffset
,
411 _cleanup_free_ DHCPPacket
*packet
= NULL
;
412 size_t optoffset
= 0;
418 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
420 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
424 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
425 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
426 req
->max_optlen
, &optoffset
);
430 packet
->dhcp
.flags
= req
->message
->flags
;
431 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
432 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
434 *_optoffset
= optoffset
;
435 *ret
= TAKE_PTR(packet
);
440 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
442 _cleanup_free_ DHCPPacket
*packet
= NULL
;
447 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
451 packet
->dhcp
.yiaddr
= address
;
453 lease_time
= htobe32(req
->lifetime
);
454 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
455 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
460 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
461 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
465 if (server
->emit_router
) {
466 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
467 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
472 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
479 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
481 _cleanup_free_ DHCPPacket
*packet
= NULL
;
486 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
490 packet
->dhcp
.yiaddr
= address
;
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,
499 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
500 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
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
);
511 if (server
->n_dns
> 0) {
512 r
= dhcp_option_append(
513 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
514 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
515 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
520 if (server
->n_ntp
> 0) {
521 r
= dhcp_option_append(
522 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
523 SD_DHCP_OPTION_NTP_SERVER
,
524 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
529 if (server
->timezone
) {
530 r
= dhcp_option_append(
531 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
532 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
533 strlen(server
->timezone
), server
->timezone
);
538 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
545 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
546 _cleanup_free_ DHCPPacket
*packet
= NULL
;
550 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
554 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
557 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
558 be32_t gateway
, uint8_t chaddr
[]) {
559 _cleanup_free_ DHCPPacket
*packet
= NULL
;
560 size_t optoffset
= 0;
564 assert(address
!= INADDR_ANY
);
567 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
571 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
572 DHCP_FORCERENEW
, ARPHRD_ETHER
,
573 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
577 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
578 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
582 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
584 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
586 sizeof(DHCPMessage
) + optoffset
);
593 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
594 DHCPRequest
*req
= userdata
;
599 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
601 req
->lifetime
= unaligned_read_be32(option
);
604 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
606 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
609 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
611 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
614 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
618 data
= memdup(option
, len
);
622 free(req
->client_id
.data
);
623 req
->client_id
.data
= data
;
624 req
->client_id
.length
= len
;
628 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
630 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
631 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
639 static void dhcp_request_free(DHCPRequest
*req
) {
643 free(req
->client_id
.data
);
647 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
649 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
653 req
->message
= message
;
655 /* set client id based on MAC address if client did not send an explicit
657 if (!req
->client_id
.data
) {
660 data
= malloc0(ETH_ALEN
+ 1);
664 ((uint8_t*) data
)[0] = 0x01;
665 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
667 req
->client_id
.length
= ETH_ALEN
+ 1;
668 req
->client_id
.data
= data
;
671 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
672 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
674 if (req
->lifetime
<= 0)
675 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
677 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
678 req
->lifetime
= server
->max_lease_time
;
683 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
686 if (!server
->pool_size
)
689 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
690 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
693 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
696 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
698 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
700 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
701 _cleanup_free_
char *error_message
= NULL
;
702 DHCPLease
*existing_lease
;
708 if (message
->op
!= BOOTREQUEST
||
709 message
->htype
!= ARPHRD_ETHER
||
710 message
->hlen
!= ETHER_ADDR_LEN
)
713 req
= new0(DHCPRequest
, 1);
717 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
721 r
= ensure_sane_request(server
, req
, message
);
723 /* this only fails on critical errors */
726 existing_lease
= hashmap_get(server
->leases_by_client_id
,
731 case DHCP_DISCOVER
: {
732 be32_t address
= INADDR_ANY
;
735 log_dhcp_server(server
, "DISCOVER (0x%x)",
736 be32toh(req
->message
->xid
));
738 if (!server
->pool_size
)
739 /* no pool allocated */
742 /* for now pick a random free address from the pool */
744 address
= existing_lease
->address
;
746 struct siphash state
;
750 /* even with no persistence of leases, we try to offer the same client
751 the same IP address. we do this by using the hash of the client id
752 as the offset into the pool of leases when finding the next free one */
754 siphash24_init(&state
, HASH_KEY
.bytes
);
755 client_id_hash_func(&req
->client_id
, &state
);
756 hash
= htole64(siphash24_finalize(&state
));
757 next_offer
= hash
% server
->pool_size
;
759 for (i
= 0; i
< server
->pool_size
; i
++) {
760 if (!server
->bound_leases
[next_offer
]) {
761 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
765 next_offer
= (next_offer
+ 1) % server
->pool_size
;
769 if (address
== INADDR_ANY
)
770 /* no free addresses left */
773 r
= server_send_offer(server
, req
, address
);
775 /* this only fails on critical errors */
776 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
778 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
782 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
784 /* TODO: make sure we don't offer this address again */
790 bool init_reboot
= false;
793 /* see RFC 2131, section 4.3.2 */
795 if (req
->server_id
) {
796 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
797 be32toh(req
->message
->xid
));
800 if (req
->server_id
!= server
->address
)
801 /* client did not pick us */
804 if (req
->message
->ciaddr
)
805 /* this MUST be zero */
808 if (!req
->requested_ip
)
809 /* this must be filled in with the yiaddr
810 from the chosen OFFER */
813 address
= req
->requested_ip
;
814 } else if (req
->requested_ip
) {
815 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
816 be32toh(req
->message
->xid
));
819 if (req
->message
->ciaddr
)
820 /* this MUST be zero */
823 /* TODO: check more carefully if IP is correct */
824 address
= req
->requested_ip
;
827 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
828 be32toh(req
->message
->xid
));
830 /* REBINDING / RENEWING */
831 if (!req
->message
->ciaddr
)
832 /* this MUST be filled in with clients IP address */
835 address
= req
->message
->ciaddr
;
838 pool_offset
= get_pool_offset(server
, address
);
840 /* verify that the requested address is from the pool, and either
841 owned by the current client or free */
842 if (pool_offset
>= 0 &&
843 server
->bound_leases
[pool_offset
] == existing_lease
) {
847 if (!existing_lease
) {
848 lease
= new0(DHCPLease
, 1);
851 lease
->address
= address
;
852 lease
->client_id
.data
= memdup(req
->client_id
.data
,
853 req
->client_id
.length
);
854 if (!lease
->client_id
.data
) {
858 lease
->client_id
.length
= req
->client_id
.length
;
859 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
861 lease
->gateway
= req
->message
->giaddr
;
863 lease
= existing_lease
;
865 r
= sd_event_now(server
->event
,
866 clock_boottime_or_monotonic(),
870 dhcp_lease_free(lease
);
874 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
876 r
= server_send_ack(server
, req
, address
);
878 /* this only fails on critical errors */
879 log_dhcp_server_errno(server
, r
, "Could not send ack: %m");
882 dhcp_lease_free(lease
);
886 log_dhcp_server(server
, "ACK (0x%x)",
887 be32toh(req
->message
->xid
));
889 server
->bound_leases
[pool_offset
] = lease
;
890 hashmap_put(server
->leases_by_client_id
,
891 &lease
->client_id
, lease
);
896 } else if (init_reboot
) {
897 r
= server_send_nak(server
, req
);
899 /* this only fails on critical errors */
900 return log_dhcp_server_errno(server
, r
, "Could not send nak: %m");
902 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
912 log_dhcp_server(server
, "RELEASE (0x%x)",
913 be32toh(req
->message
->xid
));
918 if (existing_lease
->address
!= req
->message
->ciaddr
)
921 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
925 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
926 server
->bound_leases
[pool_offset
] = NULL
;
927 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
928 dhcp_lease_free(existing_lease
);
937 static int server_receive_message(sd_event_source
*s
, int fd
,
938 uint32_t revents
, void *userdata
) {
939 _cleanup_free_ DHCPMessage
*message
= NULL
;
940 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
941 sd_dhcp_server
*server
= userdata
;
942 struct iovec iov
= {};
943 struct msghdr msg
= {
946 .msg_control
= cmsgbuf
,
947 .msg_controllen
= sizeof(cmsgbuf
),
949 struct cmsghdr
*cmsg
;
955 buflen
= next_datagram_size_fd(fd
);
959 message
= malloc(buflen
);
963 iov
.iov_base
= message
;
964 iov
.iov_len
= buflen
;
966 len
= recvmsg(fd
, &msg
, 0);
968 if (IN_SET(errno
, EAGAIN
, EINTR
))
973 if ((size_t)len
< sizeof(DHCPMessage
))
976 CMSG_FOREACH(cmsg
, &msg
) {
977 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
978 cmsg
->cmsg_type
== IP_PKTINFO
&&
979 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
980 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
982 /* TODO figure out if this can be done as a filter on
983 * the socket, like for IPv6 */
984 if (server
->ifindex
!= info
->ipi_ifindex
)
991 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
993 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message: %m");
998 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1001 assert_return(server
, -EINVAL
);
1002 assert_return(server
->event
, -EINVAL
);
1003 assert_return(!server
->receive_message
, -EBUSY
);
1004 assert_return(server
->fd_raw
< 0, -EBUSY
);
1005 assert_return(server
->fd
< 0, -EBUSY
);
1006 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1008 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1011 sd_dhcp_server_stop(server
);
1016 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
);
1018 sd_dhcp_server_stop(server
);
1023 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1024 server
->fd
, EPOLLIN
,
1025 server_receive_message
, server
);
1027 sd_dhcp_server_stop(server
);
1031 r
= sd_event_source_set_priority(server
->receive_message
,
1032 server
->event_priority
);
1034 sd_dhcp_server_stop(server
);
1038 log_dhcp_server(server
, "STARTED");
1043 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1047 assert_return(server
, -EINVAL
);
1048 assert(server
->bound_leases
);
1050 for (i
= 0; i
< server
->pool_size
; i
++) {
1051 DHCPLease
*lease
= server
->bound_leases
[i
];
1053 if (!lease
|| lease
== &server
->invalid_lease
)
1056 r
= server_send_forcerenew(server
, lease
->address
,
1062 log_dhcp_server(server
, "FORCERENEW");
1068 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1071 assert_return(server
, -EINVAL
);
1072 assert_return(timezone_is_valid(tz
), -EINVAL
);
1074 if (streq_ptr(tz
, server
->timezone
))
1077 r
= free_and_strdup(&server
->timezone
, tz
);
1084 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1085 assert_return(server
, -EINVAL
);
1087 if (t
== server
->max_lease_time
)
1090 server
->max_lease_time
= t
;
1094 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1095 assert_return(server
, -EINVAL
);
1097 if (t
== server
->default_lease_time
)
1100 server
->default_lease_time
= t
;
1104 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1105 assert_return(server
, -EINVAL
);
1106 assert_return(dns
|| n
<= 0, -EINVAL
);
1108 if (server
->n_dns
== n
&&
1109 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1113 server
->dns
= mfree(server
->dns
);
1118 c
= newdup(struct in_addr
, dns
, n
);
1130 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1131 assert_return(server
, -EINVAL
);
1132 assert_return(ntp
|| n
<= 0, -EINVAL
);
1134 if (server
->n_ntp
== n
&&
1135 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1139 server
->ntp
= mfree(server
->ntp
);
1144 c
= newdup(struct in_addr
, ntp
, n
);
1156 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1157 assert_return(server
, -EINVAL
);
1159 if (enabled
== server
->emit_router
)
1162 server
->emit_router
= enabled
;