1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
8 #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 DHCPLease
*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(server
->leases_by_client_id
);
99 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
100 assert_return(server
, false);
102 return !!server
->receive_message
;
105 void client_id_hash_func(const DHCPClientId
*id
, struct siphash
*state
) {
110 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
111 siphash24_compress(id
->data
, id
->length
, state
);
114 int client_id_compare_func(const DHCPClientId
*a
, const DHCPClientId
*b
) {
117 assert(!a
->length
|| a
->data
);
118 assert(!b
->length
|| b
->data
);
120 r
= CMP(a
->length
, b
->length
);
124 return memcmp(a
->data
, b
->data
, a
->length
);
127 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(dhcp_lease_hash_ops
, DHCPClientId
, client_id_hash_func
, client_id_compare_func
,
128 DHCPLease
, dhcp_lease_free
);
130 static sd_dhcp_server
*dhcp_server_free(sd_dhcp_server
*server
) {
133 log_dhcp_server(server
, "UNREF");
135 sd_dhcp_server_stop(server
);
137 sd_event_unref(server
->event
);
139 free(server
->timezone
);
143 free(server
->pop3_server
);
144 free(server
->smtp_server
);
146 hashmap_free(server
->leases_by_client_id
);
148 ordered_hashmap_free(server
->extra_options
);
149 ordered_hashmap_free(server
->vendor_options
);
151 free(server
->bound_leases
);
152 return mfree(server
);
155 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server
, sd_dhcp_server
, dhcp_server_free
);
157 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
158 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
160 assert_return(ret
, -EINVAL
);
161 assert_return(ifindex
> 0, -EINVAL
);
163 server
= new0(sd_dhcp_server
, 1);
170 server
->address
= htobe32(INADDR_ANY
);
171 server
->netmask
= htobe32(INADDR_ANY
);
172 server
->ifindex
= ifindex
;
174 server
->leases_by_client_id
= hashmap_new(&dhcp_lease_hash_ops
);
175 if (!server
->leases_by_client_id
)
178 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
179 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
181 *ret
= TAKE_PTR(server
);
186 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
189 assert_return(server
, -EINVAL
);
190 assert_return(!server
->event
, -EBUSY
);
193 server
->event
= sd_event_ref(event
);
195 r
= sd_event_default(&server
->event
);
200 server
->event_priority
= priority
;
205 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
206 assert_return(server
, -EINVAL
);
208 server
->event
= sd_event_unref(server
->event
);
213 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
214 assert_return(server
, NULL
);
216 return server
->event
;
219 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
220 assert_return(server
, -EINVAL
);
222 server
->receive_message
=
223 sd_event_source_unref(server
->receive_message
);
225 server
->fd_raw
= safe_close(server
->fd_raw
);
226 server
->fd
= safe_close(server
->fd
);
228 log_dhcp_server(server
, "STOPPED");
233 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
234 DHCPPacket
*packet
, size_t len
) {
235 union sockaddr_union link
= {
236 .ll
.sll_family
= AF_PACKET
,
237 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
238 .ll
.sll_ifindex
= server
->ifindex
,
239 .ll
.sll_halen
= ETH_ALEN
,
243 assert(server
->ifindex
> 0);
244 assert(server
->address
);
246 assert(len
> sizeof(DHCPPacket
));
248 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
250 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
252 DHCP_PORT_CLIENT
, len
, -1);
254 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
257 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
258 uint16_t destination_port
,
259 DHCPMessage
*message
, size_t len
) {
260 union sockaddr_union dest
= {
261 .in
.sin_family
= AF_INET
,
262 .in
.sin_port
= htobe16(destination_port
),
263 .in
.sin_addr
.s_addr
= destination
,
269 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
270 struct msghdr msg
= {
272 .msg_namelen
= sizeof(dest
.in
),
275 .msg_control
= cmsgbuf
,
276 .msg_controllen
= sizeof(cmsgbuf
),
278 struct cmsghdr
*cmsg
;
279 struct in_pktinfo
*pktinfo
;
282 assert(server
->fd
>= 0);
284 assert(len
> sizeof(DHCPMessage
));
286 cmsg
= CMSG_FIRSTHDR(&msg
);
289 cmsg
->cmsg_level
= IPPROTO_IP
;
290 cmsg
->cmsg_type
= IP_PKTINFO
;
291 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
293 /* we attach source interface and address info to the message
294 rather than binding the socket. This will be mostly useful
295 when we gain support for arbitrary number of server addresses
297 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
300 pktinfo
->ipi_ifindex
= server
->ifindex
;
301 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
303 if (sendmsg(server
->fd
, &msg
, 0) < 0)
309 static bool requested_broadcast(DHCPRequest
*req
) {
312 return req
->message
->flags
& htobe16(0x8000);
315 int dhcp_server_send_packet(sd_dhcp_server
*server
,
316 DHCPRequest
*req
, DHCPPacket
*packet
,
317 int type
, size_t optoffset
) {
318 be32_t destination
= INADDR_ANY
;
319 uint16_t destination_port
= DHCP_PORT_CLIENT
;
324 assert(req
->max_optlen
);
325 assert(optoffset
<= req
->max_optlen
);
328 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
329 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
330 4, &server
->address
);
334 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
335 SD_DHCP_OPTION_END
, 0, NULL
);
339 /* RFC 2131 Section 4.1
341 If the ’giaddr’ field in a DHCP message from a client is non-zero,
342 the server sends any return messages to the ’DHCP server’ port on the
343 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
344 field is zero and the ’ciaddr’ field is nonzero, then the server
345 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
346 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
347 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
348 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
349 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
350 messages to the client’s hardware address and ’yiaddr’ address. In
351 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
352 messages to 0xffffffff.
356 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
357 different subnet. The server MUST set the broadcast bit in the
358 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
359 client, because the client may not have a correct network address
360 or subnet mask, and the client may not be answering ARP requests.
362 if (req
->message
->giaddr
) {
363 destination
= req
->message
->giaddr
;
364 destination_port
= DHCP_PORT_SERVER
;
365 if (type
== DHCP_NAK
)
366 packet
->dhcp
.flags
= htobe16(0x8000);
367 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
368 destination
= req
->message
->ciaddr
;
370 if (destination
!= INADDR_ANY
)
371 return dhcp_server_send_udp(server
, destination
,
372 destination_port
, &packet
->dhcp
,
373 sizeof(DHCPMessage
) + optoffset
);
374 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
375 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
376 destination_port
, &packet
->dhcp
,
377 sizeof(DHCPMessage
) + optoffset
);
379 /* we cannot send UDP packet to specific MAC address when the
380 address is not yet configured, so must fall back to raw
382 return dhcp_server_send_unicast_raw(server
, packet
,
383 sizeof(DHCPPacket
) + optoffset
);
386 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
387 uint8_t type
, size_t *_optoffset
,
389 _cleanup_free_ DHCPPacket
*packet
= NULL
;
390 size_t optoffset
= 0;
396 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
398 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
402 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
403 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
404 req
->max_optlen
, &optoffset
);
408 packet
->dhcp
.flags
= req
->message
->flags
;
409 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
410 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
412 *_optoffset
= optoffset
;
413 *ret
= TAKE_PTR(packet
);
418 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
420 _cleanup_free_ DHCPPacket
*packet
= NULL
;
425 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
429 packet
->dhcp
.yiaddr
= address
;
431 lease_time
= htobe32(req
->lifetime
);
432 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
433 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
438 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
439 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
443 if (server
->emit_router
) {
444 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
445 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
450 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
457 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
459 _cleanup_free_ DHCPPacket
*packet
= NULL
;
466 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
470 packet
->dhcp
.yiaddr
= address
;
472 lease_time
= htobe32(req
->lifetime
);
473 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
474 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
479 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
480 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
484 if (server
->emit_router
) {
485 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
486 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
491 if (server
->n_dns
> 0) {
492 r
= dhcp_option_append(
493 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
494 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
495 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
500 if (server
->n_ntp
> 0) {
501 r
= dhcp_option_append(
502 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
503 SD_DHCP_OPTION_NTP_SERVER
,
504 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
509 if (server
->n_sip
> 0) {
510 r
= dhcp_option_append(
511 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
512 SD_DHCP_OPTION_SIP_SERVER
,
513 sizeof(struct in_addr
) * server
->n_sip
, server
->sip
);
518 if (server
->n_pop3_server
> 0) {
519 r
= dhcp_option_append(
520 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
521 SD_DHCP_OPTION_POP3_SERVER
,
522 sizeof(struct in_addr
) * server
->n_pop3_server
, server
->pop3_server
);
527 if (server
->n_smtp_server
> 0) {
528 r
= dhcp_option_append(
529 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
530 SD_DHCP_OPTION_SMTP_SERVER
,
531 sizeof(struct in_addr
) * server
->n_smtp_server
, server
->smtp_server
);
536 if (server
->timezone
) {
537 r
= dhcp_option_append(
538 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
539 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
540 strlen(server
->timezone
), server
->timezone
);
545 ORDERED_HASHMAP_FOREACH(j
, server
->extra_options
, i
) {
546 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
547 j
->option
, j
->length
, j
->data
);
552 if (!ordered_hashmap_isempty(server
->vendor_options
)) {
553 r
= dhcp_option_append(
554 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
555 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
556 ordered_hashmap_size(server
->vendor_options
), server
->vendor_options
);
561 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
568 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
569 _cleanup_free_ DHCPPacket
*packet
= NULL
;
573 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
577 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
580 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
581 be32_t gateway
, uint8_t chaddr
[]) {
582 _cleanup_free_ DHCPPacket
*packet
= NULL
;
583 size_t optoffset
= 0;
587 assert(address
!= INADDR_ANY
);
590 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
594 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
595 DHCP_FORCERENEW
, ARPHRD_ETHER
,
596 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
600 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
601 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
605 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
607 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
609 sizeof(DHCPMessage
) + optoffset
);
616 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
617 DHCPRequest
*req
= userdata
;
622 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
624 req
->lifetime
= unaligned_read_be32(option
);
627 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
629 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
632 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
634 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
637 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
641 data
= memdup(option
, len
);
645 free(req
->client_id
.data
);
646 req
->client_id
.data
= data
;
647 req
->client_id
.length
= len
;
651 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
653 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
654 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
662 static void dhcp_request_free(DHCPRequest
*req
) {
666 free(req
->client_id
.data
);
670 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
672 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
676 req
->message
= message
;
678 /* set client id based on MAC address if client did not send an explicit
680 if (!req
->client_id
.data
) {
683 data
= malloc0(ETH_ALEN
+ 1);
687 ((uint8_t*) data
)[0] = 0x01;
688 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
690 req
->client_id
.length
= ETH_ALEN
+ 1;
691 req
->client_id
.data
= data
;
694 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
695 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
697 if (req
->lifetime
<= 0)
698 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
700 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
701 req
->lifetime
= server
->max_lease_time
;
706 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
709 if (!server
->pool_size
)
712 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
713 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
716 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
719 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
721 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
723 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
724 _cleanup_free_
char *error_message
= NULL
;
725 DHCPLease
*existing_lease
;
731 if (message
->op
!= BOOTREQUEST
||
732 message
->htype
!= ARPHRD_ETHER
||
733 message
->hlen
!= ETHER_ADDR_LEN
)
736 req
= new0(DHCPRequest
, 1);
740 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
744 r
= ensure_sane_request(server
, req
, message
);
746 /* this only fails on critical errors */
749 existing_lease
= hashmap_get(server
->leases_by_client_id
,
754 case DHCP_DISCOVER
: {
755 be32_t address
= INADDR_ANY
;
758 log_dhcp_server(server
, "DISCOVER (0x%x)",
759 be32toh(req
->message
->xid
));
761 if (!server
->pool_size
)
762 /* no pool allocated */
765 /* for now pick a random free address from the pool */
767 address
= existing_lease
->address
;
769 struct siphash state
;
773 /* even with no persistence of leases, we try to offer the same client
774 the same IP address. we do this by using the hash of the client id
775 as the offset into the pool of leases when finding the next free one */
777 siphash24_init(&state
, HASH_KEY
.bytes
);
778 client_id_hash_func(&req
->client_id
, &state
);
779 hash
= htole64(siphash24_finalize(&state
));
780 next_offer
= hash
% server
->pool_size
;
782 for (i
= 0; i
< server
->pool_size
; i
++) {
783 if (!server
->bound_leases
[next_offer
]) {
784 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
788 next_offer
= (next_offer
+ 1) % server
->pool_size
;
792 if (address
== INADDR_ANY
)
793 /* no free addresses left */
796 r
= server_send_offer(server
, req
, address
);
798 /* this only fails on critical errors */
799 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
801 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
805 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
807 /* TODO: make sure we don't offer this address again */
813 bool init_reboot
= false;
816 /* see RFC 2131, section 4.3.2 */
818 if (req
->server_id
) {
819 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
820 be32toh(req
->message
->xid
));
823 if (req
->server_id
!= server
->address
)
824 /* client did not pick us */
827 if (req
->message
->ciaddr
)
828 /* this MUST be zero */
831 if (!req
->requested_ip
)
832 /* this must be filled in with the yiaddr
833 from the chosen OFFER */
836 address
= req
->requested_ip
;
837 } else if (req
->requested_ip
) {
838 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
839 be32toh(req
->message
->xid
));
842 if (req
->message
->ciaddr
)
843 /* this MUST be zero */
846 /* TODO: check more carefully if IP is correct */
847 address
= req
->requested_ip
;
850 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
851 be32toh(req
->message
->xid
));
853 /* REBINDING / RENEWING */
854 if (!req
->message
->ciaddr
)
855 /* this MUST be filled in with clients IP address */
858 address
= req
->message
->ciaddr
;
861 pool_offset
= get_pool_offset(server
, address
);
863 /* verify that the requested address is from the pool, and either
864 owned by the current client or free */
865 if (pool_offset
>= 0 &&
866 server
->bound_leases
[pool_offset
] == existing_lease
) {
870 if (!existing_lease
) {
871 lease
= new0(DHCPLease
, 1);
874 lease
->address
= address
;
875 lease
->client_id
.data
= memdup(req
->client_id
.data
,
876 req
->client_id
.length
);
877 if (!lease
->client_id
.data
) {
881 lease
->client_id
.length
= req
->client_id
.length
;
882 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
884 lease
->gateway
= req
->message
->giaddr
;
886 lease
= existing_lease
;
888 r
= sd_event_now(server
->event
,
889 clock_boottime_or_monotonic(),
893 dhcp_lease_free(lease
);
897 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
899 r
= server_send_ack(server
, req
, address
);
901 /* this only fails on critical errors */
902 log_dhcp_server_errno(server
, r
, "Could not send ack: %m");
905 dhcp_lease_free(lease
);
909 log_dhcp_server(server
, "ACK (0x%x)",
910 be32toh(req
->message
->xid
));
912 server
->bound_leases
[pool_offset
] = lease
;
913 hashmap_put(server
->leases_by_client_id
,
914 &lease
->client_id
, lease
);
919 } else if (init_reboot
) {
920 r
= server_send_nak(server
, req
);
922 /* this only fails on critical errors */
923 return log_dhcp_server_errno(server
, r
, "Could not send nak: %m");
925 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
935 log_dhcp_server(server
, "RELEASE (0x%x)",
936 be32toh(req
->message
->xid
));
941 if (existing_lease
->address
!= req
->message
->ciaddr
)
944 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
948 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
949 server
->bound_leases
[pool_offset
] = NULL
;
950 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
951 dhcp_lease_free(existing_lease
);
960 static int server_receive_message(sd_event_source
*s
, int fd
,
961 uint32_t revents
, void *userdata
) {
962 _cleanup_free_ DHCPMessage
*message
= NULL
;
963 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
964 sd_dhcp_server
*server
= userdata
;
965 struct iovec iov
= {};
966 struct msghdr msg
= {
969 .msg_control
= cmsgbuf
,
970 .msg_controllen
= sizeof(cmsgbuf
),
972 struct cmsghdr
*cmsg
;
978 buflen
= next_datagram_size_fd(fd
);
982 message
= malloc(buflen
);
986 iov
= IOVEC_MAKE(message
, buflen
);
988 len
= recvmsg(fd
, &msg
, 0);
990 if (IN_SET(errno
, EAGAIN
, EINTR
))
995 if ((size_t)len
< sizeof(DHCPMessage
))
998 CMSG_FOREACH(cmsg
, &msg
) {
999 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
1000 cmsg
->cmsg_type
== IP_PKTINFO
&&
1001 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
1002 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
1004 /* TODO figure out if this can be done as a filter on
1005 * the socket, like for IPv6 */
1006 if (server
->ifindex
!= info
->ipi_ifindex
)
1013 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
1015 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message: %m");
1020 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1023 assert_return(server
, -EINVAL
);
1024 assert_return(server
->event
, -EINVAL
);
1025 assert_return(!server
->receive_message
, -EBUSY
);
1026 assert_return(server
->fd_raw
< 0, -EBUSY
);
1027 assert_return(server
->fd
< 0, -EBUSY
);
1028 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1030 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
1033 sd_dhcp_server_stop(server
);
1038 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
, -1);
1040 sd_dhcp_server_stop(server
);
1045 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1046 server
->fd
, EPOLLIN
,
1047 server_receive_message
, server
);
1049 sd_dhcp_server_stop(server
);
1053 r
= sd_event_source_set_priority(server
->receive_message
,
1054 server
->event_priority
);
1056 sd_dhcp_server_stop(server
);
1060 log_dhcp_server(server
, "STARTED");
1065 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1069 assert_return(server
, -EINVAL
);
1070 assert(server
->bound_leases
);
1072 for (i
= 0; i
< server
->pool_size
; i
++) {
1073 DHCPLease
*lease
= server
->bound_leases
[i
];
1075 if (!lease
|| lease
== &server
->invalid_lease
)
1078 r
= server_send_forcerenew(server
, lease
->address
,
1084 log_dhcp_server(server
, "FORCERENEW");
1090 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1093 assert_return(server
, -EINVAL
);
1094 assert_return(timezone_is_valid(tz
, LOG_DEBUG
), -EINVAL
);
1096 if (streq_ptr(tz
, server
->timezone
))
1099 r
= free_and_strdup(&server
->timezone
, tz
);
1106 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1107 assert_return(server
, -EINVAL
);
1109 if (t
== server
->max_lease_time
)
1112 server
->max_lease_time
= t
;
1116 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1117 assert_return(server
, -EINVAL
);
1119 if (t
== server
->default_lease_time
)
1122 server
->default_lease_time
= t
;
1126 int sd_dhcp_server_set_servers(
1127 sd_dhcp_server
*server
,
1128 sd_dhcp_lease_info what
,
1129 const struct in_addr addresses
[],
1130 unsigned n_addresses
) {
1132 assert_return(server
, -EINVAL
);
1133 assert_return(addresses
|| n_addresses
== 0, -EINVAL
);
1139 case SD_DHCP_LEASE_DNS_SERVERS
:
1141 n_a
= &server
->n_dns
;
1144 case SD_DHCP_LEASE_NTP_SERVERS
:
1146 n_a
= &server
->n_ntp
;
1149 case SD_DHCP_LEASE_SIP_SERVERS
:
1151 n_a
= &server
->n_sip
;
1154 case SD_DHCP_LEASE_POP3_SERVERS
:
1155 a
= &server
->pop3_server
;
1156 n_a
= &server
->n_pop3_server
;
1159 case SD_DHCP_LEASE_SMTP_SERVERS
:
1160 a
= &server
->smtp_server
;
1161 n_a
= &server
->n_smtp_server
;
1165 return log_debug_errno(SYNTHETIC_ERRNO(ENXIO
),
1166 "Unknown DHCP lease info item %d.", what
);
1169 if (*n_a
== n_addresses
&&
1170 memcmp(*a
, addresses
, sizeof(struct in_addr
) * n_addresses
) == 0)
1173 struct in_addr
*c
= NULL
;
1175 if (n_addresses
> 0) {
1176 c
= newdup(struct in_addr
, addresses
, n_addresses
);
1187 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1188 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_DNS_SERVERS
, dns
, n
);
1190 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1191 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_NTP_SERVERS
, ntp
, n
);
1193 int sd_dhcp_server_set_sip(sd_dhcp_server
*server
, const struct in_addr sip
[], unsigned n
) {
1194 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SIP_SERVERS
, sip
, n
);
1196 int sd_dhcp_server_set_pop3_server(sd_dhcp_server
*server
, const struct in_addr pop3
[], unsigned n
) {
1197 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_POP3_SERVERS
, pop3
, n
);
1199 int sd_dhcp_server_set_smtp_server(sd_dhcp_server
*server
, const struct in_addr smtp
[], unsigned n
) {
1200 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SMTP_SERVERS
, smtp
, n
);
1203 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1204 assert_return(server
, -EINVAL
);
1206 if (enabled
== server
->emit_router
)
1209 server
->emit_router
= enabled
;
1214 int sd_dhcp_server_add_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1217 assert_return(server
, -EINVAL
);
1218 assert_return(v
, -EINVAL
);
1220 r
= ordered_hashmap_ensure_allocated(&server
->extra_options
, &dhcp_option_hash_ops
);
1224 r
= ordered_hashmap_put(server
->extra_options
, UINT_TO_PTR(v
->option
), v
);
1228 sd_dhcp_option_ref(v
);
1232 int sd_dhcp_server_add_vendor_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1235 assert_return(server
, -EINVAL
);
1236 assert_return(v
, -EINVAL
);
1238 r
= ordered_hashmap_ensure_allocated(&server
->vendor_options
, &dhcp_option_hash_ops
);
1242 r
= ordered_hashmap_put(server
->vendor_options
, v
, v
);
1246 sd_dhcp_option_ref(v
);