2 This file is part of systemd.
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5 Copyright (C) 2014 Tom Gundersen
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/ioctl.h>
23 #include "sd-dhcp-server.h"
25 #include "alloc-util.h"
26 #include "dhcp-internal.h"
27 #include "dhcp-server-internal.h"
29 #include "in-addr-util.h"
30 #include "siphash24.h"
31 #include "string-util.h"
33 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
34 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
36 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
37 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
38 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
39 * accidentally hand it out */
40 int sd_dhcp_server_configure_pool(sd_dhcp_server
*server
, struct in_addr
*address
, unsigned char prefixlen
, uint32_t offset
, uint32_t size
) {
41 struct in_addr netmask_addr
;
43 uint32_t server_off
, broadcast_off
, size_max
;
45 assert_return(server
, -EINVAL
);
46 assert_return(address
, -EINVAL
);
47 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
48 assert_return(prefixlen
<= 32, -ERANGE
);
49 assert_return(server
->address
== INADDR_ANY
, -EBUSY
);
51 assert_se(in_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
52 netmask
= netmask_addr
.s_addr
;
54 server_off
= be32toh(address
->s_addr
& ~netmask
);
55 broadcast_off
= be32toh(~netmask
);
57 /* the server address cannot be the subnet address */
58 assert_return(server_off
!= 0, -ERANGE
);
60 /* nor the broadcast address */
61 assert_return(server_off
!= broadcast_off
, -ERANGE
);
63 /* 0 offset means we should set a default, we skip the first (subnet) address
64 and take the next one */
68 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
69 - offset
/* exclude the addresses before the offset */
70 - 1; /* exclude the last (broadcast) address */
72 /* The pool must contain at least one address */
73 assert_return(size_max
>= 1, -ERANGE
);
76 assert_return(size
<= size_max
, -ERANGE
);
80 server
->bound_leases
= new0(DHCPLease
*, size
);
81 if (!server
->bound_leases
)
84 server
->pool_offset
= offset
;
85 server
->pool_size
= size
;
87 server
->address
= address
->s_addr
;
88 server
->netmask
= netmask
;
89 server
->subnet
= address
->s_addr
& netmask
;
91 if (server_off
>= offset
&& server_off
- offset
< size
)
92 server
->bound_leases
[server_off
- offset
] = &server
->invalid_lease
;
97 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
98 assert_return(server
, false);
100 return !!server
->receive_message
;
103 sd_dhcp_server
*sd_dhcp_server_ref(sd_dhcp_server
*server
) {
108 assert(server
->n_ref
>= 1);
114 void client_id_hash_func(const void *p
, struct siphash
*state
) {
115 const DHCPClientId
*id
= p
;
121 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
122 siphash24_compress(id
->data
, id
->length
, state
);
125 int client_id_compare_func(const void *_a
, const void *_b
) {
126 const DHCPClientId
*a
, *b
;
131 assert(!a
->length
|| a
->data
);
132 assert(!b
->length
|| b
->data
);
134 if (a
->length
!= b
->length
)
135 return a
->length
< b
->length
? -1 : 1;
137 return memcmp(a
->data
, b
->data
, a
->length
);
140 static const struct hash_ops client_id_hash_ops
= {
141 .hash
= client_id_hash_func
,
142 .compare
= client_id_compare_func
145 static void dhcp_lease_free(DHCPLease
*lease
) {
149 free(lease
->client_id
.data
);
153 sd_dhcp_server
*sd_dhcp_server_unref(sd_dhcp_server
*server
) {
159 assert(server
->n_ref
>= 1);
162 if (server
->n_ref
> 0)
165 log_dhcp_server(server
, "UNREF");
167 sd_dhcp_server_stop(server
);
169 sd_event_unref(server
->event
);
171 free(server
->timezone
);
175 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
176 dhcp_lease_free(lease
);
177 hashmap_free(server
->leases_by_client_id
);
179 free(server
->bound_leases
);
185 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
186 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
188 assert_return(ret
, -EINVAL
);
189 assert_return(ifindex
> 0, -EINVAL
);
191 server
= new0(sd_dhcp_server
, 1);
198 server
->address
= htobe32(INADDR_ANY
);
199 server
->netmask
= htobe32(INADDR_ANY
);
200 server
->ifindex
= ifindex
;
201 server
->leases_by_client_id
= hashmap_new(&client_id_hash_ops
);
202 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
203 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
211 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
214 assert_return(server
, -EINVAL
);
215 assert_return(!server
->event
, -EBUSY
);
218 server
->event
= sd_event_ref(event
);
220 r
= sd_event_default(&server
->event
);
225 server
->event_priority
= priority
;
230 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
231 assert_return(server
, -EINVAL
);
233 server
->event
= sd_event_unref(server
->event
);
238 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
239 assert_return(server
, NULL
);
241 return server
->event
;
244 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
245 assert_return(server
, -EINVAL
);
247 server
->receive_message
=
248 sd_event_source_unref(server
->receive_message
);
250 server
->fd_raw
= safe_close(server
->fd_raw
);
251 server
->fd
= safe_close(server
->fd
);
253 log_dhcp_server(server
, "STOPPED");
258 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
259 DHCPPacket
*packet
, size_t len
) {
260 union sockaddr_union link
= {
261 .ll
.sll_family
= AF_PACKET
,
262 .ll
.sll_protocol
= htons(ETH_P_IP
),
263 .ll
.sll_ifindex
= server
->ifindex
,
264 .ll
.sll_halen
= ETH_ALEN
,
268 assert(server
->ifindex
> 0);
269 assert(server
->address
);
271 assert(len
> sizeof(DHCPPacket
));
273 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
275 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
277 DHCP_PORT_CLIENT
, len
);
279 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
282 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
283 uint16_t destination_port
,
284 DHCPMessage
*message
, size_t len
) {
285 union sockaddr_union dest
= {
286 .in
.sin_family
= AF_INET
,
287 .in
.sin_port
= htobe16(destination_port
),
288 .in
.sin_addr
.s_addr
= destination
,
294 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
295 struct msghdr msg
= {
297 .msg_namelen
= sizeof(dest
.in
),
300 .msg_control
= cmsgbuf
,
301 .msg_controllen
= sizeof(cmsgbuf
),
303 struct cmsghdr
*cmsg
;
304 struct in_pktinfo
*pktinfo
;
308 assert(server
->fd
> 0);
310 assert(len
> sizeof(DHCPMessage
));
312 cmsg
= CMSG_FIRSTHDR(&msg
);
315 cmsg
->cmsg_level
= IPPROTO_IP
;
316 cmsg
->cmsg_type
= IP_PKTINFO
;
317 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
319 /* we attach source interface and address info to the message
320 rather than binding the socket. This will be mostly useful
321 when we gain support for arbitrary number of server addresses
323 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
326 pktinfo
->ipi_ifindex
= server
->ifindex
;
327 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
329 r
= sendmsg(server
->fd
, &msg
, 0);
336 static bool requested_broadcast(DHCPRequest
*req
) {
339 return req
->message
->flags
& htobe16(0x8000);
342 int dhcp_server_send_packet(sd_dhcp_server
*server
,
343 DHCPRequest
*req
, DHCPPacket
*packet
,
344 int type
, size_t optoffset
) {
345 be32_t destination
= INADDR_ANY
;
346 uint16_t destination_port
= DHCP_PORT_CLIENT
;
351 assert(req
->max_optlen
);
352 assert(optoffset
<= req
->max_optlen
);
355 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
356 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
357 4, &server
->address
);
361 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
362 SD_DHCP_OPTION_END
, 0, NULL
);
366 /* RFC 2131 Section 4.1
368 If the ’giaddr’ field in a DHCP message from a client is non-zero,
369 the server sends any return messages to the ’DHCP server’ port on the
370 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
371 field is zero and the ’ciaddr’ field is nonzero, then the server
372 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
373 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
374 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
375 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
376 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
377 messages to the client’s hardware address and ’yiaddr’ address. In
378 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
379 messages to 0xffffffff.
383 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
384 different subnet. The server MUST set the broadcast bit in the
385 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
386 client, because the client may not have a correct network address
387 or subnet mask, and the client may not be answering ARP requests.
389 if (req
->message
->giaddr
) {
390 destination
= req
->message
->giaddr
;
391 destination_port
= DHCP_PORT_SERVER
;
392 if (type
== DHCP_NAK
)
393 packet
->dhcp
.flags
= htobe16(0x8000);
394 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
395 destination
= req
->message
->ciaddr
;
397 if (destination
!= INADDR_ANY
)
398 return dhcp_server_send_udp(server
, destination
,
399 destination_port
, &packet
->dhcp
,
400 sizeof(DHCPMessage
) + optoffset
);
401 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
402 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
403 destination_port
, &packet
->dhcp
,
404 sizeof(DHCPMessage
) + optoffset
);
406 /* we cannot send UDP packet to specific MAC address when the
407 address is not yet configured, so must fall back to raw
409 return dhcp_server_send_unicast_raw(server
, packet
,
410 sizeof(DHCPPacket
) + optoffset
);
413 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
414 uint8_t type
, size_t *_optoffset
,
416 _cleanup_free_ DHCPPacket
*packet
= NULL
;
417 size_t optoffset
= 0;
423 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
425 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
429 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
430 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
431 req
->max_optlen
, &optoffset
);
435 packet
->dhcp
.flags
= req
->message
->flags
;
436 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
437 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
439 *_optoffset
= optoffset
;
446 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
448 _cleanup_free_ DHCPPacket
*packet
= NULL
;
453 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
457 packet
->dhcp
.yiaddr
= address
;
459 lease_time
= htobe32(req
->lifetime
);
460 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
461 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
466 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
467 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
471 if (server
->emit_router
) {
472 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
473 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
478 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
485 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
487 _cleanup_free_ DHCPPacket
*packet
= NULL
;
492 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
496 packet
->dhcp
.yiaddr
= address
;
498 lease_time
= htobe32(req
->lifetime
);
499 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
500 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
505 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
506 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
510 if (server
->emit_router
) {
511 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
512 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
517 if (server
->n_dns
> 0) {
518 r
= dhcp_option_append(
519 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
520 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
521 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
526 if (server
->n_ntp
> 0) {
527 r
= dhcp_option_append(
528 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
529 SD_DHCP_OPTION_NTP_SERVER
,
530 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
535 if (server
->timezone
) {
536 r
= dhcp_option_append(
537 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
538 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
539 strlen(server
->timezone
), server
->timezone
);
544 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
551 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
552 _cleanup_free_ DHCPPacket
*packet
= NULL
;
556 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
560 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
563 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
564 be32_t gateway
, uint8_t chaddr
[]) {
565 _cleanup_free_ DHCPPacket
*packet
= NULL
;
566 size_t optoffset
= 0;
570 assert(address
!= INADDR_ANY
);
573 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
577 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
578 DHCP_FORCERENEW
, ARPHRD_ETHER
,
579 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
583 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
584 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
588 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
590 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
592 sizeof(DHCPMessage
) + optoffset
);
599 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
600 DHCPRequest
*req
= userdata
;
605 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
607 req
->lifetime
= be32toh(*(be32_t
*)option
);
610 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
612 req
->requested_ip
= *(be32_t
*)option
;
615 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
617 req
->server_id
= *(be32_t
*)option
;
620 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
624 data
= memdup(option
, len
);
628 free(req
->client_id
.data
);
629 req
->client_id
.data
= data
;
630 req
->client_id
.length
= len
;
634 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
636 req
->max_optlen
= be16toh(*(be16_t
*)option
) -
637 - sizeof(DHCPPacket
);
645 static void dhcp_request_free(DHCPRequest
*req
) {
649 free(req
->client_id
.data
);
653 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
654 #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
656 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
660 req
->message
= message
;
662 /* set client id based on MAC address if client did not send an explicit
664 if (!req
->client_id
.data
) {
667 data
= malloc0(ETH_ALEN
+ 1);
671 ((uint8_t*) data
)[0] = 0x01;
672 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
674 req
->client_id
.length
= ETH_ALEN
+ 1;
675 req
->client_id
.data
= data
;
678 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
679 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
681 if (req
->lifetime
<= 0)
682 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
684 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
685 req
->lifetime
= server
->max_lease_time
;
690 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
693 if (!server
->pool_size
)
696 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
697 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
700 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
703 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
705 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
707 _cleanup_dhcp_request_free_ DHCPRequest
*req
= NULL
;
708 _cleanup_free_
char *error_message
= NULL
;
709 DHCPLease
*existing_lease
;
715 if (message
->op
!= BOOTREQUEST
||
716 message
->htype
!= ARPHRD_ETHER
||
717 message
->hlen
!= ETHER_ADDR_LEN
)
720 req
= new0(DHCPRequest
, 1);
724 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
728 r
= ensure_sane_request(server
, req
, message
);
730 /* this only fails on critical errors */
733 existing_lease
= hashmap_get(server
->leases_by_client_id
,
738 case DHCP_DISCOVER
: {
739 be32_t address
= INADDR_ANY
;
742 log_dhcp_server(server
, "DISCOVER (0x%x)",
743 be32toh(req
->message
->xid
));
745 if (!server
->pool_size
)
746 /* no pool allocated */
749 /* for now pick a random free address from the pool */
751 address
= existing_lease
->address
;
753 struct siphash state
;
757 /* even with no persistence of leases, we try to offer the same client
758 the same IP address. we do this by using the hash of the client id
759 as the offset into the pool of leases when finding the next free one */
761 siphash24_init(&state
, HASH_KEY
.bytes
);
762 client_id_hash_func(&req
->client_id
, &state
);
763 hash
= htole64(siphash24_finalize(&state
));
764 next_offer
= hash
% server
->pool_size
;
766 for (i
= 0; i
< server
->pool_size
; i
++) {
767 if (!server
->bound_leases
[next_offer
]) {
768 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
771 next_offer
= (next_offer
+ 1) % server
->pool_size
;
775 if (address
== INADDR_ANY
)
776 /* no free addresses left */
779 r
= server_send_offer(server
, req
, address
);
781 /* this only fails on critical errors */
782 log_dhcp_server(server
, "could not send offer: %s",
786 log_dhcp_server(server
, "OFFER (0x%x)",
787 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);
861 lease
->address
= req
->requested_ip
;
862 lease
->client_id
.data
= memdup(req
->client_id
.data
,
863 req
->client_id
.length
);
864 if (!lease
->client_id
.data
) {
868 lease
->client_id
.length
= req
->client_id
.length
;
869 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
871 lease
->gateway
= req
->message
->giaddr
;
873 lease
= existing_lease
;
875 r
= sd_event_now(server
->event
,
876 clock_boottime_or_monotonic(),
880 dhcp_lease_free(lease
);
884 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
886 r
= server_send_ack(server
, req
, address
);
888 /* this only fails on critical errors */
889 log_dhcp_server(server
, "could not send ack: %s",
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
);
906 } else if (init_reboot
) {
907 r
= server_send_nak(server
, req
);
909 /* this only fails on critical errors */
910 log_dhcp_server(server
, "could not send nak: %s",
914 log_dhcp_server(server
, "NAK (0x%x)",
915 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
);
953 static int server_receive_message(sd_event_source
*s
, int fd
,
954 uint32_t revents
, void *userdata
) {
955 _cleanup_free_ DHCPMessage
*message
= NULL
;
956 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
957 sd_dhcp_server
*server
= userdata
;
958 struct iovec iov
= {};
959 struct msghdr msg
= {
962 .msg_control
= cmsgbuf
,
963 .msg_controllen
= sizeof(cmsgbuf
),
965 struct cmsghdr
*cmsg
;
970 buflen
= next_datagram_size_fd(fd
);
974 message
= malloc(buflen
);
978 iov
.iov_base
= message
;
979 iov
.iov_len
= buflen
;
981 len
= recvmsg(fd
, &msg
, 0);
983 if (errno
== EAGAIN
|| errno
== EINTR
)
987 } else 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 return dhcp_server_handle_message(server
, message
, (size_t)len
);
1008 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1011 assert_return(server
, -EINVAL
);
1012 assert_return(server
->event
, -EINVAL
);
1013 assert_return(!server
->receive_message
, -EBUSY
);
1014 assert_return(server
->fd_raw
== -1, -EBUSY
);
1015 assert_return(server
->fd
== -1, -EBUSY
);
1016 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1018 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1021 sd_dhcp_server_stop(server
);
1026 r
= dhcp_network_bind_udp_socket(INADDR_ANY
, DHCP_PORT_SERVER
);
1028 sd_dhcp_server_stop(server
);
1033 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1034 server
->fd
, EPOLLIN
,
1035 server_receive_message
, server
);
1037 sd_dhcp_server_stop(server
);
1041 r
= sd_event_source_set_priority(server
->receive_message
,
1042 server
->event_priority
);
1044 sd_dhcp_server_stop(server
);
1048 log_dhcp_server(server
, "STARTED");
1053 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1057 assert_return(server
, -EINVAL
);
1058 assert(server
->bound_leases
);
1060 for (i
= 0; i
< server
->pool_size
; i
++) {
1061 DHCPLease
*lease
= server
->bound_leases
[i
];
1063 if (!lease
|| lease
== &server
->invalid_lease
)
1066 r
= server_send_forcerenew(server
, lease
->address
,
1072 log_dhcp_server(server
, "FORCERENEW");
1078 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1081 assert_return(server
, -EINVAL
);
1082 assert_return(timezone_is_valid(tz
), -EINVAL
);
1084 if (streq_ptr(tz
, server
->timezone
))
1087 r
= free_and_strdup(&server
->timezone
, tz
);
1094 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1095 assert_return(server
, -EINVAL
);
1097 if (t
== server
->max_lease_time
)
1100 server
->max_lease_time
= t
;
1104 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1105 assert_return(server
, -EINVAL
);
1107 if (t
== server
->default_lease_time
)
1110 server
->default_lease_time
= t
;
1114 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1115 assert_return(server
, -EINVAL
);
1116 assert_return(dns
|| n
<= 0, -EINVAL
);
1118 if (server
->n_dns
== n
&&
1119 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1123 server
->dns
= mfree(server
->dns
);
1128 c
= newdup(struct in_addr
, dns
, n
);
1140 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1141 assert_return(server
, -EINVAL
);
1142 assert_return(ntp
|| n
<= 0, -EINVAL
);
1144 if (server
->n_ntp
== n
&&
1145 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1149 server
->ntp
= mfree(server
->ntp
);
1154 c
= newdup(struct in_addr
, ntp
, 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
;