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
,
215 assert_return(server
, -EINVAL
);
216 assert_return(!server
->event
, -EBUSY
);
219 server
->event
= sd_event_ref(event
);
221 r
= sd_event_default(&server
->event
);
226 server
->event_priority
= priority
;
231 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
232 assert_return(server
, -EINVAL
);
234 server
->event
= sd_event_unref(server
->event
);
239 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
240 assert_return(server
, NULL
);
242 return server
->event
;
245 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
246 assert_return(server
, -EINVAL
);
248 server
->receive_message
=
249 sd_event_source_unref(server
->receive_message
);
251 server
->fd_raw
= safe_close(server
->fd_raw
);
252 server
->fd
= safe_close(server
->fd
);
254 log_dhcp_server(server
, "STOPPED");
259 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
260 DHCPPacket
*packet
, size_t len
) {
261 union sockaddr_union link
= {
262 .ll
.sll_family
= AF_PACKET
,
263 .ll
.sll_protocol
= htons(ETH_P_IP
),
264 .ll
.sll_ifindex
= server
->ifindex
,
265 .ll
.sll_halen
= ETH_ALEN
,
269 assert(server
->ifindex
> 0);
270 assert(server
->address
);
272 assert(len
> sizeof(DHCPPacket
));
274 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
276 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
278 DHCP_PORT_CLIENT
, len
);
280 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
283 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
284 DHCPMessage
*message
, size_t len
) {
285 union sockaddr_union dest
= {
286 .in
.sin_family
= AF_INET
,
287 .in
.sin_port
= htobe16(DHCP_PORT_CLIENT
),
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
;
350 assert(req
->max_optlen
);
351 assert(optoffset
<= req
->max_optlen
);
354 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
355 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
356 4, &server
->address
);
360 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
361 SD_DHCP_OPTION_END
, 0, NULL
);
365 /* RFC 2131 Section 4.1
367 If the ’giaddr’ field in a DHCP message from a client is non-zero,
368 the server sends any return messages to the ’DHCP server’ port on the
369 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
370 field is zero and the ’ciaddr’ field is nonzero, then the server
371 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
372 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
373 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
374 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
375 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
376 messages to the client’s hardware address and ’yiaddr’ address. In
377 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
378 messages to 0xffffffff.
382 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
383 different subnet. The server MUST set the broadcast bit in the
384 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
385 client, because the client may not have a correct network address
386 or subnet mask, and the client may not be answering ARP requests.
388 if (req
->message
->giaddr
) {
389 destination
= req
->message
->giaddr
;
390 if (type
== DHCP_NAK
)
391 packet
->dhcp
.flags
= htobe16(0x8000);
392 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
393 destination
= req
->message
->ciaddr
;
395 if (destination
!= INADDR_ANY
)
396 return dhcp_server_send_udp(server
, destination
, &packet
->dhcp
,
397 sizeof(DHCPMessage
) + optoffset
);
398 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
399 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
401 sizeof(DHCPMessage
) + optoffset
);
403 /* we cannot send UDP packet to specific MAC address when the
404 address is not yet configured, so must fall back to raw
406 return dhcp_server_send_unicast_raw(server
, packet
,
407 sizeof(DHCPPacket
) + optoffset
);
410 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
411 uint8_t type
, size_t *_optoffset
,
413 _cleanup_free_ DHCPPacket
*packet
= NULL
;
414 size_t optoffset
= 0;
420 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
422 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
426 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
427 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
428 req
->max_optlen
, &optoffset
);
432 packet
->dhcp
.flags
= req
->message
->flags
;
433 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
434 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
436 *_optoffset
= optoffset
;
443 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
445 _cleanup_free_ DHCPPacket
*packet
= NULL
;
450 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
454 packet
->dhcp
.yiaddr
= address
;
456 lease_time
= htobe32(req
->lifetime
);
457 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
458 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
463 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
464 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
468 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
469 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
473 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
480 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
482 _cleanup_free_ DHCPPacket
*packet
= NULL
;
487 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
491 packet
->dhcp
.yiaddr
= address
;
493 lease_time
= htobe32(req
->lifetime
);
494 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
495 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
500 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
501 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
505 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
506 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
, &packet
->dhcp
,
584 sizeof(DHCPMessage
) + optoffset
);
591 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
592 DHCPRequest
*req
= userdata
;
597 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
599 req
->lifetime
= be32toh(*(be32_t
*)option
);
602 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
604 req
->requested_ip
= *(be32_t
*)option
;
607 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
609 req
->server_id
= *(be32_t
*)option
;
612 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
616 data
= memdup(option
, len
);
620 free(req
->client_id
.data
);
621 req
->client_id
.data
= data
;
622 req
->client_id
.length
= len
;
626 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
628 req
->max_optlen
= be16toh(*(be16_t
*)option
) -
629 - sizeof(DHCPPacket
);
637 static void dhcp_request_free(DHCPRequest
*req
) {
641 free(req
->client_id
.data
);
645 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
646 #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
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_free_ 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
);
763 next_offer
= (next_offer
+ 1) % server
->pool_size
;
767 if (address
== INADDR_ANY
)
768 /* no free addresses left */
771 r
= server_send_offer(server
, req
, address
);
773 /* this only fails on critical errors */
774 log_dhcp_server(server
, "could not send offer: %s",
778 log_dhcp_server(server
, "OFFER (0x%x)",
779 be32toh(req
->message
->xid
));
786 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
788 /* TODO: make sure we don't offer this address again */
794 bool init_reboot
= false;
797 /* see RFC 2131, section 4.3.2 */
799 if (req
->server_id
) {
800 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
801 be32toh(req
->message
->xid
));
804 if (req
->server_id
!= server
->address
)
805 /* client did not pick us */
808 if (req
->message
->ciaddr
)
809 /* this MUST be zero */
812 if (!req
->requested_ip
)
813 /* this must be filled in with the yiaddr
814 from the chosen OFFER */
817 address
= req
->requested_ip
;
818 } else if (req
->requested_ip
) {
819 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
820 be32toh(req
->message
->xid
));
823 if (req
->message
->ciaddr
)
824 /* this MUST be zero */
827 /* TODO: check more carefully if IP is correct */
828 address
= req
->requested_ip
;
831 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
832 be32toh(req
->message
->xid
));
834 /* REBINDING / RENEWING */
835 if (!req
->message
->ciaddr
)
836 /* this MUST be filled in with clients IP address */
839 address
= req
->message
->ciaddr
;
842 pool_offset
= get_pool_offset(server
, address
);
844 /* verify that the requested address is from the pool, and either
845 owned by the current client or free */
846 if (pool_offset
>= 0 &&
847 server
->bound_leases
[pool_offset
] == existing_lease
) {
851 if (!existing_lease
) {
852 lease
= new0(DHCPLease
, 1);
853 lease
->address
= req
->requested_ip
;
854 lease
->client_id
.data
= memdup(req
->client_id
.data
,
855 req
->client_id
.length
);
856 if (!lease
->client_id
.data
) {
860 lease
->client_id
.length
= req
->client_id
.length
;
861 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
863 lease
->gateway
= req
->message
->giaddr
;
865 lease
= existing_lease
;
867 r
= sd_event_now(server
->event
,
868 clock_boottime_or_monotonic(),
872 dhcp_lease_free(lease
);
876 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
878 r
= server_send_ack(server
, req
, address
);
880 /* this only fails on critical errors */
881 log_dhcp_server(server
, "could not send ack: %s",
885 dhcp_lease_free(lease
);
889 log_dhcp_server(server
, "ACK (0x%x)",
890 be32toh(req
->message
->xid
));
892 server
->bound_leases
[pool_offset
] = lease
;
893 hashmap_put(server
->leases_by_client_id
,
894 &lease
->client_id
, lease
);
898 } else if (init_reboot
) {
899 r
= server_send_nak(server
, req
);
901 /* this only fails on critical errors */
902 log_dhcp_server(server
, "could not send nak: %s",
906 log_dhcp_server(server
, "NAK (0x%x)",
907 be32toh(req
->message
->xid
));
918 log_dhcp_server(server
, "RELEASE (0x%x)",
919 be32toh(req
->message
->xid
));
924 if (existing_lease
->address
!= req
->message
->ciaddr
)
927 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
931 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
932 server
->bound_leases
[pool_offset
] = NULL
;
933 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
934 dhcp_lease_free(existing_lease
);
945 static int server_receive_message(sd_event_source
*s
, int fd
,
946 uint32_t revents
, void *userdata
) {
947 _cleanup_free_ DHCPMessage
*message
= NULL
;
948 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
949 sd_dhcp_server
*server
= userdata
;
950 struct iovec iov
= {};
951 struct msghdr msg
= {
954 .msg_control
= cmsgbuf
,
955 .msg_controllen
= sizeof(cmsgbuf
),
957 struct cmsghdr
*cmsg
;
962 if (ioctl(fd
, FIONREAD
, &buflen
) < 0)
967 message
= malloc(buflen
);
971 iov
.iov_base
= message
;
972 iov
.iov_len
= buflen
;
974 len
= recvmsg(fd
, &msg
, 0);
976 if (errno
== EAGAIN
|| errno
== EINTR
)
980 } else if ((size_t)len
< sizeof(DHCPMessage
))
983 CMSG_FOREACH(cmsg
, &msg
) {
984 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
985 cmsg
->cmsg_type
== IP_PKTINFO
&&
986 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
987 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
989 /* TODO figure out if this can be done as a filter on
990 * the socket, like for IPv6 */
991 if (server
->ifindex
!= info
->ipi_ifindex
)
998 return dhcp_server_handle_message(server
, message
, (size_t)len
);
1001 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1004 assert_return(server
, -EINVAL
);
1005 assert_return(server
->event
, -EINVAL
);
1006 assert_return(!server
->receive_message
, -EBUSY
);
1007 assert_return(server
->fd_raw
== -1, -EBUSY
);
1008 assert_return(server
->fd
== -1, -EBUSY
);
1009 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1011 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1014 sd_dhcp_server_stop(server
);
1019 r
= dhcp_network_bind_udp_socket(INADDR_ANY
, DHCP_PORT_SERVER
);
1021 sd_dhcp_server_stop(server
);
1026 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1027 server
->fd
, EPOLLIN
,
1028 server_receive_message
, server
);
1030 sd_dhcp_server_stop(server
);
1034 r
= sd_event_source_set_priority(server
->receive_message
,
1035 server
->event_priority
);
1037 sd_dhcp_server_stop(server
);
1041 log_dhcp_server(server
, "STARTED");
1046 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1050 assert_return(server
, -EINVAL
);
1051 assert(server
->bound_leases
);
1053 for (i
= 0; i
< server
->pool_size
; i
++) {
1054 DHCPLease
*lease
= server
->bound_leases
[i
];
1056 if (!lease
|| lease
== &server
->invalid_lease
)
1059 r
= server_send_forcerenew(server
, lease
->address
,
1065 log_dhcp_server(server
, "FORCERENEW");
1071 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1074 assert_return(server
, -EINVAL
);
1075 assert_return(timezone_is_valid(tz
), -EINVAL
);
1077 if (streq_ptr(tz
, server
->timezone
))
1080 r
= free_and_strdup(&server
->timezone
, tz
);
1087 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1088 assert_return(server
, -EINVAL
);
1090 if (t
== server
->max_lease_time
)
1093 server
->max_lease_time
= t
;
1097 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1098 assert_return(server
, -EINVAL
);
1100 if (t
== server
->default_lease_time
)
1103 server
->default_lease_time
= t
;
1107 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1108 assert_return(server
, -EINVAL
);
1109 assert_return(dns
|| n
<= 0, -EINVAL
);
1111 if (server
->n_dns
== n
&&
1112 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1116 server
->dns
= mfree(server
->dns
);
1121 c
= newdup(struct in_addr
, dns
, n
);
1133 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1134 assert_return(server
, -EINVAL
);
1135 assert_return(ntp
|| n
<= 0, -EINVAL
);
1137 if (server
->n_ntp
== n
&&
1138 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1142 server
->ntp
= mfree(server
->ntp
);
1147 c
= newdup(struct in_addr
, ntp
, n
);