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 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
472 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
476 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
483 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
485 _cleanup_free_ DHCPPacket
*packet
= NULL
;
490 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
494 packet
->dhcp
.yiaddr
= address
;
496 lease_time
= htobe32(req
->lifetime
);
497 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
498 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
503 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
504 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
508 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
509 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
513 if (server
->n_dns
> 0) {
514 r
= dhcp_option_append(
515 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
516 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
517 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
522 if (server
->n_ntp
> 0) {
523 r
= dhcp_option_append(
524 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
525 SD_DHCP_OPTION_NTP_SERVER
,
526 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
531 if (server
->timezone
) {
532 r
= dhcp_option_append(
533 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
534 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
535 strlen(server
->timezone
), server
->timezone
);
540 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
547 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
548 _cleanup_free_ DHCPPacket
*packet
= NULL
;
552 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
556 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
559 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
560 be32_t gateway
, uint8_t chaddr
[]) {
561 _cleanup_free_ DHCPPacket
*packet
= NULL
;
562 size_t optoffset
= 0;
566 assert(address
!= INADDR_ANY
);
569 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
573 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
574 DHCP_FORCERENEW
, ARPHRD_ETHER
,
575 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
579 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
580 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
584 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
586 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
588 sizeof(DHCPMessage
) + optoffset
);
595 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
596 DHCPRequest
*req
= userdata
;
601 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
603 req
->lifetime
= be32toh(*(be32_t
*)option
);
606 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
608 req
->requested_ip
= *(be32_t
*)option
;
611 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
613 req
->server_id
= *(be32_t
*)option
;
616 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
620 data
= memdup(option
, len
);
624 free(req
->client_id
.data
);
625 req
->client_id
.data
= data
;
626 req
->client_id
.length
= len
;
630 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
632 req
->max_optlen
= be16toh(*(be16_t
*)option
) -
633 - sizeof(DHCPPacket
);
641 static void dhcp_request_free(DHCPRequest
*req
) {
645 free(req
->client_id
.data
);
649 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
650 #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
652 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
656 req
->message
= message
;
658 /* set client id based on MAC address if client did not send an explicit
660 if (!req
->client_id
.data
) {
663 data
= malloc0(ETH_ALEN
+ 1);
667 ((uint8_t*) data
)[0] = 0x01;
668 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
670 req
->client_id
.length
= ETH_ALEN
+ 1;
671 req
->client_id
.data
= data
;
674 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
675 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
677 if (req
->lifetime
<= 0)
678 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
680 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
681 req
->lifetime
= server
->max_lease_time
;
686 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
689 if (!server
->pool_size
)
692 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
693 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
696 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
699 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
701 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
703 _cleanup_dhcp_request_free_ DHCPRequest
*req
= NULL
;
704 _cleanup_free_
char *error_message
= NULL
;
705 DHCPLease
*existing_lease
;
711 if (message
->op
!= BOOTREQUEST
||
712 message
->htype
!= ARPHRD_ETHER
||
713 message
->hlen
!= ETHER_ADDR_LEN
)
716 req
= new0(DHCPRequest
, 1);
720 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
724 r
= ensure_sane_request(server
, req
, message
);
726 /* this only fails on critical errors */
729 existing_lease
= hashmap_get(server
->leases_by_client_id
,
734 case DHCP_DISCOVER
: {
735 be32_t address
= INADDR_ANY
;
738 log_dhcp_server(server
, "DISCOVER (0x%x)",
739 be32toh(req
->message
->xid
));
741 if (!server
->pool_size
)
742 /* no pool allocated */
745 /* for now pick a random free address from the pool */
747 address
= existing_lease
->address
;
749 struct siphash state
;
753 /* even with no persistence of leases, we try to offer the same client
754 the same IP address. we do this by using the hash of the client id
755 as the offset into the pool of leases when finding the next free one */
757 siphash24_init(&state
, HASH_KEY
.bytes
);
758 client_id_hash_func(&req
->client_id
, &state
);
759 hash
= htole64(siphash24_finalize(&state
));
760 next_offer
= hash
% server
->pool_size
;
762 for (i
= 0; i
< server
->pool_size
; i
++) {
763 if (!server
->bound_leases
[next_offer
]) {
764 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
767 next_offer
= (next_offer
+ 1) % server
->pool_size
;
771 if (address
== INADDR_ANY
)
772 /* no free addresses left */
775 r
= server_send_offer(server
, req
, address
);
777 /* this only fails on critical errors */
778 log_dhcp_server(server
, "could not send offer: %s",
782 log_dhcp_server(server
, "OFFER (0x%x)",
783 be32toh(req
->message
->xid
));
790 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
792 /* TODO: make sure we don't offer this address again */
798 bool init_reboot
= false;
801 /* see RFC 2131, section 4.3.2 */
803 if (req
->server_id
) {
804 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
805 be32toh(req
->message
->xid
));
808 if (req
->server_id
!= server
->address
)
809 /* client did not pick us */
812 if (req
->message
->ciaddr
)
813 /* this MUST be zero */
816 if (!req
->requested_ip
)
817 /* this must be filled in with the yiaddr
818 from the chosen OFFER */
821 address
= req
->requested_ip
;
822 } else if (req
->requested_ip
) {
823 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
824 be32toh(req
->message
->xid
));
827 if (req
->message
->ciaddr
)
828 /* this MUST be zero */
831 /* TODO: check more carefully if IP is correct */
832 address
= req
->requested_ip
;
835 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
836 be32toh(req
->message
->xid
));
838 /* REBINDING / RENEWING */
839 if (!req
->message
->ciaddr
)
840 /* this MUST be filled in with clients IP address */
843 address
= req
->message
->ciaddr
;
846 pool_offset
= get_pool_offset(server
, address
);
848 /* verify that the requested address is from the pool, and either
849 owned by the current client or free */
850 if (pool_offset
>= 0 &&
851 server
->bound_leases
[pool_offset
] == existing_lease
) {
855 if (!existing_lease
) {
856 lease
= new0(DHCPLease
, 1);
857 lease
->address
= req
->requested_ip
;
858 lease
->client_id
.data
= memdup(req
->client_id
.data
,
859 req
->client_id
.length
);
860 if (!lease
->client_id
.data
) {
864 lease
->client_id
.length
= req
->client_id
.length
;
865 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
867 lease
->gateway
= req
->message
->giaddr
;
869 lease
= existing_lease
;
871 r
= sd_event_now(server
->event
,
872 clock_boottime_or_monotonic(),
876 dhcp_lease_free(lease
);
880 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
882 r
= server_send_ack(server
, req
, address
);
884 /* this only fails on critical errors */
885 log_dhcp_server(server
, "could not send ack: %s",
889 dhcp_lease_free(lease
);
893 log_dhcp_server(server
, "ACK (0x%x)",
894 be32toh(req
->message
->xid
));
896 server
->bound_leases
[pool_offset
] = lease
;
897 hashmap_put(server
->leases_by_client_id
,
898 &lease
->client_id
, lease
);
902 } else if (init_reboot
) {
903 r
= server_send_nak(server
, req
);
905 /* this only fails on critical errors */
906 log_dhcp_server(server
, "could not send nak: %s",
910 log_dhcp_server(server
, "NAK (0x%x)",
911 be32toh(req
->message
->xid
));
922 log_dhcp_server(server
, "RELEASE (0x%x)",
923 be32toh(req
->message
->xid
));
928 if (existing_lease
->address
!= req
->message
->ciaddr
)
931 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
935 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
936 server
->bound_leases
[pool_offset
] = NULL
;
937 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
938 dhcp_lease_free(existing_lease
);
949 static int server_receive_message(sd_event_source
*s
, int fd
,
950 uint32_t revents
, void *userdata
) {
951 _cleanup_free_ DHCPMessage
*message
= NULL
;
952 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
953 sd_dhcp_server
*server
= userdata
;
954 struct iovec iov
= {};
955 struct msghdr msg
= {
958 .msg_control
= cmsgbuf
,
959 .msg_controllen
= sizeof(cmsgbuf
),
961 struct cmsghdr
*cmsg
;
966 buflen
= next_datagram_size_fd(fd
);
970 message
= malloc(buflen
);
974 iov
.iov_base
= message
;
975 iov
.iov_len
= buflen
;
977 len
= recvmsg(fd
, &msg
, 0);
979 if (errno
== EAGAIN
|| errno
== EINTR
)
983 } else if ((size_t)len
< sizeof(DHCPMessage
))
986 CMSG_FOREACH(cmsg
, &msg
) {
987 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
988 cmsg
->cmsg_type
== IP_PKTINFO
&&
989 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
990 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
992 /* TODO figure out if this can be done as a filter on
993 * the socket, like for IPv6 */
994 if (server
->ifindex
!= info
->ipi_ifindex
)
1001 return dhcp_server_handle_message(server
, message
, (size_t)len
);
1004 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1007 assert_return(server
, -EINVAL
);
1008 assert_return(server
->event
, -EINVAL
);
1009 assert_return(!server
->receive_message
, -EBUSY
);
1010 assert_return(server
->fd_raw
== -1, -EBUSY
);
1011 assert_return(server
->fd
== -1, -EBUSY
);
1012 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1014 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1017 sd_dhcp_server_stop(server
);
1022 r
= dhcp_network_bind_udp_socket(INADDR_ANY
, DHCP_PORT_SERVER
);
1024 sd_dhcp_server_stop(server
);
1029 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1030 server
->fd
, EPOLLIN
,
1031 server_receive_message
, server
);
1033 sd_dhcp_server_stop(server
);
1037 r
= sd_event_source_set_priority(server
->receive_message
,
1038 server
->event_priority
);
1040 sd_dhcp_server_stop(server
);
1044 log_dhcp_server(server
, "STARTED");
1049 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1053 assert_return(server
, -EINVAL
);
1054 assert(server
->bound_leases
);
1056 for (i
= 0; i
< server
->pool_size
; i
++) {
1057 DHCPLease
*lease
= server
->bound_leases
[i
];
1059 if (!lease
|| lease
== &server
->invalid_lease
)
1062 r
= server_send_forcerenew(server
, lease
->address
,
1068 log_dhcp_server(server
, "FORCERENEW");
1074 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1077 assert_return(server
, -EINVAL
);
1078 assert_return(timezone_is_valid(tz
), -EINVAL
);
1080 if (streq_ptr(tz
, server
->timezone
))
1083 r
= free_and_strdup(&server
->timezone
, tz
);
1090 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1091 assert_return(server
, -EINVAL
);
1093 if (t
== server
->max_lease_time
)
1096 server
->max_lease_time
= t
;
1100 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1101 assert_return(server
, -EINVAL
);
1103 if (t
== server
->default_lease_time
)
1106 server
->default_lease_time
= t
;
1110 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1111 assert_return(server
, -EINVAL
);
1112 assert_return(dns
|| n
<= 0, -EINVAL
);
1114 if (server
->n_dns
== n
&&
1115 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1119 server
->dns
= mfree(server
->dns
);
1124 c
= newdup(struct in_addr
, dns
, n
);
1136 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1137 assert_return(server
, -EINVAL
);
1138 assert_return(ntp
|| n
<= 0, -EINVAL
);
1140 if (server
->n_ntp
== n
&&
1141 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1145 server
->ntp
= mfree(server
->ntp
);
1150 c
= newdup(struct in_addr
, ntp
, n
);