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 void client_id_hash_func(const void *p
, struct siphash
*state
) {
105 const DHCPClientId
*id
= p
;
111 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
112 siphash24_compress(id
->data
, id
->length
, state
);
115 int client_id_compare_func(const void *_a
, const void *_b
) {
116 const DHCPClientId
*a
, *b
;
122 assert(!a
->length
|| a
->data
);
123 assert(!b
->length
|| b
->data
);
125 r
= CMP(a
->length
, b
->length
);
129 return memcmp(a
->data
, b
->data
, a
->length
);
132 static const struct hash_ops client_id_hash_ops
= {
133 .hash
= client_id_hash_func
,
134 .compare
= client_id_compare_func
137 static sd_dhcp_server
*dhcp_server_free(sd_dhcp_server
*server
) {
142 log_dhcp_server(server
, "UNREF");
144 sd_dhcp_server_stop(server
);
146 sd_event_unref(server
->event
);
148 free(server
->timezone
);
152 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
153 dhcp_lease_free(lease
);
154 hashmap_free(server
->leases_by_client_id
);
156 free(server
->bound_leases
);
157 return mfree(server
);
160 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server
, sd_dhcp_server
, dhcp_server_free
);
162 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
163 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
165 assert_return(ret
, -EINVAL
);
166 assert_return(ifindex
> 0, -EINVAL
);
168 server
= new0(sd_dhcp_server
, 1);
175 server
->address
= htobe32(INADDR_ANY
);
176 server
->netmask
= htobe32(INADDR_ANY
);
177 server
->ifindex
= ifindex
;
179 server
->leases_by_client_id
= hashmap_new(&client_id_hash_ops
);
180 if (!server
->leases_by_client_id
)
183 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
184 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
186 *ret
= TAKE_PTR(server
);
191 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
194 assert_return(server
, -EINVAL
);
195 assert_return(!server
->event
, -EBUSY
);
198 server
->event
= sd_event_ref(event
);
200 r
= sd_event_default(&server
->event
);
205 server
->event_priority
= priority
;
210 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
211 assert_return(server
, -EINVAL
);
213 server
->event
= sd_event_unref(server
->event
);
218 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
219 assert_return(server
, NULL
);
221 return server
->event
;
224 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
225 assert_return(server
, -EINVAL
);
227 server
->receive_message
=
228 sd_event_source_unref(server
->receive_message
);
230 server
->fd_raw
= safe_close(server
->fd_raw
);
231 server
->fd
= safe_close(server
->fd
);
233 log_dhcp_server(server
, "STOPPED");
238 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
239 DHCPPacket
*packet
, size_t len
) {
240 union sockaddr_union link
= {
241 .ll
.sll_family
= AF_PACKET
,
242 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
243 .ll
.sll_ifindex
= server
->ifindex
,
244 .ll
.sll_halen
= ETH_ALEN
,
248 assert(server
->ifindex
> 0);
249 assert(server
->address
);
251 assert(len
> sizeof(DHCPPacket
));
253 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
255 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
257 DHCP_PORT_CLIENT
, len
);
259 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
262 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
263 uint16_t destination_port
,
264 DHCPMessage
*message
, size_t len
) {
265 union sockaddr_union dest
= {
266 .in
.sin_family
= AF_INET
,
267 .in
.sin_port
= htobe16(destination_port
),
268 .in
.sin_addr
.s_addr
= destination
,
274 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
275 struct msghdr msg
= {
277 .msg_namelen
= sizeof(dest
.in
),
280 .msg_control
= cmsgbuf
,
281 .msg_controllen
= sizeof(cmsgbuf
),
283 struct cmsghdr
*cmsg
;
284 struct in_pktinfo
*pktinfo
;
287 assert(server
->fd
>= 0);
289 assert(len
> sizeof(DHCPMessage
));
291 cmsg
= CMSG_FIRSTHDR(&msg
);
294 cmsg
->cmsg_level
= IPPROTO_IP
;
295 cmsg
->cmsg_type
= IP_PKTINFO
;
296 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
298 /* we attach source interface and address info to the message
299 rather than binding the socket. This will be mostly useful
300 when we gain support for arbitrary number of server addresses
302 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
305 pktinfo
->ipi_ifindex
= server
->ifindex
;
306 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
308 if (sendmsg(server
->fd
, &msg
, 0) < 0)
314 static bool requested_broadcast(DHCPRequest
*req
) {
317 return req
->message
->flags
& htobe16(0x8000);
320 int dhcp_server_send_packet(sd_dhcp_server
*server
,
321 DHCPRequest
*req
, DHCPPacket
*packet
,
322 int type
, size_t optoffset
) {
323 be32_t destination
= INADDR_ANY
;
324 uint16_t destination_port
= DHCP_PORT_CLIENT
;
329 assert(req
->max_optlen
);
330 assert(optoffset
<= req
->max_optlen
);
333 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
334 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
335 4, &server
->address
);
339 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
340 SD_DHCP_OPTION_END
, 0, NULL
);
344 /* RFC 2131 Section 4.1
346 If the ’giaddr’ field in a DHCP message from a client is non-zero,
347 the server sends any return messages to the ’DHCP server’ port on the
348 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
349 field is zero and the ’ciaddr’ field is nonzero, then the server
350 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
351 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
352 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
353 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
354 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
355 messages to the client’s hardware address and ’yiaddr’ address. In
356 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
357 messages to 0xffffffff.
361 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
362 different subnet. The server MUST set the broadcast bit in the
363 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
364 client, because the client may not have a correct network address
365 or subnet mask, and the client may not be answering ARP requests.
367 if (req
->message
->giaddr
) {
368 destination
= req
->message
->giaddr
;
369 destination_port
= DHCP_PORT_SERVER
;
370 if (type
== DHCP_NAK
)
371 packet
->dhcp
.flags
= htobe16(0x8000);
372 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
373 destination
= req
->message
->ciaddr
;
375 if (destination
!= INADDR_ANY
)
376 return dhcp_server_send_udp(server
, destination
,
377 destination_port
, &packet
->dhcp
,
378 sizeof(DHCPMessage
) + optoffset
);
379 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
380 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
381 destination_port
, &packet
->dhcp
,
382 sizeof(DHCPMessage
) + optoffset
);
384 /* we cannot send UDP packet to specific MAC address when the
385 address is not yet configured, so must fall back to raw
387 return dhcp_server_send_unicast_raw(server
, packet
,
388 sizeof(DHCPPacket
) + optoffset
);
391 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
392 uint8_t type
, size_t *_optoffset
,
394 _cleanup_free_ DHCPPacket
*packet
= NULL
;
395 size_t optoffset
= 0;
401 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
403 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
407 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
408 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
409 req
->max_optlen
, &optoffset
);
413 packet
->dhcp
.flags
= req
->message
->flags
;
414 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
415 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
417 *_optoffset
= optoffset
;
418 *ret
= TAKE_PTR(packet
);
423 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
425 _cleanup_free_ DHCPPacket
*packet
= NULL
;
430 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
434 packet
->dhcp
.yiaddr
= address
;
436 lease_time
= htobe32(req
->lifetime
);
437 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
438 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
443 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
444 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
448 if (server
->emit_router
) {
449 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
450 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
455 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
462 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
464 _cleanup_free_ DHCPPacket
*packet
= NULL
;
469 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
473 packet
->dhcp
.yiaddr
= address
;
475 lease_time
= htobe32(req
->lifetime
);
476 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
477 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
482 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
483 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
487 if (server
->emit_router
) {
488 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
489 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
494 if (server
->n_dns
> 0) {
495 r
= dhcp_option_append(
496 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
497 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
498 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
503 if (server
->n_ntp
> 0) {
504 r
= dhcp_option_append(
505 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
506 SD_DHCP_OPTION_NTP_SERVER
,
507 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
512 if (server
->timezone
) {
513 r
= dhcp_option_append(
514 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
515 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
516 strlen(server
->timezone
), server
->timezone
);
521 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
528 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
529 _cleanup_free_ DHCPPacket
*packet
= NULL
;
533 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
537 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
540 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
541 be32_t gateway
, uint8_t chaddr
[]) {
542 _cleanup_free_ DHCPPacket
*packet
= NULL
;
543 size_t optoffset
= 0;
547 assert(address
!= INADDR_ANY
);
550 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
554 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
555 DHCP_FORCERENEW
, ARPHRD_ETHER
,
556 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
560 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
561 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
565 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
567 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
569 sizeof(DHCPMessage
) + optoffset
);
576 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
577 DHCPRequest
*req
= userdata
;
582 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
584 req
->lifetime
= unaligned_read_be32(option
);
587 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
589 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
592 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
594 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
597 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
601 data
= memdup(option
, len
);
605 free(req
->client_id
.data
);
606 req
->client_id
.data
= data
;
607 req
->client_id
.length
= len
;
611 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
613 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
614 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
622 static void dhcp_request_free(DHCPRequest
*req
) {
626 free(req
->client_id
.data
);
630 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
632 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
636 req
->message
= message
;
638 /* set client id based on MAC address if client did not send an explicit
640 if (!req
->client_id
.data
) {
643 data
= malloc0(ETH_ALEN
+ 1);
647 ((uint8_t*) data
)[0] = 0x01;
648 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
650 req
->client_id
.length
= ETH_ALEN
+ 1;
651 req
->client_id
.data
= data
;
654 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
655 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
657 if (req
->lifetime
<= 0)
658 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
660 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
661 req
->lifetime
= server
->max_lease_time
;
666 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
669 if (!server
->pool_size
)
672 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
673 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
676 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
679 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
681 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
683 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
684 _cleanup_free_
char *error_message
= NULL
;
685 DHCPLease
*existing_lease
;
691 if (message
->op
!= BOOTREQUEST
||
692 message
->htype
!= ARPHRD_ETHER
||
693 message
->hlen
!= ETHER_ADDR_LEN
)
696 req
= new0(DHCPRequest
, 1);
700 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
704 r
= ensure_sane_request(server
, req
, message
);
706 /* this only fails on critical errors */
709 existing_lease
= hashmap_get(server
->leases_by_client_id
,
714 case DHCP_DISCOVER
: {
715 be32_t address
= INADDR_ANY
;
718 log_dhcp_server(server
, "DISCOVER (0x%x)",
719 be32toh(req
->message
->xid
));
721 if (!server
->pool_size
)
722 /* no pool allocated */
725 /* for now pick a random free address from the pool */
727 address
= existing_lease
->address
;
729 struct siphash state
;
733 /* even with no persistence of leases, we try to offer the same client
734 the same IP address. we do this by using the hash of the client id
735 as the offset into the pool of leases when finding the next free one */
737 siphash24_init(&state
, HASH_KEY
.bytes
);
738 client_id_hash_func(&req
->client_id
, &state
);
739 hash
= htole64(siphash24_finalize(&state
));
740 next_offer
= hash
% server
->pool_size
;
742 for (i
= 0; i
< server
->pool_size
; i
++) {
743 if (!server
->bound_leases
[next_offer
]) {
744 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
748 next_offer
= (next_offer
+ 1) % server
->pool_size
;
752 if (address
== INADDR_ANY
)
753 /* no free addresses left */
756 r
= server_send_offer(server
, req
, address
);
758 /* this only fails on critical errors */
759 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
761 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
765 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
767 /* TODO: make sure we don't offer this address again */
773 bool init_reboot
= false;
776 /* see RFC 2131, section 4.3.2 */
778 if (req
->server_id
) {
779 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
780 be32toh(req
->message
->xid
));
783 if (req
->server_id
!= server
->address
)
784 /* client did not pick us */
787 if (req
->message
->ciaddr
)
788 /* this MUST be zero */
791 if (!req
->requested_ip
)
792 /* this must be filled in with the yiaddr
793 from the chosen OFFER */
796 address
= req
->requested_ip
;
797 } else if (req
->requested_ip
) {
798 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
799 be32toh(req
->message
->xid
));
802 if (req
->message
->ciaddr
)
803 /* this MUST be zero */
806 /* TODO: check more carefully if IP is correct */
807 address
= req
->requested_ip
;
810 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
811 be32toh(req
->message
->xid
));
813 /* REBINDING / RENEWING */
814 if (!req
->message
->ciaddr
)
815 /* this MUST be filled in with clients IP address */
818 address
= req
->message
->ciaddr
;
821 pool_offset
= get_pool_offset(server
, address
);
823 /* verify that the requested address is from the pool, and either
824 owned by the current client or free */
825 if (pool_offset
>= 0 &&
826 server
->bound_leases
[pool_offset
] == existing_lease
) {
830 if (!existing_lease
) {
831 lease
= new0(DHCPLease
, 1);
834 lease
->address
= address
;
835 lease
->client_id
.data
= memdup(req
->client_id
.data
,
836 req
->client_id
.length
);
837 if (!lease
->client_id
.data
) {
841 lease
->client_id
.length
= req
->client_id
.length
;
842 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
844 lease
->gateway
= req
->message
->giaddr
;
846 lease
= existing_lease
;
848 r
= sd_event_now(server
->event
,
849 clock_boottime_or_monotonic(),
853 dhcp_lease_free(lease
);
857 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
859 r
= server_send_ack(server
, req
, address
);
861 /* this only fails on critical errors */
862 log_dhcp_server_errno(server
, r
, "Could not send ack: %m");
865 dhcp_lease_free(lease
);
869 log_dhcp_server(server
, "ACK (0x%x)",
870 be32toh(req
->message
->xid
));
872 server
->bound_leases
[pool_offset
] = lease
;
873 hashmap_put(server
->leases_by_client_id
,
874 &lease
->client_id
, lease
);
879 } else if (init_reboot
) {
880 r
= server_send_nak(server
, req
);
882 /* this only fails on critical errors */
883 return log_dhcp_server_errno(server
, r
, "Could not send nak: %m");
885 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
895 log_dhcp_server(server
, "RELEASE (0x%x)",
896 be32toh(req
->message
->xid
));
901 if (existing_lease
->address
!= req
->message
->ciaddr
)
904 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
908 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
909 server
->bound_leases
[pool_offset
] = NULL
;
910 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
911 dhcp_lease_free(existing_lease
);
920 static int server_receive_message(sd_event_source
*s
, int fd
,
921 uint32_t revents
, void *userdata
) {
922 _cleanup_free_ DHCPMessage
*message
= NULL
;
923 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
924 sd_dhcp_server
*server
= userdata
;
925 struct iovec iov
= {};
926 struct msghdr msg
= {
929 .msg_control
= cmsgbuf
,
930 .msg_controllen
= sizeof(cmsgbuf
),
932 struct cmsghdr
*cmsg
;
938 buflen
= next_datagram_size_fd(fd
);
942 message
= malloc(buflen
);
946 iov
.iov_base
= message
;
947 iov
.iov_len
= buflen
;
949 len
= recvmsg(fd
, &msg
, 0);
951 if (IN_SET(errno
, EAGAIN
, EINTR
))
956 if ((size_t)len
< sizeof(DHCPMessage
))
959 CMSG_FOREACH(cmsg
, &msg
) {
960 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
961 cmsg
->cmsg_type
== IP_PKTINFO
&&
962 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
963 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
965 /* TODO figure out if this can be done as a filter on
966 * the socket, like for IPv6 */
967 if (server
->ifindex
!= info
->ipi_ifindex
)
974 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
976 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message: %m");
981 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
984 assert_return(server
, -EINVAL
);
985 assert_return(server
->event
, -EINVAL
);
986 assert_return(!server
->receive_message
, -EBUSY
);
987 assert_return(server
->fd_raw
< 0, -EBUSY
);
988 assert_return(server
->fd
< 0, -EBUSY
);
989 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
991 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
994 sd_dhcp_server_stop(server
);
999 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
);
1001 sd_dhcp_server_stop(server
);
1006 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1007 server
->fd
, EPOLLIN
,
1008 server_receive_message
, server
);
1010 sd_dhcp_server_stop(server
);
1014 r
= sd_event_source_set_priority(server
->receive_message
,
1015 server
->event_priority
);
1017 sd_dhcp_server_stop(server
);
1021 log_dhcp_server(server
, "STARTED");
1026 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1030 assert_return(server
, -EINVAL
);
1031 assert(server
->bound_leases
);
1033 for (i
= 0; i
< server
->pool_size
; i
++) {
1034 DHCPLease
*lease
= server
->bound_leases
[i
];
1036 if (!lease
|| lease
== &server
->invalid_lease
)
1039 r
= server_send_forcerenew(server
, lease
->address
,
1045 log_dhcp_server(server
, "FORCERENEW");
1051 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1054 assert_return(server
, -EINVAL
);
1055 assert_return(timezone_is_valid(tz
, LOG_DEBUG
), -EINVAL
);
1057 if (streq_ptr(tz
, server
->timezone
))
1060 r
= free_and_strdup(&server
->timezone
, tz
);
1067 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1068 assert_return(server
, -EINVAL
);
1070 if (t
== server
->max_lease_time
)
1073 server
->max_lease_time
= t
;
1077 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1078 assert_return(server
, -EINVAL
);
1080 if (t
== server
->default_lease_time
)
1083 server
->default_lease_time
= t
;
1087 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1088 assert_return(server
, -EINVAL
);
1089 assert_return(dns
|| n
<= 0, -EINVAL
);
1091 if (server
->n_dns
== n
&&
1092 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1096 server
->dns
= mfree(server
->dns
);
1101 c
= newdup(struct in_addr
, dns
, n
);
1113 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1114 assert_return(server
, -EINVAL
);
1115 assert_return(ntp
|| n
<= 0, -EINVAL
);
1117 if (server
->n_ntp
== n
&&
1118 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1122 server
->ntp
= mfree(server
->ntp
);
1127 c
= newdup(struct in_addr
, ntp
, n
);
1139 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1140 assert_return(server
, -EINVAL
);
1142 if (enabled
== server
->emit_router
)
1145 server
->emit_router
= enabled
;