1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
6 #include <net/if_arp.h>
9 #include "sd-dhcp-server.h"
12 #include "alloc-util.h"
13 #include "dhcp-internal.h"
14 #include "dhcp-server-internal.h"
16 #include "in-addr-util.h"
18 #include "siphash24.h"
19 #include "string-util.h"
20 #include "unaligned.h"
22 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
23 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
25 static DHCPLease
*dhcp_lease_free(DHCPLease
*lease
) {
29 free(lease
->client_id
.data
);
33 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
34 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
35 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
36 * accidentally hand it out */
37 int sd_dhcp_server_configure_pool(
38 sd_dhcp_server
*server
,
39 const struct in_addr
*address
,
40 unsigned char prefixlen
,
44 struct in_addr netmask_addr
;
46 uint32_t server_off
, broadcast_off
, size_max
;
48 assert_return(server
, -EINVAL
);
49 assert_return(address
, -EINVAL
);
50 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
51 assert_return(prefixlen
<= 32, -ERANGE
);
53 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
54 netmask
= netmask_addr
.s_addr
;
56 server_off
= be32toh(address
->s_addr
& ~netmask
);
57 broadcast_off
= be32toh(~netmask
);
59 /* the server address cannot be the subnet address */
60 assert_return(server_off
!= 0, -ERANGE
);
62 /* nor the broadcast address */
63 assert_return(server_off
!= broadcast_off
, -ERANGE
);
65 /* 0 offset means we should set a default, we skip the first (subnet) address
66 and take the next one */
70 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
71 - offset
/* exclude the addresses before the offset */
72 - 1; /* exclude the last (broadcast) address */
74 /* The pool must contain at least one address */
75 assert_return(size_max
>= 1, -ERANGE
);
78 assert_return(size
<= size_max
, -ERANGE
);
82 if (server
->address
!= address
->s_addr
|| server
->netmask
!= netmask
|| server
->pool_size
!= size
|| server
->pool_offset
!= offset
) {
84 free(server
->bound_leases
);
85 server
->bound_leases
= new0(DHCPLease
*, size
);
86 if (!server
->bound_leases
)
89 server
->pool_offset
= offset
;
90 server
->pool_size
= size
;
92 server
->address
= address
->s_addr
;
93 server
->netmask
= netmask
;
94 server
->subnet
= address
->s_addr
& netmask
;
96 if (server_off
>= offset
&& server_off
- offset
< size
)
97 server
->bound_leases
[server_off
- offset
] = &server
->invalid_lease
;
99 /* Drop any leases associated with the old address range */
100 hashmap_clear(server
->leases_by_client_id
);
102 if (server
->callback
)
103 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
109 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
110 assert_return(server
, false);
112 return !!server
->receive_message
;
115 void client_id_hash_func(const DHCPClientId
*id
, struct siphash
*state
) {
120 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
121 siphash24_compress(id
->data
, id
->length
, state
);
124 int client_id_compare_func(const DHCPClientId
*a
, const DHCPClientId
*b
) {
127 assert(!a
->length
|| a
->data
);
128 assert(!b
->length
|| b
->data
);
130 r
= CMP(a
->length
, b
->length
);
134 return memcmp(a
->data
, b
->data
, a
->length
);
137 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(dhcp_lease_hash_ops
, DHCPClientId
, client_id_hash_func
, client_id_compare_func
,
138 DHCPLease
, dhcp_lease_free
);
140 static sd_dhcp_server
*dhcp_server_free(sd_dhcp_server
*server
) {
143 log_dhcp_server(server
, "UNREF");
145 sd_dhcp_server_stop(server
);
147 sd_event_unref(server
->event
);
149 free(server
->timezone
);
151 for (sd_dhcp_lease_server_type i
= 0; i
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; i
++)
152 free(server
->servers
[i
].addr
);
154 hashmap_free(server
->leases_by_client_id
);
156 ordered_hashmap_free(server
->extra_options
);
157 ordered_hashmap_free(server
->vendor_options
);
159 free(server
->bound_leases
);
160 return mfree(server
);
163 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server
, sd_dhcp_server
, dhcp_server_free
);
165 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
166 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
168 assert_return(ret
, -EINVAL
);
169 assert_return(ifindex
> 0, -EINVAL
);
171 server
= new0(sd_dhcp_server
, 1);
178 server
->address
= htobe32(INADDR_ANY
);
179 server
->netmask
= htobe32(INADDR_ANY
);
180 server
->ifindex
= ifindex
;
182 server
->leases_by_client_id
= hashmap_new(&dhcp_lease_hash_ops
);
183 if (!server
->leases_by_client_id
)
186 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
187 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
189 *ret
= TAKE_PTR(server
);
194 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
197 assert_return(server
, -EINVAL
);
198 assert_return(!server
->event
, -EBUSY
);
201 server
->event
= sd_event_ref(event
);
203 r
= sd_event_default(&server
->event
);
208 server
->event_priority
= priority
;
213 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
214 assert_return(server
, -EINVAL
);
216 server
->event
= sd_event_unref(server
->event
);
221 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
222 assert_return(server
, NULL
);
224 return server
->event
;
227 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
228 assert_return(server
, -EINVAL
);
230 server
->receive_message
=
231 sd_event_source_unref(server
->receive_message
);
233 server
->fd_raw
= safe_close(server
->fd_raw
);
234 server
->fd
= safe_close(server
->fd
);
236 log_dhcp_server(server
, "STOPPED");
241 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
242 DHCPPacket
*packet
, size_t len
) {
243 union sockaddr_union link
= {
244 .ll
.sll_family
= AF_PACKET
,
245 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
246 .ll
.sll_ifindex
= server
->ifindex
,
247 .ll
.sll_halen
= ETH_ALEN
,
251 assert(server
->ifindex
> 0);
252 assert(server
->address
);
254 assert(len
> sizeof(DHCPPacket
));
256 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
258 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
260 DHCP_PORT_CLIENT
, len
, -1);
262 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
265 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
266 uint16_t destination_port
,
267 DHCPMessage
*message
, size_t len
) {
268 union sockaddr_union dest
= {
269 .in
.sin_family
= AF_INET
,
270 .in
.sin_port
= htobe16(destination_port
),
271 .in
.sin_addr
.s_addr
= destination
,
277 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo
))) control
= {};
278 struct msghdr msg
= {
280 .msg_namelen
= sizeof(dest
.in
),
283 .msg_control
= &control
,
284 .msg_controllen
= sizeof(control
),
286 struct cmsghdr
*cmsg
;
287 struct in_pktinfo
*pktinfo
;
290 assert(server
->fd
>= 0);
292 assert(len
> sizeof(DHCPMessage
));
294 cmsg
= CMSG_FIRSTHDR(&msg
);
297 cmsg
->cmsg_level
= IPPROTO_IP
;
298 cmsg
->cmsg_type
= IP_PKTINFO
;
299 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
301 /* we attach source interface and address info to the message
302 rather than binding the socket. This will be mostly useful
303 when we gain support for arbitrary number of server addresses
305 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
308 pktinfo
->ipi_ifindex
= server
->ifindex
;
309 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
311 if (sendmsg(server
->fd
, &msg
, 0) < 0)
317 static bool requested_broadcast(DHCPRequest
*req
) {
320 return req
->message
->flags
& htobe16(0x8000);
323 int dhcp_server_send_packet(sd_dhcp_server
*server
,
324 DHCPRequest
*req
, DHCPPacket
*packet
,
325 int type
, size_t optoffset
) {
326 be32_t destination
= INADDR_ANY
;
327 uint16_t destination_port
= DHCP_PORT_CLIENT
;
332 assert(req
->max_optlen
);
333 assert(optoffset
<= req
->max_optlen
);
336 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
337 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
338 4, &server
->address
);
342 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
343 SD_DHCP_OPTION_END
, 0, NULL
);
347 /* RFC 2131 Section 4.1
349 If the ’giaddr’ field in a DHCP message from a client is non-zero,
350 the server sends any return messages to the ’DHCP server’ port on the
351 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
352 field is zero and the ’ciaddr’ field is nonzero, then the server
353 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
354 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
355 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
356 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
357 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
358 messages to the client’s hardware address and ’yiaddr’ address. In
359 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
360 messages to 0xffffffff.
364 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
365 different subnet. The server MUST set the broadcast bit in the
366 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
367 client, because the client may not have a correct network address
368 or subnet mask, and the client may not be answering ARP requests.
370 if (req
->message
->giaddr
) {
371 destination
= req
->message
->giaddr
;
372 destination_port
= DHCP_PORT_SERVER
;
373 if (type
== DHCP_NAK
)
374 packet
->dhcp
.flags
= htobe16(0x8000);
375 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
376 destination
= req
->message
->ciaddr
;
378 if (destination
!= INADDR_ANY
)
379 return dhcp_server_send_udp(server
, destination
,
380 destination_port
, &packet
->dhcp
,
381 sizeof(DHCPMessage
) + optoffset
);
382 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
383 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
384 destination_port
, &packet
->dhcp
,
385 sizeof(DHCPMessage
) + optoffset
);
387 /* we cannot send UDP packet to specific MAC address when the
388 address is not yet configured, so must fall back to raw
390 return dhcp_server_send_unicast_raw(server
, packet
,
391 sizeof(DHCPPacket
) + optoffset
);
394 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
395 uint8_t type
, size_t *_optoffset
,
397 _cleanup_free_ DHCPPacket
*packet
= NULL
;
398 size_t optoffset
= 0;
404 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
406 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
410 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
411 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
412 req
->max_optlen
, &optoffset
);
416 packet
->dhcp
.flags
= req
->message
->flags
;
417 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
418 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
420 *_optoffset
= optoffset
;
421 *ret
= TAKE_PTR(packet
);
426 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
428 _cleanup_free_ DHCPPacket
*packet
= NULL
;
433 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
437 packet
->dhcp
.yiaddr
= address
;
439 lease_time
= htobe32(req
->lifetime
);
440 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
441 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
446 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
447 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
451 if (server
->emit_router
) {
452 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
453 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
458 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
465 static int server_send_ack(
466 sd_dhcp_server
*server
,
470 static const uint8_t option_map
[_SD_DHCP_LEASE_SERVER_TYPE_MAX
] = {
471 [SD_DHCP_LEASE_DNS
] = SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
472 [SD_DHCP_LEASE_NTP
] = SD_DHCP_OPTION_NTP_SERVER
,
473 [SD_DHCP_LEASE_SIP
] = SD_DHCP_OPTION_SIP_SERVER
,
474 [SD_DHCP_LEASE_POP3
] = SD_DHCP_OPTION_POP3_SERVER
,
475 [SD_DHCP_LEASE_SMTP
] = SD_DHCP_OPTION_SMTP_SERVER
,
476 [SD_DHCP_LEASE_LPR
] = SD_DHCP_OPTION_LPR_SERVER
,
479 _cleanup_free_ DHCPPacket
*packet
= NULL
;
485 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
489 packet
->dhcp
.yiaddr
= address
;
491 lease_time
= htobe32(req
->lifetime
);
492 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
493 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
498 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
499 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
503 if (server
->emit_router
) {
504 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
505 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
510 for (sd_dhcp_lease_server_type k
= 0; k
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; k
++) {
512 if (server
->servers
[k
].size
<= 0)
515 r
= dhcp_option_append(
516 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
518 sizeof(struct in_addr
) * server
->servers
[k
].size
, server
->servers
[k
].addr
);
524 if (server
->timezone
) {
525 r
= dhcp_option_append(
526 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
527 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
528 strlen(server
->timezone
), server
->timezone
);
533 ORDERED_HASHMAP_FOREACH(j
, server
->extra_options
) {
534 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
535 j
->option
, j
->length
, j
->data
);
540 if (!ordered_hashmap_isempty(server
->vendor_options
)) {
541 r
= dhcp_option_append(
542 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
543 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
544 ordered_hashmap_size(server
->vendor_options
), server
->vendor_options
);
549 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
556 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
557 _cleanup_free_ DHCPPacket
*packet
= NULL
;
561 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
565 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
568 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
569 be32_t gateway
, uint8_t chaddr
[]) {
570 _cleanup_free_ DHCPPacket
*packet
= NULL
;
571 size_t optoffset
= 0;
575 assert(address
!= INADDR_ANY
);
578 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
582 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
583 DHCP_FORCERENEW
, ARPHRD_ETHER
,
584 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
588 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
589 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
593 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
595 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
597 sizeof(DHCPMessage
) + optoffset
);
604 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
605 DHCPRequest
*req
= userdata
;
610 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
612 req
->lifetime
= unaligned_read_be32(option
);
615 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
617 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
620 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
622 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
625 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
629 data
= memdup(option
, len
);
633 free(req
->client_id
.data
);
634 req
->client_id
.data
= data
;
635 req
->client_id
.length
= len
;
639 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
641 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
642 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
650 static void dhcp_request_free(DHCPRequest
*req
) {
654 free(req
->client_id
.data
);
658 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
660 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
664 req
->message
= message
;
666 /* set client id based on MAC address if client did not send an explicit
668 if (!req
->client_id
.data
) {
671 data
= malloc0(ETH_ALEN
+ 1);
675 ((uint8_t*) data
)[0] = 0x01;
676 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
678 req
->client_id
.length
= ETH_ALEN
+ 1;
679 req
->client_id
.data
= data
;
682 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
683 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
685 if (req
->lifetime
<= 0)
686 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
688 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
689 req
->lifetime
= server
->max_lease_time
;
694 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
697 if (!server
->pool_size
)
700 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
701 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
704 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
707 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
709 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
711 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
712 _cleanup_free_
char *error_message
= NULL
;
713 DHCPLease
*existing_lease
;
719 if (message
->op
!= BOOTREQUEST
||
720 message
->htype
!= ARPHRD_ETHER
||
721 message
->hlen
!= ETHER_ADDR_LEN
)
724 req
= new0(DHCPRequest
, 1);
728 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
732 r
= ensure_sane_request(server
, req
, message
);
734 /* this only fails on critical errors */
737 existing_lease
= hashmap_get(server
->leases_by_client_id
,
742 case DHCP_DISCOVER
: {
743 be32_t address
= INADDR_ANY
;
746 log_dhcp_server(server
, "DISCOVER (0x%x)",
747 be32toh(req
->message
->xid
));
749 if (!server
->pool_size
)
750 /* no pool allocated */
753 /* for now pick a random free address from the pool */
755 address
= existing_lease
->address
;
757 struct siphash state
;
761 /* even with no persistence of leases, we try to offer the same client
762 the same IP address. we do this by using the hash of the client id
763 as the offset into the pool of leases when finding the next free one */
765 siphash24_init(&state
, HASH_KEY
.bytes
);
766 client_id_hash_func(&req
->client_id
, &state
);
767 hash
= htole64(siphash24_finalize(&state
));
768 next_offer
= hash
% server
->pool_size
;
770 for (i
= 0; i
< server
->pool_size
; i
++) {
771 if (!server
->bound_leases
[next_offer
]) {
772 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
776 next_offer
= (next_offer
+ 1) % server
->pool_size
;
780 if (address
== INADDR_ANY
)
781 /* no free addresses left */
784 r
= server_send_offer(server
, req
, address
);
786 /* this only fails on critical errors */
787 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
789 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
793 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
795 /* TODO: make sure we don't offer this address again */
801 bool init_reboot
= false;
804 /* see RFC 2131, section 4.3.2 */
806 if (req
->server_id
) {
807 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
808 be32toh(req
->message
->xid
));
811 if (req
->server_id
!= server
->address
)
812 /* client did not pick us */
815 if (req
->message
->ciaddr
)
816 /* this MUST be zero */
819 if (!req
->requested_ip
)
820 /* this must be filled in with the yiaddr
821 from the chosen OFFER */
824 address
= req
->requested_ip
;
825 } else if (req
->requested_ip
) {
826 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
827 be32toh(req
->message
->xid
));
830 if (req
->message
->ciaddr
)
831 /* this MUST be zero */
834 /* TODO: check more carefully if IP is correct */
835 address
= req
->requested_ip
;
838 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
839 be32toh(req
->message
->xid
));
841 /* REBINDING / RENEWING */
842 if (!req
->message
->ciaddr
)
843 /* this MUST be filled in with clients IP address */
846 address
= req
->message
->ciaddr
;
849 pool_offset
= get_pool_offset(server
, address
);
851 /* verify that the requested address is from the pool, and either
852 owned by the current client or free */
853 if (pool_offset
>= 0 &&
854 server
->bound_leases
[pool_offset
] == existing_lease
) {
858 if (!existing_lease
) {
859 lease
= new0(DHCPLease
, 1);
862 lease
->address
= address
;
863 lease
->client_id
.data
= memdup(req
->client_id
.data
,
864 req
->client_id
.length
);
865 if (!lease
->client_id
.data
) {
869 lease
->client_id
.length
= req
->client_id
.length
;
870 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
872 lease
->gateway
= req
->message
->giaddr
;
874 lease
= existing_lease
;
876 r
= sd_event_now(server
->event
,
877 clock_boottime_or_monotonic(),
881 dhcp_lease_free(lease
);
885 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
887 r
= server_send_ack(server
, req
, address
);
889 /* this only fails on critical errors */
890 log_dhcp_server_errno(server
, r
, "Could not send ack: %m");
893 dhcp_lease_free(lease
);
897 log_dhcp_server(server
, "ACK (0x%x)",
898 be32toh(req
->message
->xid
));
900 server
->bound_leases
[pool_offset
] = lease
;
901 hashmap_put(server
->leases_by_client_id
,
902 &lease
->client_id
, lease
);
904 if (server
->callback
)
905 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
910 } else if (init_reboot
) {
911 r
= server_send_nak(server
, req
);
913 /* this only fails on critical errors */
914 return log_dhcp_server_errno(server
, r
, "Could not send nak: %m");
916 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
926 log_dhcp_server(server
, "RELEASE (0x%x)",
927 be32toh(req
->message
->xid
));
932 if (existing_lease
->address
!= req
->message
->ciaddr
)
935 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
939 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
940 server
->bound_leases
[pool_offset
] = NULL
;
941 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
942 dhcp_lease_free(existing_lease
);
944 if (server
->callback
)
945 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
954 static int server_receive_message(sd_event_source
*s
, int fd
,
955 uint32_t revents
, void *userdata
) {
956 _cleanup_free_ DHCPMessage
*message
= NULL
;
957 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo
))) control
;
958 sd_dhcp_server
*server
= userdata
;
959 struct iovec iov
= {};
960 struct msghdr msg
= {
963 .msg_control
= &control
,
964 .msg_controllen
= sizeof(control
),
966 struct cmsghdr
*cmsg
;
972 buflen
= next_datagram_size_fd(fd
);
976 message
= malloc(buflen
);
980 iov
= IOVEC_MAKE(message
, buflen
);
982 len
= recvmsg_safe(fd
, &msg
, 0);
983 if (IN_SET(len
, -EAGAIN
, -EINTR
))
987 if ((size_t) len
< sizeof(DHCPMessage
))
990 CMSG_FOREACH(cmsg
, &msg
) {
991 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
992 cmsg
->cmsg_type
== IP_PKTINFO
&&
993 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
994 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
996 /* TODO figure out if this can be done as a filter on
997 * the socket, like for IPv6 */
998 if (server
->ifindex
!= info
->ipi_ifindex
)
1005 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
1007 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message: %m");
1012 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1015 assert_return(server
, -EINVAL
);
1016 assert_return(server
->event
, -EINVAL
);
1017 assert_return(!server
->receive_message
, -EBUSY
);
1018 assert_return(server
->fd_raw
< 0, -EBUSY
);
1019 assert_return(server
->fd
< 0, -EBUSY
);
1020 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1022 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
1025 sd_dhcp_server_stop(server
);
1030 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
, -1);
1032 sd_dhcp_server_stop(server
);
1037 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1038 server
->fd
, EPOLLIN
,
1039 server_receive_message
, server
);
1041 sd_dhcp_server_stop(server
);
1045 r
= sd_event_source_set_priority(server
->receive_message
,
1046 server
->event_priority
);
1048 sd_dhcp_server_stop(server
);
1052 log_dhcp_server(server
, "STARTED");
1057 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1061 assert_return(server
, -EINVAL
);
1062 assert(server
->bound_leases
);
1064 for (i
= 0; i
< server
->pool_size
; i
++) {
1065 DHCPLease
*lease
= server
->bound_leases
[i
];
1067 if (!lease
|| lease
== &server
->invalid_lease
)
1070 r
= server_send_forcerenew(server
, lease
->address
,
1076 log_dhcp_server(server
, "FORCERENEW");
1082 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1085 assert_return(server
, -EINVAL
);
1086 assert_return(timezone_is_valid(tz
, LOG_DEBUG
), -EINVAL
);
1088 if (streq_ptr(tz
, server
->timezone
))
1091 r
= free_and_strdup(&server
->timezone
, tz
);
1098 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1099 assert_return(server
, -EINVAL
);
1101 if (t
== server
->max_lease_time
)
1104 server
->max_lease_time
= t
;
1108 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1109 assert_return(server
, -EINVAL
);
1111 if (t
== server
->default_lease_time
)
1114 server
->default_lease_time
= t
;
1118 int sd_dhcp_server_set_servers(
1119 sd_dhcp_server
*server
,
1120 sd_dhcp_lease_server_type what
,
1121 const struct in_addr addresses
[],
1122 size_t n_addresses
) {
1124 struct in_addr
*c
= NULL
;
1126 assert_return(server
, -EINVAL
);
1127 assert_return(addresses
|| n_addresses
== 0, -EINVAL
);
1128 assert_return(what
>= 0, -EINVAL
);
1129 assert_return(what
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
, -EINVAL
);
1131 if (server
->servers
[what
].size
== n_addresses
&&
1132 memcmp(server
->servers
[what
].addr
, addresses
, sizeof(struct in_addr
) * n_addresses
) == 0)
1135 if (n_addresses
> 0) {
1136 c
= newdup(struct in_addr
, addresses
, n_addresses
);
1141 free(server
->servers
[what
].addr
);
1142 server
->servers
[what
].addr
= c
;
1143 server
->servers
[what
].size
= n_addresses
;
1147 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], size_t n
) {
1148 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_DNS
, dns
, n
);
1150 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], size_t n
) {
1151 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_NTP
, ntp
, n
);
1153 int sd_dhcp_server_set_sip(sd_dhcp_server
*server
, const struct in_addr sip
[], size_t n
) {
1154 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SIP
, sip
, n
);
1156 int sd_dhcp_server_set_pop3(sd_dhcp_server
*server
, const struct in_addr pop3
[], size_t n
) {
1157 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_POP3
, pop3
, n
);
1159 int sd_dhcp_server_set_smtp(sd_dhcp_server
*server
, const struct in_addr smtp
[], size_t n
) {
1160 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SMTP
, smtp
, n
);
1162 int sd_dhcp_server_set_lpr(sd_dhcp_server
*server
, const struct in_addr lpr
[], size_t n
) {
1163 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_LPR
, lpr
, n
);
1166 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1167 assert_return(server
, -EINVAL
);
1169 if (enabled
== server
->emit_router
)
1172 server
->emit_router
= enabled
;
1177 int sd_dhcp_server_add_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1180 assert_return(server
, -EINVAL
);
1181 assert_return(v
, -EINVAL
);
1183 r
= ordered_hashmap_ensure_allocated(&server
->extra_options
, &dhcp_option_hash_ops
);
1187 r
= ordered_hashmap_put(server
->extra_options
, UINT_TO_PTR(v
->option
), v
);
1191 sd_dhcp_option_ref(v
);
1195 int sd_dhcp_server_add_vendor_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1198 assert_return(server
, -EINVAL
);
1199 assert_return(v
, -EINVAL
);
1201 r
= ordered_hashmap_ensure_allocated(&server
->vendor_options
, &dhcp_option_hash_ops
);
1205 r
= ordered_hashmap_put(server
->vendor_options
, v
, v
);
1209 sd_dhcp_option_ref(v
);
1214 int sd_dhcp_server_set_callback(sd_dhcp_server
*server
, sd_dhcp_server_callback_t cb
, void *userdata
) {
1215 assert_return(server
, -EINVAL
);
1217 server
->callback
= cb
;
1218 server
->callback_userdata
= userdata
;