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"
32 #include "unaligned.h"
34 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
35 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
37 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
38 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
39 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
40 * accidentally hand it out */
41 int sd_dhcp_server_configure_pool(sd_dhcp_server
*server
, struct in_addr
*address
, unsigned char prefixlen
, uint32_t offset
, uint32_t size
) {
42 struct in_addr netmask_addr
;
44 uint32_t server_off
, broadcast_off
, size_max
;
46 assert_return(server
, -EINVAL
);
47 assert_return(address
, -EINVAL
);
48 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
49 assert_return(prefixlen
<= 32, -ERANGE
);
50 assert_return(server
->address
== INADDR_ANY
, -EBUSY
);
52 assert_se(in_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
53 netmask
= netmask_addr
.s_addr
;
55 server_off
= be32toh(address
->s_addr
& ~netmask
);
56 broadcast_off
= be32toh(~netmask
);
58 /* the server address cannot be the subnet address */
59 assert_return(server_off
!= 0, -ERANGE
);
61 /* nor the broadcast address */
62 assert_return(server_off
!= broadcast_off
, -ERANGE
);
64 /* 0 offset means we should set a default, we skip the first (subnet) address
65 and take the next one */
69 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
70 - offset
/* exclude the addresses before the offset */
71 - 1; /* exclude the last (broadcast) address */
73 /* The pool must contain at least one address */
74 assert_return(size_max
>= 1, -ERANGE
);
77 assert_return(size
<= size_max
, -ERANGE
);
81 server
->bound_leases
= new0(DHCPLease
*, size
);
82 if (!server
->bound_leases
)
85 server
->pool_offset
= offset
;
86 server
->pool_size
= size
;
88 server
->address
= address
->s_addr
;
89 server
->netmask
= netmask
;
90 server
->subnet
= address
->s_addr
& netmask
;
92 if (server_off
>= offset
&& server_off
- offset
< size
)
93 server
->bound_leases
[server_off
- offset
] = &server
->invalid_lease
;
98 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
99 assert_return(server
, false);
101 return !!server
->receive_message
;
104 sd_dhcp_server
*sd_dhcp_server_ref(sd_dhcp_server
*server
) {
109 assert(server
->n_ref
>= 1);
115 void client_id_hash_func(const void *p
, struct siphash
*state
) {
116 const DHCPClientId
*id
= p
;
122 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
123 siphash24_compress(id
->data
, id
->length
, state
);
126 int client_id_compare_func(const void *_a
, const void *_b
) {
127 const DHCPClientId
*a
, *b
;
132 assert(!a
->length
|| a
->data
);
133 assert(!b
->length
|| b
->data
);
135 if (a
->length
!= b
->length
)
136 return a
->length
< b
->length
? -1 : 1;
138 return memcmp(a
->data
, b
->data
, a
->length
);
141 static const struct hash_ops client_id_hash_ops
= {
142 .hash
= client_id_hash_func
,
143 .compare
= client_id_compare_func
146 static void dhcp_lease_free(DHCPLease
*lease
) {
150 free(lease
->client_id
.data
);
154 sd_dhcp_server
*sd_dhcp_server_unref(sd_dhcp_server
*server
) {
160 assert(server
->n_ref
>= 1);
163 if (server
->n_ref
> 0)
166 log_dhcp_server(server
, "UNREF");
168 sd_dhcp_server_stop(server
);
170 sd_event_unref(server
->event
);
172 free(server
->timezone
);
176 while ((lease
= hashmap_steal_first(server
->leases_by_client_id
)))
177 dhcp_lease_free(lease
);
178 hashmap_free(server
->leases_by_client_id
);
180 free(server
->bound_leases
);
181 return mfree(server
);
184 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
185 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
187 assert_return(ret
, -EINVAL
);
188 assert_return(ifindex
> 0, -EINVAL
);
190 server
= new0(sd_dhcp_server
, 1);
197 server
->address
= htobe32(INADDR_ANY
);
198 server
->netmask
= htobe32(INADDR_ANY
);
199 server
->ifindex
= ifindex
;
201 server
->leases_by_client_id
= hashmap_new(&client_id_hash_ops
);
202 if (!server
->leases_by_client_id
)
205 server
->default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
);
206 server
->max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
);
214 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
217 assert_return(server
, -EINVAL
);
218 assert_return(!server
->event
, -EBUSY
);
221 server
->event
= sd_event_ref(event
);
223 r
= sd_event_default(&server
->event
);
228 server
->event_priority
= priority
;
233 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
234 assert_return(server
, -EINVAL
);
236 server
->event
= sd_event_unref(server
->event
);
241 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
242 assert_return(server
, NULL
);
244 return server
->event
;
247 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
248 assert_return(server
, -EINVAL
);
250 server
->receive_message
=
251 sd_event_source_unref(server
->receive_message
);
253 server
->fd_raw
= safe_close(server
->fd_raw
);
254 server
->fd
= safe_close(server
->fd
);
256 log_dhcp_server(server
, "STOPPED");
261 static int dhcp_server_send_unicast_raw(sd_dhcp_server
*server
,
262 DHCPPacket
*packet
, size_t len
) {
263 union sockaddr_union link
= {
264 .ll
.sll_family
= AF_PACKET
,
265 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
266 .ll
.sll_ifindex
= server
->ifindex
,
267 .ll
.sll_halen
= ETH_ALEN
,
271 assert(server
->ifindex
> 0);
272 assert(server
->address
);
274 assert(len
> sizeof(DHCPPacket
));
276 memcpy(&link
.ll
.sll_addr
, &packet
->dhcp
.chaddr
, ETH_ALEN
);
278 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
280 DHCP_PORT_CLIENT
, len
);
282 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
285 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
286 uint16_t destination_port
,
287 DHCPMessage
*message
, size_t len
) {
288 union sockaddr_union dest
= {
289 .in
.sin_family
= AF_INET
,
290 .in
.sin_port
= htobe16(destination_port
),
291 .in
.sin_addr
.s_addr
= destination
,
297 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))] = {};
298 struct msghdr msg
= {
300 .msg_namelen
= sizeof(dest
.in
),
303 .msg_control
= cmsgbuf
,
304 .msg_controllen
= sizeof(cmsgbuf
),
306 struct cmsghdr
*cmsg
;
307 struct in_pktinfo
*pktinfo
;
311 assert(server
->fd
> 0);
313 assert(len
> sizeof(DHCPMessage
));
315 cmsg
= CMSG_FIRSTHDR(&msg
);
318 cmsg
->cmsg_level
= IPPROTO_IP
;
319 cmsg
->cmsg_type
= IP_PKTINFO
;
320 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
322 /* we attach source interface and address info to the message
323 rather than binding the socket. This will be mostly useful
324 when we gain support for arbitrary number of server addresses
326 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
329 pktinfo
->ipi_ifindex
= server
->ifindex
;
330 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
332 r
= sendmsg(server
->fd
, &msg
, 0);
339 static bool requested_broadcast(DHCPRequest
*req
) {
342 return req
->message
->flags
& htobe16(0x8000);
345 int dhcp_server_send_packet(sd_dhcp_server
*server
,
346 DHCPRequest
*req
, DHCPPacket
*packet
,
347 int type
, size_t optoffset
) {
348 be32_t destination
= INADDR_ANY
;
349 uint16_t destination_port
= DHCP_PORT_CLIENT
;
354 assert(req
->max_optlen
);
355 assert(optoffset
<= req
->max_optlen
);
358 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
359 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
360 4, &server
->address
);
364 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
365 SD_DHCP_OPTION_END
, 0, NULL
);
369 /* RFC 2131 Section 4.1
371 If the ’giaddr’ field in a DHCP message from a client is non-zero,
372 the server sends any return messages to the ’DHCP server’ port on the
373 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
374 field is zero and the ’ciaddr’ field is nonzero, then the server
375 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
376 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
377 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
378 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
379 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
380 messages to the client’s hardware address and ’yiaddr’ address. In
381 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
382 messages to 0xffffffff.
386 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
387 different subnet. The server MUST set the broadcast bit in the
388 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
389 client, because the client may not have a correct network address
390 or subnet mask, and the client may not be answering ARP requests.
392 if (req
->message
->giaddr
) {
393 destination
= req
->message
->giaddr
;
394 destination_port
= DHCP_PORT_SERVER
;
395 if (type
== DHCP_NAK
)
396 packet
->dhcp
.flags
= htobe16(0x8000);
397 } else if (req
->message
->ciaddr
&& type
!= DHCP_NAK
)
398 destination
= req
->message
->ciaddr
;
400 if (destination
!= INADDR_ANY
)
401 return dhcp_server_send_udp(server
, destination
,
402 destination_port
, &packet
->dhcp
,
403 sizeof(DHCPMessage
) + optoffset
);
404 else if (requested_broadcast(req
) || type
== DHCP_NAK
)
405 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
406 destination_port
, &packet
->dhcp
,
407 sizeof(DHCPMessage
) + optoffset
);
409 /* we cannot send UDP packet to specific MAC address when the
410 address is not yet configured, so must fall back to raw
412 return dhcp_server_send_unicast_raw(server
, packet
,
413 sizeof(DHCPPacket
) + optoffset
);
416 static int server_message_init(sd_dhcp_server
*server
, DHCPPacket
**ret
,
417 uint8_t type
, size_t *_optoffset
,
419 _cleanup_free_ DHCPPacket
*packet
= NULL
;
420 size_t optoffset
= 0;
426 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
428 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
432 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
433 be32toh(req
->message
->xid
), type
, ARPHRD_ETHER
,
434 req
->max_optlen
, &optoffset
);
438 packet
->dhcp
.flags
= req
->message
->flags
;
439 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
440 memcpy(&packet
->dhcp
.chaddr
, &req
->message
->chaddr
, ETH_ALEN
);
442 *_optoffset
= optoffset
;
449 static int server_send_offer(sd_dhcp_server
*server
, DHCPRequest
*req
,
451 _cleanup_free_ DHCPPacket
*packet
= NULL
;
456 r
= server_message_init(server
, &packet
, DHCP_OFFER
, &offset
, req
);
460 packet
->dhcp
.yiaddr
= address
;
462 lease_time
= htobe32(req
->lifetime
);
463 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
464 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
469 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
470 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
474 if (server
->emit_router
) {
475 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
476 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
481 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_OFFER
, offset
);
488 static int server_send_ack(sd_dhcp_server
*server
, DHCPRequest
*req
,
490 _cleanup_free_ DHCPPacket
*packet
= NULL
;
495 r
= server_message_init(server
, &packet
, DHCP_ACK
, &offset
, req
);
499 packet
->dhcp
.yiaddr
= address
;
501 lease_time
= htobe32(req
->lifetime
);
502 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
503 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
508 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
509 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
513 if (server
->emit_router
) {
514 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
515 SD_DHCP_OPTION_ROUTER
, 4, &server
->address
);
520 if (server
->n_dns
> 0) {
521 r
= dhcp_option_append(
522 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
523 SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
524 sizeof(struct in_addr
) * server
->n_dns
, server
->dns
);
529 if (server
->n_ntp
> 0) {
530 r
= dhcp_option_append(
531 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
532 SD_DHCP_OPTION_NTP_SERVER
,
533 sizeof(struct in_addr
) * server
->n_ntp
, server
->ntp
);
538 if (server
->timezone
) {
539 r
= dhcp_option_append(
540 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
541 SD_DHCP_OPTION_NEW_TZDB_TIMEZONE
,
542 strlen(server
->timezone
), server
->timezone
);
547 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_ACK
, offset
);
554 static int server_send_nak(sd_dhcp_server
*server
, DHCPRequest
*req
) {
555 _cleanup_free_ DHCPPacket
*packet
= NULL
;
559 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
563 return dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
566 static int server_send_forcerenew(sd_dhcp_server
*server
, be32_t address
,
567 be32_t gateway
, uint8_t chaddr
[]) {
568 _cleanup_free_ DHCPPacket
*packet
= NULL
;
569 size_t optoffset
= 0;
573 assert(address
!= INADDR_ANY
);
576 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
580 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
581 DHCP_FORCERENEW
, ARPHRD_ETHER
,
582 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
586 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
587 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
591 memcpy(&packet
->dhcp
.chaddr
, chaddr
, ETH_ALEN
);
593 r
= dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
595 sizeof(DHCPMessage
) + optoffset
);
602 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
603 DHCPRequest
*req
= userdata
;
608 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
610 req
->lifetime
= unaligned_read_be32(option
);
613 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
615 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
618 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
620 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
623 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
627 data
= memdup(option
, len
);
631 free(req
->client_id
.data
);
632 req
->client_id
.data
= data
;
633 req
->client_id
.length
= len
;
637 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
639 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
640 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
648 static void dhcp_request_free(DHCPRequest
*req
) {
652 free(req
->client_id
.data
);
656 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
657 #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
659 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
663 req
->message
= message
;
665 /* set client id based on MAC address if client did not send an explicit
667 if (!req
->client_id
.data
) {
670 data
= malloc0(ETH_ALEN
+ 1);
674 ((uint8_t*) data
)[0] = 0x01;
675 memcpy((uint8_t*) data
+ 1, &message
->chaddr
, ETH_ALEN
);
677 req
->client_id
.length
= ETH_ALEN
+ 1;
678 req
->client_id
.data
= data
;
681 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
682 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
684 if (req
->lifetime
<= 0)
685 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
687 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
688 req
->lifetime
= server
->max_lease_time
;
693 static int get_pool_offset(sd_dhcp_server
*server
, be32_t requested_ip
) {
696 if (!server
->pool_size
)
699 if (be32toh(requested_ip
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
700 be32toh(requested_ip
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
703 return be32toh(requested_ip
& ~server
->netmask
) - server
->pool_offset
;
706 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
708 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
,
710 _cleanup_dhcp_request_free_ DHCPRequest
*req
= NULL
;
711 _cleanup_free_
char *error_message
= NULL
;
712 DHCPLease
*existing_lease
;
718 if (message
->op
!= BOOTREQUEST
||
719 message
->htype
!= ARPHRD_ETHER
||
720 message
->hlen
!= ETHER_ADDR_LEN
)
723 req
= new0(DHCPRequest
, 1);
727 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
731 r
= ensure_sane_request(server
, req
, message
);
733 /* this only fails on critical errors */
736 existing_lease
= hashmap_get(server
->leases_by_client_id
,
741 case DHCP_DISCOVER
: {
742 be32_t address
= INADDR_ANY
;
745 log_dhcp_server(server
, "DISCOVER (0x%x)",
746 be32toh(req
->message
->xid
));
748 if (!server
->pool_size
)
749 /* no pool allocated */
752 /* for now pick a random free address from the pool */
754 address
= existing_lease
->address
;
756 struct siphash state
;
760 /* even with no persistence of leases, we try to offer the same client
761 the same IP address. we do this by using the hash of the client id
762 as the offset into the pool of leases when finding the next free one */
764 siphash24_init(&state
, HASH_KEY
.bytes
);
765 client_id_hash_func(&req
->client_id
, &state
);
766 hash
= htole64(siphash24_finalize(&state
));
767 next_offer
= hash
% server
->pool_size
;
769 for (i
= 0; i
< server
->pool_size
; i
++) {
770 if (!server
->bound_leases
[next_offer
]) {
771 address
= server
->subnet
| htobe32(server
->pool_offset
+ next_offer
);
774 next_offer
= (next_offer
+ 1) % server
->pool_size
;
778 if (address
== INADDR_ANY
)
779 /* no free addresses left */
782 r
= server_send_offer(server
, req
, address
);
784 /* this only fails on critical errors */
785 log_dhcp_server(server
, "could not send offer: %s",
789 log_dhcp_server(server
, "OFFER (0x%x)",
790 be32toh(req
->message
->xid
));
797 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
799 /* TODO: make sure we don't offer this address again */
805 bool init_reboot
= false;
808 /* see RFC 2131, section 4.3.2 */
810 if (req
->server_id
) {
811 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
812 be32toh(req
->message
->xid
));
815 if (req
->server_id
!= server
->address
)
816 /* client did not pick us */
819 if (req
->message
->ciaddr
)
820 /* this MUST be zero */
823 if (!req
->requested_ip
)
824 /* this must be filled in with the yiaddr
825 from the chosen OFFER */
828 address
= req
->requested_ip
;
829 } else if (req
->requested_ip
) {
830 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
831 be32toh(req
->message
->xid
));
834 if (req
->message
->ciaddr
)
835 /* this MUST be zero */
838 /* TODO: check more carefully if IP is correct */
839 address
= req
->requested_ip
;
842 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
843 be32toh(req
->message
->xid
));
845 /* REBINDING / RENEWING */
846 if (!req
->message
->ciaddr
)
847 /* this MUST be filled in with clients IP address */
850 address
= req
->message
->ciaddr
;
853 pool_offset
= get_pool_offset(server
, address
);
855 /* verify that the requested address is from the pool, and either
856 owned by the current client or free */
857 if (pool_offset
>= 0 &&
858 server
->bound_leases
[pool_offset
] == existing_lease
) {
862 if (!existing_lease
) {
863 lease
= new0(DHCPLease
, 1);
866 lease
->address
= address
;
867 lease
->client_id
.data
= memdup(req
->client_id
.data
,
868 req
->client_id
.length
);
869 if (!lease
->client_id
.data
) {
873 lease
->client_id
.length
= req
->client_id
.length
;
874 memcpy(&lease
->chaddr
, &req
->message
->chaddr
,
876 lease
->gateway
= req
->message
->giaddr
;
878 lease
= existing_lease
;
880 r
= sd_event_now(server
->event
,
881 clock_boottime_or_monotonic(),
885 dhcp_lease_free(lease
);
889 lease
->expiration
= req
->lifetime
* USEC_PER_SEC
+ time_now
;
891 r
= server_send_ack(server
, req
, address
);
893 /* this only fails on critical errors */
894 log_dhcp_server(server
, "could not send ack: %s",
898 dhcp_lease_free(lease
);
902 log_dhcp_server(server
, "ACK (0x%x)",
903 be32toh(req
->message
->xid
));
905 server
->bound_leases
[pool_offset
] = lease
;
906 hashmap_put(server
->leases_by_client_id
,
907 &lease
->client_id
, lease
);
911 } else if (init_reboot
) {
912 r
= server_send_nak(server
, req
);
914 /* this only fails on critical errors */
915 log_dhcp_server(server
, "could not send nak: %s",
919 log_dhcp_server(server
, "NAK (0x%x)",
920 be32toh(req
->message
->xid
));
931 log_dhcp_server(server
, "RELEASE (0x%x)",
932 be32toh(req
->message
->xid
));
937 if (existing_lease
->address
!= req
->message
->ciaddr
)
940 pool_offset
= get_pool_offset(server
, req
->message
->ciaddr
);
944 if (server
->bound_leases
[pool_offset
] == existing_lease
) {
945 server
->bound_leases
[pool_offset
] = NULL
;
946 hashmap_remove(server
->leases_by_client_id
, existing_lease
);
947 dhcp_lease_free(existing_lease
);
958 static int server_receive_message(sd_event_source
*s
, int fd
,
959 uint32_t revents
, void *userdata
) {
960 _cleanup_free_ DHCPMessage
*message
= NULL
;
961 uint8_t cmsgbuf
[CMSG_LEN(sizeof(struct in_pktinfo
))];
962 sd_dhcp_server
*server
= userdata
;
963 struct iovec iov
= {};
964 struct msghdr msg
= {
967 .msg_control
= cmsgbuf
,
968 .msg_controllen
= sizeof(cmsgbuf
),
970 struct cmsghdr
*cmsg
;
975 buflen
= next_datagram_size_fd(fd
);
979 message
= malloc(buflen
);
983 iov
.iov_base
= message
;
984 iov
.iov_len
= buflen
;
986 len
= recvmsg(fd
, &msg
, 0);
988 if (errno
== EAGAIN
|| errno
== EINTR
)
992 } else if ((size_t)len
< sizeof(DHCPMessage
))
995 CMSG_FOREACH(cmsg
, &msg
) {
996 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
997 cmsg
->cmsg_type
== IP_PKTINFO
&&
998 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
999 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
1001 /* TODO figure out if this can be done as a filter on
1002 * the socket, like for IPv6 */
1003 if (server
->ifindex
!= info
->ipi_ifindex
)
1010 return dhcp_server_handle_message(server
, message
, (size_t)len
);
1013 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1016 assert_return(server
, -EINVAL
);
1017 assert_return(server
->event
, -EINVAL
);
1018 assert_return(!server
->receive_message
, -EBUSY
);
1019 assert_return(server
->fd_raw
== -1, -EBUSY
);
1020 assert_return(server
->fd
== -1, -EBUSY
);
1021 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1023 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_NONBLOCK
, 0);
1026 sd_dhcp_server_stop(server
);
1031 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
);
1033 sd_dhcp_server_stop(server
);
1038 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1039 server
->fd
, EPOLLIN
,
1040 server_receive_message
, server
);
1042 sd_dhcp_server_stop(server
);
1046 r
= sd_event_source_set_priority(server
->receive_message
,
1047 server
->event_priority
);
1049 sd_dhcp_server_stop(server
);
1053 log_dhcp_server(server
, "STARTED");
1058 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1062 assert_return(server
, -EINVAL
);
1063 assert(server
->bound_leases
);
1065 for (i
= 0; i
< server
->pool_size
; i
++) {
1066 DHCPLease
*lease
= server
->bound_leases
[i
];
1068 if (!lease
|| lease
== &server
->invalid_lease
)
1071 r
= server_send_forcerenew(server
, lease
->address
,
1077 log_dhcp_server(server
, "FORCERENEW");
1083 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1086 assert_return(server
, -EINVAL
);
1087 assert_return(timezone_is_valid(tz
), -EINVAL
);
1089 if (streq_ptr(tz
, server
->timezone
))
1092 r
= free_and_strdup(&server
->timezone
, tz
);
1099 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1100 assert_return(server
, -EINVAL
);
1102 if (t
== server
->max_lease_time
)
1105 server
->max_lease_time
= t
;
1109 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1110 assert_return(server
, -EINVAL
);
1112 if (t
== server
->default_lease_time
)
1115 server
->default_lease_time
= t
;
1119 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], unsigned n
) {
1120 assert_return(server
, -EINVAL
);
1121 assert_return(dns
|| n
<= 0, -EINVAL
);
1123 if (server
->n_dns
== n
&&
1124 memcmp(server
->dns
, dns
, sizeof(struct in_addr
) * n
) == 0)
1128 server
->dns
= mfree(server
->dns
);
1133 c
= newdup(struct in_addr
, dns
, n
);
1145 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], unsigned n
) {
1146 assert_return(server
, -EINVAL
);
1147 assert_return(ntp
|| n
<= 0, -EINVAL
);
1149 if (server
->n_ntp
== n
&&
1150 memcmp(server
->ntp
, ntp
, sizeof(struct in_addr
) * n
) == 0)
1154 server
->ntp
= mfree(server
->ntp
);
1159 c
= newdup(struct in_addr
, ntp
, n
);
1171 int sd_dhcp_server_set_emit_router(sd_dhcp_server
*server
, int enabled
) {
1172 assert_return(server
, -EINVAL
);
1174 if (enabled
== server
->emit_router
)
1177 server
->emit_router
= enabled
;