1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright (C) 2013 Intel Corporation. All rights reserved.
4 Copyright (C) 2014 Tom Gundersen
9 #include "sd-dhcp-server.h"
11 #include "alloc-util.h"
12 #include "dhcp-internal.h"
13 #include "dhcp-server-internal.h"
15 #include "in-addr-util.h"
17 #include "siphash24.h"
18 #include "string-util.h"
19 #include "unaligned.h"
21 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
22 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
24 static void dhcp_lease_free(DHCPLease
*lease
) {
28 free(lease
->client_id
.data
);
32 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
33 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
34 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
35 * accidentally hand it out */
36 int sd_dhcp_server_configure_pool(sd_dhcp_server
*server
, struct in_addr
*address
, unsigned char prefixlen
, uint32_t offset
, uint32_t size
) {
37 struct in_addr netmask_addr
;
39 uint32_t server_off
, broadcast_off
, size_max
;
41 assert_return(server
, -EINVAL
);
42 assert_return(address
, -EINVAL
);
43 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
44 assert_return(prefixlen
<= 32, -ERANGE
);
46 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
47 netmask
= netmask_addr
.s_addr
;
49 server_off
= be32toh(address
->s_addr
& ~netmask
);
50 broadcast_off
= be32toh(~netmask
);
52 /* the server address cannot be the subnet address */
53 assert_return(server_off
!= 0, -ERANGE
);
55 /* nor the broadcast address */
56 assert_return(server_off
!= broadcast_off
, -ERANGE
);
58 /* 0 offset means we should set a default, we skip the first (subnet) address
59 and take the next one */
63 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
64 - offset
/* exclude the addresses before the offset */
65 - 1; /* exclude the last (broadcast) address */
67 /* The pool must contain at least one address */
68 assert_return(size_max
>= 1, -ERANGE
);
71 assert_return(size
<= size_max
, -ERANGE
);
75 if (server
->address
!= address
->s_addr
|| server
->netmask
!= netmask
|| server
->pool_size
!= size
|| server
->pool_offset
!= offset
) {
77 free(server
->bound_leases
);
78 server
->bound_leases
= new0(DHCPLease
*, size
);
79 if (!server
->bound_leases
)
82 server
->pool_offset
= offset
;
83 server
->pool_size
= size
;
85 server
->address
= address
->s_addr
;
86 server
->netmask
= netmask
;
87 server
->subnet
= address
->s_addr
& netmask
;
89 if (server_off
>= offset
&& server_off
- offset
< size
)
90 server
->bound_leases
[server_off
- offset
] = &server
->invalid_lease
;
92 /* Drop any leases associated with the old address range */
93 hashmap_clear_with_destructor(server
->leases_by_client_id
, dhcp_lease_free
);
99 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
100 assert_return(server
, false);
102 return !!server
->receive_message
;
105 sd_dhcp_server
*sd_dhcp_server_ref(sd_dhcp_server
*server
) {
110 assert(server
->n_ref
>= 1);
116 void client_id_hash_func(const void *p
, struct siphash
*state
) {
117 const DHCPClientId
*id
= p
;
123 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
124 siphash24_compress(id
->data
, id
->length
, state
);
127 int client_id_compare_func(const void *_a
, const void *_b
) {
128 const DHCPClientId
*a
, *b
;
133 assert(!a
->length
|| a
->data
);
134 assert(!b
->length
|| b
->data
);
136 if (a
->length
!= b
->length
)
137 return a
->length
< b
->length
? -1 : 1;
139 return memcmp(a
->data
, b
->data
, a
->length
);
142 static const struct hash_ops client_id_hash_ops
= {
143 .hash
= client_id_hash_func
,
144 .compare
= client_id_compare_func
147 sd_dhcp_server
*sd_dhcp_server_unref(sd_dhcp_server
*server
) {
153 assert(server
->n_ref
>= 1);
156 if (server
->n_ref
> 0)
159 log_dhcp_server(server
, "UNREF");
161 sd_dhcp_server_stop(server
);
163 sd_event_unref(server
->event
);
165 free(server
->timezone
);
169 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
170 dhcp_lease_free(lease
);
171 hashmap_free(server
->leases_by_client_id
);
173 free(server
->bound_leases
);
174 return mfree(server
);
177 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
178 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
180 assert_return(ret
, -EINVAL
);
181 assert_return(ifindex
> 0, -EINVAL
);
183 server
= new0(sd_dhcp_server
, 1);
190 server
->address
= htobe32(INADDR_ANY
);
191 server
->netmask
= htobe32(INADDR_ANY
);
192 server
->ifindex
= ifindex
;
194 server
->leases_by_client_id
= hashmap_new(&client_id_hash_ops
);
195 if (!server
->leases_by_client_id
)
198 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
199 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
201 *ret
= TAKE_PTR(server
);
206 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
209 assert_return(server
, -EINVAL
);
210 assert_return(!server
->event
, -EBUSY
);
213 server
->event
= sd_event_ref(event
);
215 r
= sd_event_default(&server
->event
);
220 server
->event_priority
= priority
;
225 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
226 assert_return(server
, -EINVAL
);
228 server
->event
= sd_event_unref(server
->event
);
233 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
234 assert_return(server
, NULL
);
236 return server
->event
;
239 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
240 assert_return(server
, -EINVAL
);
242 server
->receive_message
=
243 sd_event_source_unref(server
->receive_message
);
245 server
->fd_raw
= safe_close(server
->fd_raw
);
246 server
->fd
= safe_close(server
->fd
);
248 log_dhcp_server(server
, "STOPPED");
253 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
254 DHCPPacket
*packet
, size_t len
) {
255 union sockaddr_union link
= {
256 .ll
.sll_family
= AF_PACKET
,
257 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
258 .ll
.sll_ifindex
= server
->ifindex
,
259 .ll
.sll_halen
= ETH_ALEN
,
263 assert(server
->ifindex
> 0);
264 assert(server
->address
);
266 assert(len
> sizeof(DHCPPacket
));
268 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
270 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
272 DHCP_PORT_CLIENT
, len
);
274 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
277 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
278 uint16_t destination_port
,
279 DHCPMessage
*message
, size_t len
) {
280 union sockaddr_union dest
= {
281 .in
.sin_family
= AF_INET
,
282 .in
.sin_port
= htobe16(destination_port
),
283 .in
.sin_addr
.s_addr
= destination
,
289 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
290 struct msghdr msg
= {
292 .msg_namelen
= sizeof(dest
.in
),
295 .msg_control
= cmsgbuf
,
296 .msg_controllen
= sizeof(cmsgbuf
),
298 struct cmsghdr
*cmsg
;
299 struct in_pktinfo
*pktinfo
;
302 assert(server
->fd
>= 0);
304 assert(len
> sizeof(DHCPMessage
));
306 cmsg
= CMSG_FIRSTHDR(&msg
);
309 cmsg
->cmsg_level
= IPPROTO_IP
;
310 cmsg
->cmsg_type
= IP_PKTINFO
;
311 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
313 /* we attach source interface and address info to the message
314 rather than binding the socket. This will be mostly useful
315 when we gain support for arbitrary number of server addresses
317 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
320 pktinfo
->ipi_ifindex
= server
->ifindex
;
321 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
323 if (sendmsg(server
->fd
, &msg
, 0) < 0)
329 static bool requested_broadcast(DHCPRequest
*req
) {
332 return req
->message
->flags
& htobe16(0x8000);
335 int dhcp_server_send_packet(sd_dhcp_server
*server
,
336 DHCPRequest
*req
, DHCPPacket
*packet
,
337 int type
, size_t optoffset
) {
338 be32_t destination
= INADDR_ANY
;
339 uint16_t destination_port
= DHCP_PORT_CLIENT
;
344 assert(req
->max_optlen
);
345 assert(optoffset
<= req
->max_optlen
);
348 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
349 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
350 4, &server
->address
);
354 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
355 SD_DHCP_OPTION_END
, 0, NULL
);
359 /* RFC 2131 Section 4.1
361 If the ’giaddr’ field in a DHCP message from a client is non-zero,
362 the server sends any return messages to the ’DHCP server’ port on the
363 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
364 field is zero and the ’ciaddr’ field is nonzero, then the server
365 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
366 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
367 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
368 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
369 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
370 messages to the client’s hardware address and ’yiaddr’ address. In
371 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
372 messages to 0xffffffff.
376 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
377 different subnet. The server MUST set the broadcast bit in the
378 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
379 client, because the client may not have a correct network address
380 or subnet mask, and the client may not be answering ARP requests.
382 if (req
->message
->giaddr
) {
383 destination
= req
->message
->giaddr
;
384 destination_port
= DHCP_PORT_SERVER
;
385 if (type
== DHCP_NAK
)
386 packet
->dhcp
.flags
= htobe16(0x8000);
387 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
388 destination
= req
->message
->ciaddr
;
390 if (destination
!= INADDR_ANY
)
391 return dhcp_server_send_udp(server
, destination
,
392 destination_port
, &packet
->dhcp
,
393 sizeof(DHCPMessage
) + optoffset
);
394 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
395 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
396 destination_port
, &packet
->dhcp
,
397 sizeof(DHCPMessage
) + optoffset
);
399 /* we cannot send UDP packet to specific MAC address when the
400 address is not yet configured, so must fall back to raw
402 return dhcp_server_send_unicast_raw(server
, packet
,
403 sizeof(DHCPPacket
) + optoffset
);
406 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
407 uint8_t type
, size_t *_optoffset
,
409 _cleanup_free_ DHCPPacket
*packet
= NULL
;
410 size_t optoffset
= 0;
416 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
418 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
422 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
423 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
424 req
->max_optlen
, &optoffset
);
428 packet
->dhcp
.flags
= req
->message
->flags
;
429 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
430 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
432 *_optoffset
= optoffset
;
433 *ret
= TAKE_PTR(packet
);
438 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
440 _cleanup_free_ DHCPPacket
*packet
= NULL
;
445 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
449 packet
->dhcp
.yiaddr
= address
;
451 lease_time
= htobe32(req
->lifetime
);
452 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
453 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
458 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
459 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
463 if (server
->emit_router
) {
464 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
465 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
470 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
477 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
479 _cleanup_free_ DHCPPacket
*packet
= NULL
;
484 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
488 packet
->dhcp
.yiaddr
= address
;
490 lease_time
= htobe32(req
->lifetime
);
491 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
492 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
497 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
498 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
502 if (server
->emit_router
) {
503 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
504 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
509 if (server
->n_dns
> 0) {
510 r
= dhcp_option_append(
511 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
512 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
513 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
518 if (server
->n_ntp
> 0) {
519 r
= dhcp_option_append(
520 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
521 SD_DHCP_OPTION_NTP_SERVER
,
522 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
527 if (server
->timezone
) {
528 r
= dhcp_option_append(
529 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
530 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
531 strlen(server
->timezone
), server
->timezone
);
536 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
543 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
544 _cleanup_free_ DHCPPacket
*packet
= NULL
;
548 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
552 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
555 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
556 be32_t gateway
, uint8_t chaddr
[]) {
557 _cleanup_free_ DHCPPacket
*packet
= NULL
;
558 size_t optoffset
= 0;
562 assert(address
!= INADDR_ANY
);
565 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
569 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
570 DHCP_FORCERENEW
, ARPHRD_ETHER
,
571 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
575 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
576 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
580 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
582 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
584 sizeof(DHCPMessage
) + optoffset
);
591 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
592 DHCPRequest
*req
= userdata
;
597 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
599 req
->lifetime
= unaligned_read_be32(option
);
602 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
604 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
607 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
609 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
612 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
616 data
= memdup(option
, len
);
620 free(req
->client_id
.data
);
621 req
->client_id
.data
= data
;
622 req
->client_id
.length
= len
;
626 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
628 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
629 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
637 static void dhcp_request_free(DHCPRequest
*req
) {
641 free(req
->client_id
.data
);
645 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
647 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
651 req
->message
= message
;
653 /* set client id based on MAC address if client did not send an explicit
655 if (!req
->client_id
.data
) {
658 data
= malloc0(ETH_ALEN
+ 1);
662 ((uint8_t*) data
)[0] = 0x01;
663 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
665 req
->client_id
.length
= ETH_ALEN
+ 1;
666 req
->client_id
.data
= data
;
669 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
670 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
672 if (req
->lifetime
<= 0)
673 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
675 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
676 req
->lifetime
= server
->max_lease_time
;
681 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
684 if (!server
->pool_size
)
687 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
688 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
691 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
694 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
696 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
698 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
699 _cleanup_free_
char *error_message
= NULL
;
700 DHCPLease
*existing_lease
;
706 if (message
->op
!= BOOTREQUEST
||
707 message
->htype
!= ARPHRD_ETHER
||
708 message
->hlen
!= ETHER_ADDR_LEN
)
711 req
= new0(DHCPRequest
, 1);
715 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
719 r
= ensure_sane_request(server
, req
, message
);
721 /* this only fails on critical errors */
724 existing_lease
= hashmap_get(server
->leases_by_client_id
,
729 case DHCP_DISCOVER
: {
730 be32_t address
= INADDR_ANY
;
733 log_dhcp_server(server
, "DISCOVER (0x%x)",
734 be32toh(req
->message
->xid
));
736 if (!server
->pool_size
)
737 /* no pool allocated */
740 /* for now pick a random free address from the pool */
742 address
= existing_lease
->address
;
744 struct siphash state
;
748 /* even with no persistence of leases, we try to offer the same client
749 the same IP address. we do this by using the hash of the client id
750 as the offset into the pool of leases when finding the next free one */
752 siphash24_init(&state
, HASH_KEY
.bytes
);
753 client_id_hash_func(&req
->client_id
, &state
);
754 hash
= htole64(siphash24_finalize(&state
));
755 next_offer
= hash
% server
->pool_size
;
757 for (i
= 0; i
< server
->pool_size
; i
++) {
758 if (!server
->bound_leases
[next_offer
]) {
759 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
763 next_offer
= (next_offer
+ 1) % server
->pool_size
;
767 if (address
== INADDR_ANY
)
768 /* no free addresses left */
771 r
= server_send_offer(server
, req
, address
);
773 /* this only fails on critical errors */
774 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
776 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
780 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
782 /* TODO: make sure we don't offer this address again */
788 bool init_reboot
= false;
791 /* see RFC 2131, section 4.3.2 */
793 if (req
->server_id
) {
794 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
795 be32toh(req
->message
->xid
));
798 if (req
->server_id
!= server
->address
)
799 /* client did not pick us */
802 if (req
->message
->ciaddr
)
803 /* this MUST be zero */
806 if (!req
->requested_ip
)
807 /* this must be filled in with the yiaddr
808 from the chosen OFFER */
811 address
= req
->requested_ip
;
812 } else if (req
->requested_ip
) {
813 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
814 be32toh(req
->message
->xid
));
817 if (req
->message
->ciaddr
)
818 /* this MUST be zero */
821 /* TODO: check more carefully if IP is correct */
822 address
= req
->requested_ip
;
825 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
826 be32toh(req
->message
->xid
));
828 /* REBINDING / RENEWING */
829 if (!req
->message
->ciaddr
)
830 /* this MUST be filled in with clients IP address */
833 address
= req
->message
->ciaddr
;
836 pool_offset
= get_pool_offset(server
, address
);
838 /* verify that the requested address is from the pool, and either
839 owned by the current client or free */
840 if (pool_offset
>= 0 &&
841 server
->bound_leases
[pool_offset
] == existing_lease
) {
845 if (!existing_lease
) {
846 lease
= new0(DHCPLease
, 1);
849 lease
->address
= address
;
850 lease
->client_id
.data
= memdup(req
->client_id
.data
,
851 req
->client_id
.length
);
852 if (!lease
->client_id
.data
) {
856 lease
->client_id
.length
= req
->client_id
.length
;
857 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
859 lease
->gateway
= req
->message
->giaddr
;
861 lease
= existing_lease
;
863 r
= sd_event_now(server
->event
,
864 clock_boottime_or_monotonic(),
868 dhcp_lease_free(lease
);
872 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
874 r
= server_send_ack(server
, req
, address
);
876 /* this only fails on critical errors */
877 log_dhcp_server_errno(server
, r
, "Could not send ack: %m");
880 dhcp_lease_free(lease
);
884 log_dhcp_server(server
, "ACK (0x%x)",
885 be32toh(req
->message
->xid
));
887 server
->bound_leases
[pool_offset
] = lease
;
888 hashmap_put(server
->leases_by_client_id
,
889 &lease
->client_id
, lease
);
894 } else if (init_reboot
) {
895 r
= server_send_nak(server
, req
);
897 /* this only fails on critical errors */
898 return log_dhcp_server_errno(server
, r
, "Could not send nak: %m");
900 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
910 log_dhcp_server(server
, "RELEASE (0x%x)",
911 be32toh(req
->message
->xid
));
916 if (existing_lease
->address
!= req
->message
->ciaddr
)
919 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
923 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
924 server
->bound_leases
[pool_offset
] = NULL
;
925 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
926 dhcp_lease_free(existing_lease
);
935 static int server_receive_message(sd_event_source
*s
, int fd
,
936 uint32_t revents
, void *userdata
) {
937 _cleanup_free_ DHCPMessage
*message
= NULL
;
938 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
939 sd_dhcp_server
*server
= userdata
;
940 struct iovec iov
= {};
941 struct msghdr msg
= {
944 .msg_control
= cmsgbuf
,
945 .msg_controllen
= sizeof(cmsgbuf
),
947 struct cmsghdr
*cmsg
;
953 buflen
= next_datagram_size_fd(fd
);
957 message
= malloc(buflen
);
961 iov
.iov_base
= message
;
962 iov
.iov_len
= buflen
;
964 len
= recvmsg(fd
, &msg
, 0);
966 if (IN_SET(errno
, EAGAIN
, EINTR
))
971 if ((size_t)len
< sizeof(DHCPMessage
))
974 CMSG_FOREACH(cmsg
, &msg
) {
975 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
976 cmsg
->cmsg_type
== IP_PKTINFO
&&
977 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
978 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
980 /* TODO figure out if this can be done as a filter on
981 * the socket, like for IPv6 */
982 if (server
->ifindex
!= info
->ipi_ifindex
)
989 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
991 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message: %m");
996 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
999 assert_return(server
, -EINVAL
);
1000 assert_return(server
->event
, -EINVAL
);
1001 assert_return(!server
->receive_message
, -EBUSY
);
1002 assert_return(server
->fd_raw
< 0, -EBUSY
);
1003 assert_return(server
->fd
< 0, -EBUSY
);
1004 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1006 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1009 sd_dhcp_server_stop(server
);
1014 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
);
1016 sd_dhcp_server_stop(server
);
1021 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1022 server
->fd
, EPOLLIN
,
1023 server_receive_message
, server
);
1025 sd_dhcp_server_stop(server
);
1029 r
= sd_event_source_set_priority(server
->receive_message
,
1030 server
->event_priority
);
1032 sd_dhcp_server_stop(server
);
1036 log_dhcp_server(server
, "STARTED");
1041 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1045 assert_return(server
, -EINVAL
);
1046 assert(server
->bound_leases
);
1048 for (i
= 0; i
< server
->pool_size
; i
++) {
1049 DHCPLease
*lease
= server
->bound_leases
[i
];
1051 if (!lease
|| lease
== &server
->invalid_lease
)
1054 r
= server_send_forcerenew(server
, lease
->address
,
1060 log_dhcp_server(server
, "FORCERENEW");
1066 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1069 assert_return(server
, -EINVAL
);
1070 assert_return(timezone_is_valid(tz
, LOG_DEBUG
), -EINVAL
);
1072 if (streq_ptr(tz
, server
->timezone
))
1075 r
= free_and_strdup(&server
->timezone
, tz
);
1082 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1083 assert_return(server
, -EINVAL
);
1085 if (t
== server
->max_lease_time
)
1088 server
->max_lease_time
= t
;
1092 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1093 assert_return(server
, -EINVAL
);
1095 if (t
== server
->default_lease_time
)
1098 server
->default_lease_time
= t
;
1102 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1103 assert_return(server
, -EINVAL
);
1104 assert_return(dns
|| n
<= 0, -EINVAL
);
1106 if (server
->n_dns
== n
&&
1107 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1111 server
->dns
= mfree(server
->dns
);
1116 c
= newdup(struct in_addr
, dns
, n
);
1128 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1129 assert_return(server
, -EINVAL
);
1130 assert_return(ntp
|| n
<= 0, -EINVAL
);
1132 if (server
->n_ntp
== n
&&
1133 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1137 server
->ntp
= mfree(server
->ntp
);
1142 c
= newdup(struct in_addr
, ntp
, n
);
1154 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1155 assert_return(server
, -EINVAL
);
1157 if (enabled
== server
->emit_router
)
1160 server
->emit_router
= enabled
;