1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
8 #include "sd-dhcp-server.h"
10 #include "alloc-util.h"
11 #include "dhcp-internal.h"
12 #include "dhcp-server-internal.h"
14 #include "in-addr-util.h"
16 #include "siphash24.h"
17 #include "string-util.h"
18 #include "unaligned.h"
20 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
21 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
23 static void dhcp_lease_free(DHCPLease
*lease
) {
27 free(lease
->client_id
.data
);
31 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
32 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
33 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
34 * accidentally hand it out */
35 int sd_dhcp_server_configure_pool(sd_dhcp_server
*server
, struct in_addr
*address
, unsigned char prefixlen
, uint32_t offset
, uint32_t size
) {
36 struct in_addr netmask_addr
;
38 uint32_t server_off
, broadcast_off
, size_max
;
40 assert_return(server
, -EINVAL
);
41 assert_return(address
, -EINVAL
);
42 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
43 assert_return(prefixlen
<= 32, -ERANGE
);
45 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
46 netmask
= netmask_addr
.s_addr
;
48 server_off
= be32toh(address
->s_addr
& ~netmask
);
49 broadcast_off
= be32toh(~netmask
);
51 /* the server address cannot be the subnet address */
52 assert_return(server_off
!= 0, -ERANGE
);
54 /* nor the broadcast address */
55 assert_return(server_off
!= broadcast_off
, -ERANGE
);
57 /* 0 offset means we should set a default, we skip the first (subnet) address
58 and take the next one */
62 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
63 - offset
/* exclude the addresses before the offset */
64 - 1; /* exclude the last (broadcast) address */
66 /* The pool must contain at least one address */
67 assert_return(size_max
>= 1, -ERANGE
);
70 assert_return(size
<= size_max
, -ERANGE
);
74 if (server
->address
!= address
->s_addr
|| server
->netmask
!= netmask
|| server
->pool_size
!= size
|| server
->pool_offset
!= offset
) {
76 free(server
->bound_leases
);
77 server
->bound_leases
= new0(DHCPLease
*, size
);
78 if (!server
->bound_leases
)
81 server
->pool_offset
= offset
;
82 server
->pool_size
= size
;
84 server
->address
= address
->s_addr
;
85 server
->netmask
= netmask
;
86 server
->subnet
= address
->s_addr
& netmask
;
88 if (server_off
>= offset
&& server_off
- offset
< size
)
89 server
->bound_leases
[server_off
- offset
] = &server
->invalid_lease
;
91 /* Drop any leases associated with the old address range */
92 hashmap_clear_with_destructor(server
->leases_by_client_id
, dhcp_lease_free
);
98 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
99 assert_return(server
, false);
101 return !!server
->receive_message
;
104 sd_dhcp_server
*sd_dhcp_server_ref(sd_dhcp_server
*server
) {
109 assert(server
->n_ref
>= 1);
115 void client_id_hash_func(const void *p
, struct siphash
*state
) {
116 const DHCPClientId
*id
= p
;
122 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
123 siphash24_compress(id
->data
, id
->length
, state
);
126 int client_id_compare_func(const void *_a
, const void *_b
) {
127 const DHCPClientId
*a
, *b
;
133 assert(!a
->length
|| a
->data
);
134 assert(!b
->length
|| b
->data
);
136 r
= CMP(a
->length
, b
->length
);
140 return memcmp(a
->data
, b
->data
, a
->length
);
143 static const struct hash_ops client_id_hash_ops
= {
144 .hash
= client_id_hash_func
,
145 .compare
= client_id_compare_func
148 sd_dhcp_server
*sd_dhcp_server_unref(sd_dhcp_server
*server
) {
154 assert(server
->n_ref
>= 1);
157 if (server
->n_ref
> 0)
160 log_dhcp_server(server
, "UNREF");
162 sd_dhcp_server_stop(server
);
164 sd_event_unref(server
->event
);
166 free(server
->timezone
);
170 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
171 dhcp_lease_free(lease
);
172 hashmap_free(server
->leases_by_client_id
);
174 free(server
->bound_leases
);
175 return mfree(server
);
178 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
179 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
181 assert_return(ret
, -EINVAL
);
182 assert_return(ifindex
> 0, -EINVAL
);
184 server
= new0(sd_dhcp_server
, 1);
191 server
->address
= htobe32(INADDR_ANY
);
192 server
->netmask
= htobe32(INADDR_ANY
);
193 server
->ifindex
= ifindex
;
195 server
->leases_by_client_id
= hashmap_new(&client_id_hash_ops
);
196 if (!server
->leases_by_client_id
)
199 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
200 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
202 *ret
= TAKE_PTR(server
);
207 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
210 assert_return(server
, -EINVAL
);
211 assert_return(!server
->event
, -EBUSY
);
214 server
->event
= sd_event_ref(event
);
216 r
= sd_event_default(&server
->event
);
221 server
->event_priority
= priority
;
226 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
227 assert_return(server
, -EINVAL
);
229 server
->event
= sd_event_unref(server
->event
);
234 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
235 assert_return(server
, NULL
);
237 return server
->event
;
240 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
241 assert_return(server
, -EINVAL
);
243 server
->receive_message
=
244 sd_event_source_unref(server
->receive_message
);
246 server
->fd_raw
= safe_close(server
->fd_raw
);
247 server
->fd
= safe_close(server
->fd
);
249 log_dhcp_server(server
, "STOPPED");
254 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
255 DHCPPacket
*packet
, size_t len
) {
256 union sockaddr_union link
= {
257 .ll
.sll_family
= AF_PACKET
,
258 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
259 .ll
.sll_ifindex
= server
->ifindex
,
260 .ll
.sll_halen
= ETH_ALEN
,
264 assert(server
->ifindex
> 0);
265 assert(server
->address
);
267 assert(len
> sizeof(DHCPPacket
));
269 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
271 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
273 DHCP_PORT_CLIENT
, len
);
275 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
278 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
279 uint16_t destination_port
,
280 DHCPMessage
*message
, size_t len
) {
281 union sockaddr_union dest
= {
282 .in
.sin_family
= AF_INET
,
283 .in
.sin_port
= htobe16(destination_port
),
284 .in
.sin_addr
.s_addr
= destination
,
290 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
291 struct msghdr msg
= {
293 .msg_namelen
= sizeof(dest
.in
),
296 .msg_control
= cmsgbuf
,
297 .msg_controllen
= sizeof(cmsgbuf
),
299 struct cmsghdr
*cmsg
;
300 struct in_pktinfo
*pktinfo
;
303 assert(server
->fd
>= 0);
305 assert(len
> sizeof(DHCPMessage
));
307 cmsg
= CMSG_FIRSTHDR(&msg
);
310 cmsg
->cmsg_level
= IPPROTO_IP
;
311 cmsg
->cmsg_type
= IP_PKTINFO
;
312 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
314 /* we attach source interface and address info to the message
315 rather than binding the socket. This will be mostly useful
316 when we gain support for arbitrary number of server addresses
318 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
321 pktinfo
->ipi_ifindex
= server
->ifindex
;
322 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
324 if (sendmsg(server
->fd
, &msg
, 0) < 0)
330 static bool requested_broadcast(DHCPRequest
*req
) {
333 return req
->message
->flags
& htobe16(0x8000);
336 int dhcp_server_send_packet(sd_dhcp_server
*server
,
337 DHCPRequest
*req
, DHCPPacket
*packet
,
338 int type
, size_t optoffset
) {
339 be32_t destination
= INADDR_ANY
;
340 uint16_t destination_port
= DHCP_PORT_CLIENT
;
345 assert(req
->max_optlen
);
346 assert(optoffset
<= req
->max_optlen
);
349 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
350 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
351 4, &server
->address
);
355 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
356 SD_DHCP_OPTION_END
, 0, NULL
);
360 /* RFC 2131 Section 4.1
362 If the ’giaddr’ field in a DHCP message from a client is non-zero,
363 the server sends any return messages to the ’DHCP server’ port on the
364 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
365 field is zero and the ’ciaddr’ field is nonzero, then the server
366 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
367 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
368 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
369 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
370 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
371 messages to the client’s hardware address and ’yiaddr’ address. In
372 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
373 messages to 0xffffffff.
377 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
378 different subnet. The server MUST set the broadcast bit in the
379 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
380 client, because the client may not have a correct network address
381 or subnet mask, and the client may not be answering ARP requests.
383 if (req
->message
->giaddr
) {
384 destination
= req
->message
->giaddr
;
385 destination_port
= DHCP_PORT_SERVER
;
386 if (type
== DHCP_NAK
)
387 packet
->dhcp
.flags
= htobe16(0x8000);
388 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
389 destination
= req
->message
->ciaddr
;
391 if (destination
!= INADDR_ANY
)
392 return dhcp_server_send_udp(server
, destination
,
393 destination_port
, &packet
->dhcp
,
394 sizeof(DHCPMessage
) + optoffset
);
395 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
396 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
397 destination_port
, &packet
->dhcp
,
398 sizeof(DHCPMessage
) + optoffset
);
400 /* we cannot send UDP packet to specific MAC address when the
401 address is not yet configured, so must fall back to raw
403 return dhcp_server_send_unicast_raw(server
, packet
,
404 sizeof(DHCPPacket
) + optoffset
);
407 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
408 uint8_t type
, size_t *_optoffset
,
410 _cleanup_free_ DHCPPacket
*packet
= NULL
;
411 size_t optoffset
= 0;
417 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
419 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
423 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
424 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
425 req
->max_optlen
, &optoffset
);
429 packet
->dhcp
.flags
= req
->message
->flags
;
430 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
431 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
433 *_optoffset
= optoffset
;
434 *ret
= TAKE_PTR(packet
);
439 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
441 _cleanup_free_ DHCPPacket
*packet
= NULL
;
446 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
450 packet
->dhcp
.yiaddr
= address
;
452 lease_time
= htobe32(req
->lifetime
);
453 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
454 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
459 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
460 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
464 if (server
->emit_router
) {
465 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
466 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
471 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
478 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
480 _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 if (server
->n_dns
> 0) {
511 r
= dhcp_option_append(
512 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
513 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
514 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
519 if (server
->n_ntp
> 0) {
520 r
= dhcp_option_append(
521 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
522 SD_DHCP_OPTION_NTP_SERVER
,
523 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
528 if (server
->timezone
) {
529 r
= dhcp_option_append(
530 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
531 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
532 strlen(server
->timezone
), server
->timezone
);
537 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
544 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
545 _cleanup_free_ DHCPPacket
*packet
= NULL
;
549 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
553 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
556 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
557 be32_t gateway
, uint8_t chaddr
[]) {
558 _cleanup_free_ DHCPPacket
*packet
= NULL
;
559 size_t optoffset
= 0;
563 assert(address
!= INADDR_ANY
);
566 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
570 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
571 DHCP_FORCERENEW
, ARPHRD_ETHER
,
572 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
576 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
577 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
581 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
583 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
585 sizeof(DHCPMessage
) + optoffset
);
592 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
593 DHCPRequest
*req
= userdata
;
598 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
600 req
->lifetime
= unaligned_read_be32(option
);
603 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
605 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
608 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
610 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
613 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
617 data
= memdup(option
, len
);
621 free(req
->client_id
.data
);
622 req
->client_id
.data
= data
;
623 req
->client_id
.length
= len
;
627 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
629 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
630 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
638 static void dhcp_request_free(DHCPRequest
*req
) {
642 free(req
->client_id
.data
);
646 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
648 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
652 req
->message
= message
;
654 /* set client id based on MAC address if client did not send an explicit
656 if (!req
->client_id
.data
) {
659 data
= malloc0(ETH_ALEN
+ 1);
663 ((uint8_t*) data
)[0] = 0x01;
664 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
666 req
->client_id
.length
= ETH_ALEN
+ 1;
667 req
->client_id
.data
= data
;
670 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
671 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
673 if (req
->lifetime
<= 0)
674 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
676 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
677 req
->lifetime
= server
->max_lease_time
;
682 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
685 if (!server
->pool_size
)
688 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
689 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
692 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
695 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
697 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
699 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
700 _cleanup_free_
char *error_message
= NULL
;
701 DHCPLease
*existing_lease
;
707 if (message
->op
!= BOOTREQUEST
||
708 message
->htype
!= ARPHRD_ETHER
||
709 message
->hlen
!= ETHER_ADDR_LEN
)
712 req
= new0(DHCPRequest
, 1);
716 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
720 r
= ensure_sane_request(server
, req
, message
);
722 /* this only fails on critical errors */
725 existing_lease
= hashmap_get(server
->leases_by_client_id
,
730 case DHCP_DISCOVER
: {
731 be32_t address
= INADDR_ANY
;
734 log_dhcp_server(server
, "DISCOVER (0x%x)",
735 be32toh(req
->message
->xid
));
737 if (!server
->pool_size
)
738 /* no pool allocated */
741 /* for now pick a random free address from the pool */
743 address
= existing_lease
->address
;
745 struct siphash state
;
749 /* even with no persistence of leases, we try to offer the same client
750 the same IP address. we do this by using the hash of the client id
751 as the offset into the pool of leases when finding the next free one */
753 siphash24_init(&state
, HASH_KEY
.bytes
);
754 client_id_hash_func(&req
->client_id
, &state
);
755 hash
= htole64(siphash24_finalize(&state
));
756 next_offer
= hash
% server
->pool_size
;
758 for (i
= 0; i
< server
->pool_size
; i
++) {
759 if (!server
->bound_leases
[next_offer
]) {
760 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
764 next_offer
= (next_offer
+ 1) % server
->pool_size
;
768 if (address
== INADDR_ANY
)
769 /* no free addresses left */
772 r
= server_send_offer(server
, req
, address
);
774 /* this only fails on critical errors */
775 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
777 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
781 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
783 /* TODO: make sure we don't offer this address again */
789 bool init_reboot
= false;
792 /* see RFC 2131, section 4.3.2 */
794 if (req
->server_id
) {
795 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
796 be32toh(req
->message
->xid
));
799 if (req
->server_id
!= server
->address
)
800 /* client did not pick us */
803 if (req
->message
->ciaddr
)
804 /* this MUST be zero */
807 if (!req
->requested_ip
)
808 /* this must be filled in with the yiaddr
809 from the chosen OFFER */
812 address
= req
->requested_ip
;
813 } else if (req
->requested_ip
) {
814 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
815 be32toh(req
->message
->xid
));
818 if (req
->message
->ciaddr
)
819 /* this MUST be zero */
822 /* TODO: check more carefully if IP is correct */
823 address
= req
->requested_ip
;
826 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
827 be32toh(req
->message
->xid
));
829 /* REBINDING / RENEWING */
830 if (!req
->message
->ciaddr
)
831 /* this MUST be filled in with clients IP address */
834 address
= req
->message
->ciaddr
;
837 pool_offset
= get_pool_offset(server
, address
);
839 /* verify that the requested address is from the pool, and either
840 owned by the current client or free */
841 if (pool_offset
>= 0 &&
842 server
->bound_leases
[pool_offset
] == existing_lease
) {
846 if (!existing_lease
) {
847 lease
= new0(DHCPLease
, 1);
850 lease
->address
= address
;
851 lease
->client_id
.data
= memdup(req
->client_id
.data
,
852 req
->client_id
.length
);
853 if (!lease
->client_id
.data
) {
857 lease
->client_id
.length
= req
->client_id
.length
;
858 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
860 lease
->gateway
= req
->message
->giaddr
;
862 lease
= existing_lease
;
864 r
= sd_event_now(server
->event
,
865 clock_boottime_or_monotonic(),
869 dhcp_lease_free(lease
);
873 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
875 r
= server_send_ack(server
, req
, address
);
877 /* this only fails on critical errors */
878 log_dhcp_server_errno(server
, r
, "Could not send ack: %m");
881 dhcp_lease_free(lease
);
885 log_dhcp_server(server
, "ACK (0x%x)",
886 be32toh(req
->message
->xid
));
888 server
->bound_leases
[pool_offset
] = lease
;
889 hashmap_put(server
->leases_by_client_id
,
890 &lease
->client_id
, lease
);
895 } else if (init_reboot
) {
896 r
= server_send_nak(server
, req
);
898 /* this only fails on critical errors */
899 return log_dhcp_server_errno(server
, r
, "Could not send nak: %m");
901 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
911 log_dhcp_server(server
, "RELEASE (0x%x)",
912 be32toh(req
->message
->xid
));
917 if (existing_lease
->address
!= req
->message
->ciaddr
)
920 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
924 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
925 server
->bound_leases
[pool_offset
] = NULL
;
926 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
927 dhcp_lease_free(existing_lease
);
936 static int server_receive_message(sd_event_source
*s
, int fd
,
937 uint32_t revents
, void *userdata
) {
938 _cleanup_free_ DHCPMessage
*message
= NULL
;
939 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
940 sd_dhcp_server
*server
= userdata
;
941 struct iovec iov
= {};
942 struct msghdr msg
= {
945 .msg_control
= cmsgbuf
,
946 .msg_controllen
= sizeof(cmsgbuf
),
948 struct cmsghdr
*cmsg
;
954 buflen
= next_datagram_size_fd(fd
);
958 message
= malloc(buflen
);
962 iov
.iov_base
= message
;
963 iov
.iov_len
= buflen
;
965 len
= recvmsg(fd
, &msg
, 0);
967 if (IN_SET(errno
, EAGAIN
, EINTR
))
972 if ((size_t)len
< sizeof(DHCPMessage
))
975 CMSG_FOREACH(cmsg
, &msg
) {
976 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
977 cmsg
->cmsg_type
== IP_PKTINFO
&&
978 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
979 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
981 /* TODO figure out if this can be done as a filter on
982 * the socket, like for IPv6 */
983 if (server
->ifindex
!= info
->ipi_ifindex
)
990 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
992 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message: %m");
997 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1000 assert_return(server
, -EINVAL
);
1001 assert_return(server
->event
, -EINVAL
);
1002 assert_return(!server
->receive_message
, -EBUSY
);
1003 assert_return(server
->fd_raw
< 0, -EBUSY
);
1004 assert_return(server
->fd
< 0, -EBUSY
);
1005 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1007 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1010 sd_dhcp_server_stop(server
);
1015 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
);
1017 sd_dhcp_server_stop(server
);
1022 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1023 server
->fd
, EPOLLIN
,
1024 server_receive_message
, server
);
1026 sd_dhcp_server_stop(server
);
1030 r
= sd_event_source_set_priority(server
->receive_message
,
1031 server
->event_priority
);
1033 sd_dhcp_server_stop(server
);
1037 log_dhcp_server(server
, "STARTED");
1042 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1046 assert_return(server
, -EINVAL
);
1047 assert(server
->bound_leases
);
1049 for (i
= 0; i
< server
->pool_size
; i
++) {
1050 DHCPLease
*lease
= server
->bound_leases
[i
];
1052 if (!lease
|| lease
== &server
->invalid_lease
)
1055 r
= server_send_forcerenew(server
, lease
->address
,
1061 log_dhcp_server(server
, "FORCERENEW");
1067 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1070 assert_return(server
, -EINVAL
);
1071 assert_return(timezone_is_valid(tz
, LOG_DEBUG
), -EINVAL
);
1073 if (streq_ptr(tz
, server
->timezone
))
1076 r
= free_and_strdup(&server
->timezone
, tz
);
1083 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1084 assert_return(server
, -EINVAL
);
1086 if (t
== server
->max_lease_time
)
1089 server
->max_lease_time
= t
;
1093 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1094 assert_return(server
, -EINVAL
);
1096 if (t
== server
->default_lease_time
)
1099 server
->default_lease_time
= t
;
1103 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1104 assert_return(server
, -EINVAL
);
1105 assert_return(dns
|| n
<= 0, -EINVAL
);
1107 if (server
->n_dns
== n
&&
1108 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1112 server
->dns
= mfree(server
->dns
);
1117 c
= newdup(struct in_addr
, dns
, n
);
1129 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1130 assert_return(server
, -EINVAL
);
1131 assert_return(ntp
|| n
<= 0, -EINVAL
);
1133 if (server
->n_ntp
== n
&&
1134 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1138 server
->ntp
= mfree(server
->ntp
);
1143 c
= newdup(struct in_addr
, ntp
, n
);
1155 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1156 assert_return(server
, -EINVAL
);
1158 if (enabled
== server
->emit_router
)
1161 server
->emit_router
= enabled
;