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
) {
231 server
->receive_message
=
232 sd_event_source_unref(server
->receive_message
);
234 server
->fd_raw
= safe_close(server
->fd_raw
);
235 server
->fd
= safe_close(server
->fd
);
237 log_dhcp_server(server
, "STOPPED");
242 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
243 DHCPPacket
*packet
, size_t len
) {
244 union sockaddr_union link
= {
245 .ll
.sll_family
= AF_PACKET
,
246 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
247 .ll
.sll_ifindex
= server
->ifindex
,
248 .ll
.sll_halen
= ETH_ALEN
,
252 assert(server
->ifindex
> 0);
253 assert(server
->address
);
255 assert(len
> sizeof(DHCPPacket
));
257 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
259 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
261 DHCP_PORT_CLIENT
, len
, -1);
263 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
266 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
267 uint16_t destination_port
,
268 DHCPMessage
*message
, size_t len
) {
269 union sockaddr_union dest
= {
270 .in
.sin_family
= AF_INET
,
271 .in
.sin_port
= htobe16(destination_port
),
272 .in
.sin_addr
.s_addr
= destination
,
278 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo
))) control
= {};
279 struct msghdr msg
= {
281 .msg_namelen
= sizeof(dest
.in
),
284 .msg_control
= &control
,
285 .msg_controllen
= sizeof(control
),
287 struct cmsghdr
*cmsg
;
288 struct in_pktinfo
*pktinfo
;
291 assert(server
->fd
>= 0);
293 assert(len
> sizeof(DHCPMessage
));
295 cmsg
= CMSG_FIRSTHDR(&msg
);
298 cmsg
->cmsg_level
= IPPROTO_IP
;
299 cmsg
->cmsg_type
= IP_PKTINFO
;
300 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
302 /* we attach source interface and address info to the message
303 rather than binding the socket. This will be mostly useful
304 when we gain support for arbitrary number of server addresses
306 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
309 pktinfo
->ipi_ifindex
= server
->ifindex
;
310 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
312 if (sendmsg(server
->fd
, &msg
, 0) < 0)
318 static bool requested_broadcast(DHCPRequest
*req
) {
321 return req
->message
->flags
& htobe16(0x8000);
324 int dhcp_server_send_packet(sd_dhcp_server
*server
,
325 DHCPRequest
*req
, DHCPPacket
*packet
,
326 int type
, size_t optoffset
) {
327 be32_t destination
= INADDR_ANY
;
328 uint16_t destination_port
= DHCP_PORT_CLIENT
;
333 assert(req
->max_optlen
);
334 assert(optoffset
<= req
->max_optlen
);
337 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
338 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
339 4, &server
->address
);
343 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
344 SD_DHCP_OPTION_END
, 0, NULL
);
348 /* RFC 2131 Section 4.1
350 If the ’giaddr’ field in a DHCP message from a client is non-zero,
351 the server sends any return messages to the ’DHCP server’ port on the
352 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
353 field is zero and the ’ciaddr’ field is nonzero, then the server
354 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
355 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
356 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
357 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
358 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
359 messages to the client’s hardware address and ’yiaddr’ address. In
360 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
361 messages to 0xffffffff.
365 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
366 different subnet. The server MUST set the broadcast bit in the
367 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
368 client, because the client may not have a correct network address
369 or subnet mask, and the client may not be answering ARP requests.
371 if (req
->message
->giaddr
) {
372 destination
= req
->message
->giaddr
;
373 destination_port
= DHCP_PORT_SERVER
;
374 if (type
== DHCP_NAK
)
375 packet
->dhcp
.flags
= htobe16(0x8000);
376 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
377 destination
= req
->message
->ciaddr
;
379 if (destination
!= INADDR_ANY
)
380 return dhcp_server_send_udp(server
, destination
,
381 destination_port
, &packet
->dhcp
,
382 sizeof(DHCPMessage
) + optoffset
);
383 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
384 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
385 destination_port
, &packet
->dhcp
,
386 sizeof(DHCPMessage
) + optoffset
);
388 /* we cannot send UDP packet to specific MAC address when the
389 address is not yet configured, so must fall back to raw
391 return dhcp_server_send_unicast_raw(server
, packet
,
392 sizeof(DHCPPacket
) + optoffset
);
395 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
396 uint8_t type
, size_t *_optoffset
,
398 _cleanup_free_ DHCPPacket
*packet
= NULL
;
399 size_t optoffset
= 0;
405 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
407 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
411 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
412 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
413 req
->max_optlen
, &optoffset
);
417 packet
->dhcp
.flags
= req
->message
->flags
;
418 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
419 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
421 *_optoffset
= optoffset
;
422 *ret
= TAKE_PTR(packet
);
427 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
429 _cleanup_free_ DHCPPacket
*packet
= NULL
;
434 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
438 packet
->dhcp
.yiaddr
= address
;
440 lease_time
= htobe32(req
->lifetime
);
441 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
442 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
447 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
448 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
452 if (server
->emit_router
) {
453 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
454 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
459 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
466 static int server_send_ack(
467 sd_dhcp_server
*server
,
471 static const uint8_t option_map
[_SD_DHCP_LEASE_SERVER_TYPE_MAX
] = {
472 [SD_DHCP_LEASE_DNS
] = SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
473 [SD_DHCP_LEASE_NTP
] = SD_DHCP_OPTION_NTP_SERVER
,
474 [SD_DHCP_LEASE_SIP
] = SD_DHCP_OPTION_SIP_SERVER
,
475 [SD_DHCP_LEASE_POP3
] = SD_DHCP_OPTION_POP3_SERVER
,
476 [SD_DHCP_LEASE_SMTP
] = SD_DHCP_OPTION_SMTP_SERVER
,
477 [SD_DHCP_LEASE_LPR
] = SD_DHCP_OPTION_LPR_SERVER
,
480 _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 for (sd_dhcp_lease_server_type k
= 0; k
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; k
++) {
513 if (server
->servers
[k
].size
<= 0)
516 r
= dhcp_option_append(
517 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
519 sizeof(struct in_addr
) * server
->servers
[k
].size
, server
->servers
[k
].addr
);
525 if (server
->timezone
) {
526 r
= dhcp_option_append(
527 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
528 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
529 strlen(server
->timezone
), server
->timezone
);
534 ORDERED_HASHMAP_FOREACH(j
, server
->extra_options
) {
535 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
536 j
->option
, j
->length
, j
->data
);
541 if (!ordered_hashmap_isempty(server
->vendor_options
)) {
542 r
= dhcp_option_append(
543 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
544 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
545 ordered_hashmap_size(server
->vendor_options
), server
->vendor_options
);
550 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
557 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
558 _cleanup_free_ DHCPPacket
*packet
= NULL
;
562 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
566 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
569 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
570 be32_t gateway
, const uint8_t chaddr
[]) {
571 _cleanup_free_ DHCPPacket
*packet
= NULL
;
572 size_t optoffset
= 0;
576 assert(address
!= INADDR_ANY
);
579 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
583 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
584 DHCP_FORCERENEW
, ARPHRD_ETHER
,
585 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
589 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
590 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
594 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
596 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
598 sizeof(DHCPMessage
) + optoffset
);
605 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
606 DHCPRequest
*req
= userdata
;
611 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
613 req
->lifetime
= unaligned_read_be32(option
);
616 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
618 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
621 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
623 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
626 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
630 data
= memdup(option
, len
);
634 free(req
->client_id
.data
);
635 req
->client_id
.data
= data
;
636 req
->client_id
.length
= len
;
640 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
642 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
643 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
651 static void dhcp_request_free(DHCPRequest
*req
) {
655 free(req
->client_id
.data
);
659 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
661 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
665 req
->message
= message
;
667 /* set client id based on MAC address if client did not send an explicit
669 if (!req
->client_id
.data
) {
672 data
= malloc0(ETH_ALEN
+ 1);
676 ((uint8_t*) data
)[0] = 0x01;
677 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
679 req
->client_id
.length
= ETH_ALEN
+ 1;
680 req
->client_id
.data
= data
;
683 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
684 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
686 if (req
->lifetime
<= 0)
687 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
689 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
690 req
->lifetime
= server
->max_lease_time
;
695 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
698 if (!server
->pool_size
)
701 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
702 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
705 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
708 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
710 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
712 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
713 _cleanup_free_
char *error_message
= NULL
;
714 DHCPLease
*existing_lease
;
720 if (message
->op
!= BOOTREQUEST
||
721 message
->htype
!= ARPHRD_ETHER
||
722 message
->hlen
!= ETHER_ADDR_LEN
)
725 req
= new0(DHCPRequest
, 1);
729 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
733 r
= ensure_sane_request(server
, req
, message
);
735 /* this only fails on critical errors */
738 existing_lease
= hashmap_get(server
->leases_by_client_id
,
743 case DHCP_DISCOVER
: {
744 be32_t address
= INADDR_ANY
;
747 log_dhcp_server(server
, "DISCOVER (0x%x)",
748 be32toh(req
->message
->xid
));
750 if (!server
->pool_size
)
751 /* no pool allocated */
754 /* for now pick a random free address from the pool */
756 address
= existing_lease
->address
;
758 struct siphash state
;
762 /* even with no persistence of leases, we try to offer the same client
763 the same IP address. we do this by using the hash of the client id
764 as the offset into the pool of leases when finding the next free one */
766 siphash24_init(&state
, HASH_KEY
.bytes
);
767 client_id_hash_func(&req
->client_id
, &state
);
768 hash
= htole64(siphash24_finalize(&state
));
769 next_offer
= hash
% server
->pool_size
;
771 for (i
= 0; i
< server
->pool_size
; i
++) {
772 if (!server
->bound_leases
[next_offer
]) {
773 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
777 next_offer
= (next_offer
+ 1) % server
->pool_size
;
781 if (address
== INADDR_ANY
)
782 /* no free addresses left */
785 r
= server_send_offer(server
, req
, address
);
787 /* this only fails on critical errors */
788 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
790 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
794 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
796 /* TODO: make sure we don't offer this address again */
802 bool init_reboot
= false;
805 /* see RFC 2131, section 4.3.2 */
807 if (req
->server_id
) {
808 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
809 be32toh(req
->message
->xid
));
812 if (req
->server_id
!= server
->address
)
813 /* client did not pick us */
816 if (req
->message
->ciaddr
)
817 /* this MUST be zero */
820 if (!req
->requested_ip
)
821 /* this must be filled in with the yiaddr
822 from the chosen OFFER */
825 address
= req
->requested_ip
;
826 } else if (req
->requested_ip
) {
827 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
828 be32toh(req
->message
->xid
));
831 if (req
->message
->ciaddr
)
832 /* this MUST be zero */
835 /* TODO: check more carefully if IP is correct */
836 address
= req
->requested_ip
;
839 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
840 be32toh(req
->message
->xid
));
842 /* REBINDING / RENEWING */
843 if (!req
->message
->ciaddr
)
844 /* this MUST be filled in with clients IP address */
847 address
= req
->message
->ciaddr
;
850 pool_offset
= get_pool_offset(server
, address
);
852 /* verify that the requested address is from the pool, and either
853 owned by the current client or free */
854 if (pool_offset
>= 0 &&
855 server
->bound_leases
[pool_offset
] == existing_lease
) {
859 if (!existing_lease
) {
860 lease
= new0(DHCPLease
, 1);
863 lease
->address
= address
;
864 lease
->client_id
.data
= memdup(req
->client_id
.data
,
865 req
->client_id
.length
);
866 if (!lease
->client_id
.data
) {
870 lease
->client_id
.length
= req
->client_id
.length
;
871 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
873 lease
->gateway
= req
->message
->giaddr
;
875 lease
= existing_lease
;
877 r
= sd_event_now(server
->event
,
878 clock_boottime_or_monotonic(),
882 dhcp_lease_free(lease
);
886 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
888 r
= server_send_ack(server
, req
, address
);
890 /* this only fails on critical errors */
891 log_dhcp_server_errno(server
, r
, "Could not send ack: %m");
894 dhcp_lease_free(lease
);
898 log_dhcp_server(server
, "ACK (0x%x)",
899 be32toh(req
->message
->xid
));
901 server
->bound_leases
[pool_offset
] = lease
;
902 hashmap_put(server
->leases_by_client_id
,
903 &lease
->client_id
, lease
);
905 if (server
->callback
)
906 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
911 } else if (init_reboot
) {
912 r
= server_send_nak(server
, req
);
914 /* this only fails on critical errors */
915 return log_dhcp_server_errno(server
, r
, "Could not send nak: %m");
917 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
927 log_dhcp_server(server
, "RELEASE (0x%x)",
928 be32toh(req
->message
->xid
));
933 if (existing_lease
->address
!= req
->message
->ciaddr
)
936 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
940 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
941 server
->bound_leases
[pool_offset
] = NULL
;
942 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
943 dhcp_lease_free(existing_lease
);
945 if (server
->callback
)
946 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
955 static int server_receive_message(sd_event_source
*s
, int fd
,
956 uint32_t revents
, void *userdata
) {
957 _cleanup_free_ DHCPMessage
*message
= NULL
;
958 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo
))) control
;
959 sd_dhcp_server
*server
= userdata
;
960 struct iovec iov
= {};
961 struct msghdr msg
= {
964 .msg_control
= &control
,
965 .msg_controllen
= sizeof(control
),
967 struct cmsghdr
*cmsg
;
973 buflen
= next_datagram_size_fd(fd
);
977 message
= malloc(buflen
);
981 iov
= IOVEC_MAKE(message
, buflen
);
983 len
= recvmsg_safe(fd
, &msg
, 0);
984 if (IN_SET(len
, -EAGAIN
, -EINTR
))
988 if ((size_t) len
< sizeof(DHCPMessage
))
991 CMSG_FOREACH(cmsg
, &msg
) {
992 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
993 cmsg
->cmsg_type
== IP_PKTINFO
&&
994 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
995 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
997 /* TODO figure out if this can be done as a filter on
998 * the socket, like for IPv6 */
999 if (server
->ifindex
!= info
->ipi_ifindex
)
1006 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
1008 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message: %m");
1013 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1016 assert_return(server
, -EINVAL
);
1017 assert_return(server
->event
, -EINVAL
);
1018 assert_return(!server
->receive_message
, -EBUSY
);
1019 assert_return(server
->fd_raw
< 0, -EBUSY
);
1020 assert_return(server
->fd
< 0, -EBUSY
);
1021 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1023 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
1026 sd_dhcp_server_stop(server
);
1031 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
, -1);
1033 sd_dhcp_server_stop(server
);
1038 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1039 server
->fd
, EPOLLIN
,
1040 server_receive_message
, server
);
1042 sd_dhcp_server_stop(server
);
1046 r
= sd_event_source_set_priority(server
->receive_message
,
1047 server
->event_priority
);
1049 sd_dhcp_server_stop(server
);
1053 log_dhcp_server(server
, "STARTED");
1058 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1062 assert_return(server
, -EINVAL
);
1063 assert(server
->bound_leases
);
1065 for (i
= 0; i
< server
->pool_size
; i
++) {
1066 DHCPLease
*lease
= server
->bound_leases
[i
];
1068 if (!lease
|| lease
== &server
->invalid_lease
)
1071 r
= server_send_forcerenew(server
, lease
->address
,
1077 log_dhcp_server(server
, "FORCERENEW");
1083 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1086 assert_return(server
, -EINVAL
);
1087 assert_return(timezone_is_valid(tz
, LOG_DEBUG
), -EINVAL
);
1089 if (streq_ptr(tz
, server
->timezone
))
1092 r
= free_and_strdup(&server
->timezone
, tz
);
1099 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1100 assert_return(server
, -EINVAL
);
1102 if (t
== server
->max_lease_time
)
1105 server
->max_lease_time
= t
;
1109 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1110 assert_return(server
, -EINVAL
);
1112 if (t
== server
->default_lease_time
)
1115 server
->default_lease_time
= t
;
1119 int sd_dhcp_server_set_servers(
1120 sd_dhcp_server
*server
,
1121 sd_dhcp_lease_server_type what
,
1122 const struct in_addr addresses
[],
1123 size_t n_addresses
) {
1125 struct in_addr
*c
= NULL
;
1127 assert_return(server
, -EINVAL
);
1128 assert_return(addresses
|| n_addresses
== 0, -EINVAL
);
1129 assert_return(what
>= 0, -EINVAL
);
1130 assert_return(what
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
, -EINVAL
);
1132 if (server
->servers
[what
].size
== n_addresses
&&
1133 memcmp(server
->servers
[what
].addr
, addresses
, sizeof(struct in_addr
) * n_addresses
) == 0)
1136 if (n_addresses
> 0) {
1137 c
= newdup(struct in_addr
, addresses
, n_addresses
);
1142 free(server
->servers
[what
].addr
);
1143 server
->servers
[what
].addr
= c
;
1144 server
->servers
[what
].size
= n_addresses
;
1148 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], size_t n
) {
1149 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_DNS
, dns
, n
);
1151 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], size_t n
) {
1152 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_NTP
, ntp
, n
);
1154 int sd_dhcp_server_set_sip(sd_dhcp_server
*server
, const struct in_addr sip
[], size_t n
) {
1155 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SIP
, sip
, n
);
1157 int sd_dhcp_server_set_pop3(sd_dhcp_server
*server
, const struct in_addr pop3
[], size_t n
) {
1158 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_POP3
, pop3
, n
);
1160 int sd_dhcp_server_set_smtp(sd_dhcp_server
*server
, const struct in_addr smtp
[], size_t n
) {
1161 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SMTP
, smtp
, n
);
1163 int sd_dhcp_server_set_lpr(sd_dhcp_server
*server
, const struct in_addr lpr
[], size_t n
) {
1164 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_LPR
, lpr
, n
);
1167 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1168 assert_return(server
, -EINVAL
);
1170 if (enabled
== server
->emit_router
)
1173 server
->emit_router
= enabled
;
1178 int sd_dhcp_server_add_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1181 assert_return(server
, -EINVAL
);
1182 assert_return(v
, -EINVAL
);
1184 r
= ordered_hashmap_ensure_allocated(&server
->extra_options
, &dhcp_option_hash_ops
);
1188 r
= ordered_hashmap_put(server
->extra_options
, UINT_TO_PTR(v
->option
), v
);
1192 sd_dhcp_option_ref(v
);
1196 int sd_dhcp_server_add_vendor_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1199 assert_return(server
, -EINVAL
);
1200 assert_return(v
, -EINVAL
);
1202 r
= ordered_hashmap_ensure_allocated(&server
->vendor_options
, &dhcp_option_hash_ops
);
1206 r
= ordered_hashmap_put(server
->vendor_options
, v
, v
);
1210 sd_dhcp_option_ref(v
);
1215 int sd_dhcp_server_set_callback(sd_dhcp_server
*server
, sd_dhcp_server_callback_t cb
, void *userdata
) {
1216 assert_return(server
, -EINVAL
);
1218 server
->callback
= cb
;
1219 server
->callback_userdata
= userdata
;