1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2013 Intel Corporation. All rights reserved.
6 #include <net/if_arp.h>
9 #include "sd-dhcp-server.h"
12 #include "alloc-util.h"
13 #include "dhcp-internal.h"
14 #include "dhcp-server-internal.h"
15 #include "dns-domain.h"
17 #include "in-addr-util.h"
19 #include "memory-util.h"
20 #include "network-common.h"
21 #include "ordered-set.h"
22 #include "siphash24.h"
23 #include "string-util.h"
24 #include "unaligned.h"
27 #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
28 #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
30 static DHCPLease
*dhcp_lease_free(DHCPLease
*lease
) {
35 hashmap_remove_value(lease
->server
->bound_leases_by_address
, UINT32_TO_PTR(lease
->address
), lease
);
36 hashmap_remove_value(lease
->server
->bound_leases_by_client_id
, &lease
->client_id
, lease
);
37 hashmap_remove_value(lease
->server
->static_leases_by_address
, UINT32_TO_PTR(lease
->address
), lease
);
38 hashmap_remove_value(lease
->server
->static_leases_by_client_id
, &lease
->client_id
, lease
);
41 free(lease
->client_id
.data
);
45 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPLease
*, dhcp_lease_free
);
47 /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
48 * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
49 * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
50 * accidentally hand it out */
51 int sd_dhcp_server_configure_pool(
52 sd_dhcp_server
*server
,
53 const struct in_addr
*address
,
54 unsigned char prefixlen
,
58 struct in_addr netmask_addr
;
60 uint32_t server_off
, broadcast_off
, size_max
;
62 assert_return(server
, -EINVAL
);
63 assert_return(address
, -EINVAL
);
64 assert_return(address
->s_addr
!= INADDR_ANY
, -EINVAL
);
65 assert_return(prefixlen
<= 32, -ERANGE
);
67 assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr
, prefixlen
));
68 netmask
= netmask_addr
.s_addr
;
70 server_off
= be32toh(address
->s_addr
& ~netmask
);
71 broadcast_off
= be32toh(~netmask
);
73 /* the server address cannot be the subnet address */
74 assert_return(server_off
!= 0, -ERANGE
);
76 /* nor the broadcast address */
77 assert_return(server_off
!= broadcast_off
, -ERANGE
);
79 /* 0 offset means we should set a default, we skip the first (subnet) address
80 and take the next one */
84 size_max
= (broadcast_off
+ 1) /* the number of addresses in the subnet */
85 - offset
/* exclude the addresses before the offset */
86 - 1; /* exclude the last (broadcast) address */
88 /* The pool must contain at least one address */
89 assert_return(size_max
>= 1, -ERANGE
);
92 assert_return(size
<= size_max
, -ERANGE
);
96 if (server
->address
!= address
->s_addr
|| server
->netmask
!= netmask
|| server
->pool_size
!= size
|| server
->pool_offset
!= offset
) {
98 server
->pool_offset
= offset
;
99 server
->pool_size
= size
;
101 server
->address
= address
->s_addr
;
102 server
->netmask
= netmask
;
103 server
->subnet
= address
->s_addr
& netmask
;
105 /* Drop any leases associated with the old address range */
106 hashmap_clear(server
->bound_leases_by_address
);
107 hashmap_clear(server
->bound_leases_by_client_id
);
109 if (server
->callback
)
110 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
116 int sd_dhcp_server_is_running(sd_dhcp_server
*server
) {
117 assert_return(server
, false);
119 return !!server
->receive_message
;
122 int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server
*server
) {
123 assert_return(server
, -EINVAL
);
125 return in4_addr_is_set(&server
->relay_target
);
128 void client_id_hash_func(const DHCPClientId
*id
, struct siphash
*state
) {
130 assert(id
->length
> 0);
133 siphash24_compress(&id
->length
, sizeof(id
->length
), state
);
134 siphash24_compress(id
->data
, id
->length
, state
);
137 int client_id_compare_func(const DHCPClientId
*a
, const DHCPClientId
*b
) {
140 assert(a
->length
> 0);
142 assert(b
->length
> 0);
145 r
= CMP(a
->length
, b
->length
);
149 return memcmp(a
->data
, b
->data
, a
->length
);
152 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
156 client_id_compare_func
,
160 static sd_dhcp_server
*dhcp_server_free(sd_dhcp_server
*server
) {
163 sd_dhcp_server_stop(server
);
165 sd_event_unref(server
->event
);
167 free(server
->boot_server_name
);
168 free(server
->boot_filename
);
169 free(server
->timezone
);
171 for (sd_dhcp_lease_server_type_t i
= 0; i
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; i
++)
172 free(server
->servers
[i
].addr
);
174 server
->bound_leases_by_address
= hashmap_free(server
->bound_leases_by_address
);
175 server
->bound_leases_by_client_id
= hashmap_free(server
->bound_leases_by_client_id
);
176 server
->static_leases_by_address
= hashmap_free(server
->static_leases_by_address
);
177 server
->static_leases_by_client_id
= hashmap_free(server
->static_leases_by_client_id
);
179 ordered_set_free(server
->extra_options
);
180 ordered_set_free(server
->vendor_options
);
182 free(server
->agent_circuit_id
);
183 free(server
->agent_remote_id
);
185 free(server
->ifname
);
186 return mfree(server
);
189 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server
, sd_dhcp_server
, dhcp_server_free
);
191 int sd_dhcp_server_new(sd_dhcp_server
**ret
, int ifindex
) {
192 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
194 assert_return(ret
, -EINVAL
);
195 assert_return(ifindex
> 0, -EINVAL
);
197 server
= new(sd_dhcp_server
, 1);
201 *server
= (sd_dhcp_server
) {
206 .address
= htobe32(INADDR_ANY
),
207 .netmask
= htobe32(INADDR_ANY
),
209 .bind_to_interface
= true,
210 .default_lease_time
= DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC
, USEC_PER_SEC
),
211 .max_lease_time
= DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC
, USEC_PER_SEC
),
214 *ret
= TAKE_PTR(server
);
219 int sd_dhcp_server_set_ifname(sd_dhcp_server
*server
, const char *ifname
) {
220 assert_return(server
, -EINVAL
);
221 assert_return(ifname
, -EINVAL
);
223 if (!ifname_valid_full(ifname
, IFNAME_VALID_ALTERNATIVE
))
226 return free_and_strdup(&server
->ifname
, ifname
);
229 int sd_dhcp_server_get_ifname(sd_dhcp_server
*server
, const char **ret
) {
232 assert_return(server
, -EINVAL
);
234 r
= get_ifname(server
->ifindex
, &server
->ifname
);
239 *ret
= server
->ifname
;
244 int sd_dhcp_server_attach_event(sd_dhcp_server
*server
, sd_event
*event
, int64_t priority
) {
247 assert_return(server
, -EINVAL
);
248 assert_return(!server
->event
, -EBUSY
);
251 server
->event
= sd_event_ref(event
);
253 r
= sd_event_default(&server
->event
);
258 server
->event_priority
= priority
;
263 int sd_dhcp_server_detach_event(sd_dhcp_server
*server
) {
264 assert_return(server
, -EINVAL
);
266 server
->event
= sd_event_unref(server
->event
);
271 sd_event
*sd_dhcp_server_get_event(sd_dhcp_server
*server
) {
272 assert_return(server
, NULL
);
274 return server
->event
;
277 int sd_dhcp_server_set_boot_server_address(sd_dhcp_server
*server
, const struct in_addr
*address
) {
278 assert_return(server
, -EINVAL
);
281 server
->boot_server_address
= *address
;
283 server
->boot_server_address
= (struct in_addr
) {};
288 int sd_dhcp_server_set_boot_server_name(sd_dhcp_server
*server
, const char *name
) {
291 assert_return(server
, -EINVAL
);
294 r
= dns_name_is_valid(name
);
301 return free_and_strdup(&server
->boot_server_name
, name
);
304 int sd_dhcp_server_set_boot_filename(sd_dhcp_server
*server
, const char *filename
) {
305 assert_return(server
, -EINVAL
);
307 if (filename
&& (!string_is_safe(filename
) || !ascii_is_valid(filename
)))
310 return free_and_strdup(&server
->boot_filename
, filename
);
313 int sd_dhcp_server_stop(sd_dhcp_server
*server
) {
319 running
= sd_dhcp_server_is_running(server
);
321 server
->receive_message
= sd_event_source_disable_unref(server
->receive_message
);
322 server
->receive_broadcast
= sd_event_source_disable_unref(server
->receive_broadcast
);
324 server
->fd_raw
= safe_close(server
->fd_raw
);
325 server
->fd
= safe_close(server
->fd
);
326 server
->fd_broadcast
= safe_close(server
->fd_broadcast
);
329 log_dhcp_server(server
, "STOPPED");
334 static int dhcp_server_send_unicast_raw(
335 sd_dhcp_server
*server
,
337 const uint8_t *chaddr
,
341 union sockaddr_union link
= {
342 .ll
.sll_family
= AF_PACKET
,
343 .ll
.sll_protocol
= htobe16(ETH_P_IP
),
344 .ll
.sll_ifindex
= server
->ifindex
,
345 .ll
.sll_halen
= hlen
,
349 assert(server
->ifindex
> 0);
350 assert(server
->address
!= 0);
354 assert(len
> sizeof(DHCPPacket
));
356 memcpy(link
.ll
.sll_addr
, chaddr
, hlen
);
358 if (len
> UINT16_MAX
)
361 dhcp_packet_append_ip_headers(packet
, server
->address
, DHCP_PORT_SERVER
,
363 DHCP_PORT_CLIENT
, len
, -1);
365 return dhcp_network_send_raw_socket(server
->fd_raw
, &link
, packet
, len
);
368 static int dhcp_server_send_udp(sd_dhcp_server
*server
, be32_t destination
,
369 uint16_t destination_port
,
370 DHCPMessage
*message
, size_t len
) {
371 union sockaddr_union dest
= {
372 .in
.sin_family
= AF_INET
,
373 .in
.sin_port
= htobe16(destination_port
),
374 .in
.sin_addr
.s_addr
= destination
,
380 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo
))) control
= {};
381 struct msghdr msg
= {
383 .msg_namelen
= sizeof(dest
.in
),
387 struct cmsghdr
*cmsg
;
388 struct in_pktinfo
*pktinfo
;
391 assert(server
->fd
>= 0);
393 assert(len
> sizeof(DHCPMessage
));
395 if (server
->bind_to_interface
) {
396 msg
.msg_control
= &control
;
397 msg
.msg_controllen
= sizeof(control
);
399 cmsg
= CMSG_FIRSTHDR(&msg
);
402 cmsg
->cmsg_level
= IPPROTO_IP
;
403 cmsg
->cmsg_type
= IP_PKTINFO
;
404 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
406 /* we attach source interface and address info to the message
407 rather than binding the socket. This will be mostly useful
408 when we gain support for arbitrary number of server addresses
410 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
413 pktinfo
->ipi_ifindex
= server
->ifindex
;
414 pktinfo
->ipi_spec_dst
.s_addr
= server
->address
;
417 if (sendmsg(server
->fd
, &msg
, 0) < 0)
423 static bool requested_broadcast(DHCPMessage
*message
) {
425 return message
->flags
& htobe16(0x8000);
428 static int dhcp_server_send(
429 sd_dhcp_server
*server
,
431 const uint8_t *chaddr
,
433 uint16_t destination_port
,
438 if (destination
!= INADDR_ANY
)
439 return dhcp_server_send_udp(server
, destination
,
440 destination_port
, &packet
->dhcp
,
441 sizeof(DHCPMessage
) + optoffset
);
442 else if (l2_broadcast
)
443 return dhcp_server_send_udp(server
, INADDR_BROADCAST
,
444 destination_port
, &packet
->dhcp
,
445 sizeof(DHCPMessage
) + optoffset
);
447 /* we cannot send UDP packet to specific MAC address when the
448 address is not yet configured, so must fall back to raw
450 return dhcp_server_send_unicast_raw(server
, hlen
, chaddr
, packet
,
451 sizeof(DHCPPacket
) + optoffset
);
454 int dhcp_server_send_packet(sd_dhcp_server
*server
,
455 DHCPRequest
*req
, DHCPPacket
*packet
,
456 int type
, size_t optoffset
) {
457 be32_t destination
= INADDR_ANY
;
458 uint16_t destination_port
= DHCP_PORT_CLIENT
;
463 assert(req
->max_optlen
> 0);
464 assert(req
->message
);
465 assert(optoffset
<= req
->max_optlen
);
468 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
469 SD_DHCP_OPTION_SERVER_IDENTIFIER
,
470 4, &server
->address
);
474 if (req
->agent_info_option
) {
475 size_t opt_full_length
= *(req
->agent_info_option
+ 1) + 2;
476 /* there must be space left for SD_DHCP_OPTION_END */
477 if (optoffset
+ opt_full_length
< req
->max_optlen
) {
478 memcpy(packet
->dhcp
.options
+ optoffset
, req
->agent_info_option
, opt_full_length
);
479 optoffset
+= opt_full_length
;
483 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &optoffset
, 0,
484 SD_DHCP_OPTION_END
, 0, NULL
);
488 /* RFC 2131 Section 4.1
490 If the ’giaddr’ field in a DHCP message from a client is non-zero,
491 the server sends any return messages to the ’DHCP server’ port on the
492 BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’
493 field is zero and the ’ciaddr’ field is nonzero, then the server
494 unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’.
495 If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is
496 set, then the server broadcasts DHCPOFFER and DHCPACK messages to
497 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and
498 ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK
499 messages to the client’s hardware address and ’yiaddr’ address. In
500 all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK
501 messages to 0xffffffff.
505 If ’giaddr’ is set in the DHCPREQUEST message, the client is on a
506 different subnet. The server MUST set the broadcast bit in the
507 DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
508 client, because the client may not have a correct network address
509 or subnet mask, and the client may not be answering ARP requests.
511 if (req
->message
->giaddr
!= 0) {
512 destination
= req
->message
->giaddr
;
513 destination_port
= DHCP_PORT_SERVER
;
514 if (type
== DHCP_NAK
)
515 packet
->dhcp
.flags
= htobe16(0x8000);
516 } else if (req
->message
->ciaddr
!= 0 && type
!= DHCP_NAK
)
517 destination
= req
->message
->ciaddr
;
519 bool l2_broadcast
= requested_broadcast(req
->message
) || type
== DHCP_NAK
;
520 return dhcp_server_send(server
, req
->message
->hlen
, req
->message
->chaddr
,
521 destination
, destination_port
, packet
, optoffset
, l2_broadcast
);
524 static int server_message_init(
525 sd_dhcp_server
*server
,
528 size_t *ret_optoffset
,
531 _cleanup_free_ DHCPPacket
*packet
= NULL
;
532 size_t optoffset
= 0;
537 assert(ret_optoffset
);
538 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
, DHCP_NAK
));
541 packet
= malloc0(sizeof(DHCPPacket
) + req
->max_optlen
);
545 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
,
546 be32toh(req
->message
->xid
), type
,
547 req
->message
->htype
, req
->message
->hlen
, req
->message
->chaddr
,
548 req
->max_optlen
, &optoffset
);
552 packet
->dhcp
.flags
= req
->message
->flags
;
553 packet
->dhcp
.giaddr
= req
->message
->giaddr
;
555 *ret_optoffset
= optoffset
;
556 *ret
= TAKE_PTR(packet
);
561 static int server_send_offer_or_ack(
562 sd_dhcp_server
*server
,
567 _cleanup_free_ DHCPPacket
*packet
= NULL
;
575 assert(IN_SET(type
, DHCP_OFFER
, DHCP_ACK
));
577 r
= server_message_init(server
, &packet
, type
, &offset
, req
);
581 packet
->dhcp
.yiaddr
= address
;
582 packet
->dhcp
.siaddr
= server
->boot_server_address
.s_addr
;
584 lease_time
= htobe32(req
->lifetime
);
585 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
586 SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
, 4,
591 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
592 SD_DHCP_OPTION_SUBNET_MASK
, 4, &server
->netmask
);
596 if (server
->emit_router
) {
597 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
598 SD_DHCP_OPTION_ROUTER
, 4,
599 in4_addr_is_set(&server
->router_address
) ?
600 &server
->router_address
.s_addr
:
606 if (server
->boot_server_name
) {
607 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
608 SD_DHCP_OPTION_BOOT_SERVER_NAME
,
609 strlen(server
->boot_server_name
), server
->boot_server_name
);
614 if (server
->boot_filename
) {
615 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
616 SD_DHCP_OPTION_BOOT_FILENAME
,
617 strlen(server
->boot_filename
), server
->boot_filename
);
622 if (type
== DHCP_ACK
) {
623 static const uint8_t option_map
[_SD_DHCP_LEASE_SERVER_TYPE_MAX
] = {
624 [SD_DHCP_LEASE_DNS
] = SD_DHCP_OPTION_DOMAIN_NAME_SERVER
,
625 [SD_DHCP_LEASE_NTP
] = SD_DHCP_OPTION_NTP_SERVER
,
626 [SD_DHCP_LEASE_SIP
] = SD_DHCP_OPTION_SIP_SERVER
,
627 [SD_DHCP_LEASE_POP3
] = SD_DHCP_OPTION_POP3_SERVER
,
628 [SD_DHCP_LEASE_SMTP
] = SD_DHCP_OPTION_SMTP_SERVER
,
629 [SD_DHCP_LEASE_LPR
] = SD_DHCP_OPTION_LPR_SERVER
,
632 for (sd_dhcp_lease_server_type_t k
= 0; k
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; k
++) {
633 if (server
->servers
[k
].size
<= 0)
636 r
= dhcp_option_append(
637 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
639 sizeof(struct in_addr
) * server
->servers
[k
].size
,
640 server
->servers
[k
].addr
);
646 if (server
->timezone
) {
647 r
= dhcp_option_append(
648 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
649 SD_DHCP_OPTION_TZDB_TIMEZONE
,
650 strlen(server
->timezone
), server
->timezone
);
656 ORDERED_SET_FOREACH(j
, server
->extra_options
) {
657 r
= dhcp_option_append(&packet
->dhcp
, req
->max_optlen
, &offset
, 0,
658 j
->option
, j
->length
, j
->data
);
663 if (!ordered_set_isempty(server
->vendor_options
)) {
664 r
= dhcp_option_append(
665 &packet
->dhcp
, req
->max_optlen
, &offset
, 0,
666 SD_DHCP_OPTION_VENDOR_SPECIFIC
,
667 ordered_set_size(server
->vendor_options
), server
->vendor_options
);
672 return dhcp_server_send_packet(server
, req
, packet
, type
, offset
);
675 static int server_send_nak_or_ignore(sd_dhcp_server
*server
, bool init_reboot
, DHCPRequest
*req
) {
676 _cleanup_free_ DHCPPacket
*packet
= NULL
;
680 /* When a request is refused, RFC 2131, section 4.3.2 mentioned we should send NAK when the
681 * client is in INITREBOOT. If the client is in other state, there is nothing mentioned in the
682 * RFC whether we should send NAK or not. Hence, let's silently ignore the request. */
687 r
= server_message_init(server
, &packet
, DHCP_NAK
, &offset
, req
);
689 return log_dhcp_server_errno(server
, r
, "Failed to create NAK message: %m");
691 r
= dhcp_server_send_packet(server
, req
, packet
, DHCP_NAK
, offset
);
693 return log_dhcp_server_errno(server
, r
, "Could not send NAK message: %m");
695 log_dhcp_server(server
, "NAK (0x%x)", be32toh(req
->message
->xid
));
699 static int server_send_forcerenew(
700 sd_dhcp_server
*server
,
705 const uint8_t *chaddr
) {
707 _cleanup_free_ DHCPPacket
*packet
= NULL
;
708 size_t optoffset
= 0;
712 assert(address
!= INADDR_ANY
);
715 packet
= malloc0(sizeof(DHCPPacket
) + DHCP_MIN_OPTIONS_SIZE
);
719 r
= dhcp_message_init(&packet
->dhcp
, BOOTREPLY
, 0,
720 DHCP_FORCERENEW
, htype
, hlen
, chaddr
,
721 DHCP_MIN_OPTIONS_SIZE
, &optoffset
);
725 r
= dhcp_option_append(&packet
->dhcp
, DHCP_MIN_OPTIONS_SIZE
,
726 &optoffset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
730 return dhcp_server_send_udp(server
, address
, DHCP_PORT_CLIENT
,
732 sizeof(DHCPMessage
) + optoffset
);
735 static int parse_request(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
736 DHCPRequest
*req
= userdata
;
741 case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME
:
743 req
->lifetime
= unaligned_read_be32(option
);
746 case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
:
748 memcpy(&req
->requested_ip
, option
, sizeof(be32_t
));
751 case SD_DHCP_OPTION_SERVER_IDENTIFIER
:
753 memcpy(&req
->server_id
, option
, sizeof(be32_t
));
756 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
760 data
= memdup(option
, len
);
764 free_and_replace(req
->client_id
.data
, data
);
765 req
->client_id
.length
= len
;
769 case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE
:
771 if (len
== 2 && unaligned_read_be16(option
) >= sizeof(DHCPPacket
))
772 req
->max_optlen
= unaligned_read_be16(option
) - sizeof(DHCPPacket
);
775 case SD_DHCP_OPTION_RELAY_AGENT_INFORMATION
:
776 req
->agent_info_option
= (uint8_t*)option
- 2;
784 static DHCPRequest
* dhcp_request_free(DHCPRequest
*req
) {
788 free(req
->client_id
.data
);
792 DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest
*, dhcp_request_free
);
794 static int ensure_sane_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPMessage
*message
) {
798 req
->message
= message
;
800 if (message
->hlen
> sizeof(message
->chaddr
))
803 /* set client id based on MAC address if client did not send an explicit one */
804 if (!req
->client_id
.data
) {
807 if (message
->hlen
== 0)
810 data
= new0(uint8_t, message
->hlen
+ 1);
815 memcpy(data
+ 1, message
->chaddr
, message
->hlen
);
817 req
->client_id
.length
= message
->hlen
+ 1;
818 req
->client_id
.data
= data
;
821 if (message
->hlen
== 0 || memeqzero(message
->chaddr
, message
->hlen
)) {
822 /* See RFC2131 section 4.1.1.
823 * hlen and chaddr may not be set for non-ethernet interface.
824 * Let's try to retrieve it from the client ID. */
826 if (!req
->client_id
.data
)
829 if (req
->client_id
.length
<= 1 || req
->client_id
.length
> sizeof(message
->chaddr
) + 1)
832 if (req
->client_id
.data
[0] != 0x01)
835 message
->hlen
= req
->client_id
.length
- 1;
836 memcpy(message
->chaddr
, req
->client_id
.data
+ 1, message
->hlen
);
839 if (req
->max_optlen
< DHCP_MIN_OPTIONS_SIZE
)
840 req
->max_optlen
= DHCP_MIN_OPTIONS_SIZE
;
842 if (req
->lifetime
<= 0)
843 req
->lifetime
= MAX(1ULL, server
->default_lease_time
);
845 if (server
->max_lease_time
> 0 && req
->lifetime
> server
->max_lease_time
)
846 req
->lifetime
= server
->max_lease_time
;
851 static bool address_is_in_pool(sd_dhcp_server
*server
, be32_t address
) {
854 if (server
->pool_size
== 0)
857 if (address
== server
->address
)
860 if (be32toh(address
) < (be32toh(server
->subnet
) | server
->pool_offset
) ||
861 be32toh(address
) >= (be32toh(server
->subnet
) | (server
->pool_offset
+ server
->pool_size
)))
864 if (hashmap_contains(server
->static_leases_by_address
, UINT32_TO_PTR(address
)))
870 static int append_agent_information_option(sd_dhcp_server
*server
, DHCPMessage
*message
, size_t opt_length
, size_t size
) {
877 r
= dhcp_option_find_option(message
->options
, opt_length
, SD_DHCP_OPTION_END
, &offset
);
881 r
= dhcp_option_append(message
, size
, &offset
, 0, SD_DHCP_OPTION_RELAY_AGENT_INFORMATION
, 0, server
);
885 r
= dhcp_option_append(message
, size
, &offset
, 0, SD_DHCP_OPTION_END
, 0, NULL
);
891 static int dhcp_server_relay_message(sd_dhcp_server
*server
, DHCPMessage
*message
, size_t opt_length
, size_t buflen
) {
892 _cleanup_free_ DHCPPacket
*packet
= NULL
;
897 assert(sd_dhcp_server_is_in_relay_mode(server
));
899 if (message
->hlen
== 0 || message
->hlen
> sizeof(message
->chaddr
) || memeqzero(message
->chaddr
, message
->hlen
))
900 return log_dhcp_server_errno(server
, SYNTHETIC_ERRNO(EBADMSG
),
901 "(relay agent) received message without/invalid hardware address, discarding.");
903 if (message
->op
== BOOTREQUEST
) {
904 log_dhcp_server(server
, "(relay agent) BOOTREQUEST (0x%x)", be32toh(message
->xid
));
905 if (message
->hops
>= 16)
909 /* https://tools.ietf.org/html/rfc1542#section-4.1.1 */
910 if (message
->giaddr
== 0)
911 message
->giaddr
= server
->address
;
913 if (server
->agent_circuit_id
|| server
->agent_remote_id
) {
914 r
= append_agent_information_option(server
, message
, opt_length
, buflen
- sizeof(DHCPMessage
));
916 return log_dhcp_server_errno(server
, r
, "could not append relay option: %m");
920 return dhcp_server_send_udp(server
, server
->relay_target
.s_addr
, DHCP_PORT_SERVER
, message
, sizeof(DHCPMessage
) + opt_length
);
921 } else if (message
->op
== BOOTREPLY
) {
922 log_dhcp_server(server
, "(relay agent) BOOTREPLY (0x%x)", be32toh(message
->xid
));
923 if (message
->giaddr
!= server
->address
)
924 return log_dhcp_server_errno(server
, SYNTHETIC_ERRNO(EBADMSG
),
925 "(relay agent) BOOTREPLY giaddr mismatch, discarding");
927 int message_type
= dhcp_option_parse(message
, sizeof(DHCPMessage
) + opt_length
, NULL
, NULL
, NULL
);
928 if (message_type
< 0)
931 packet
= malloc0(sizeof(DHCPPacket
) + opt_length
);
934 memcpy(&packet
->dhcp
, message
, sizeof(DHCPMessage
) + opt_length
);
936 r
= dhcp_option_remove_option(packet
->dhcp
.options
, opt_length
, SD_DHCP_OPTION_RELAY_AGENT_INFORMATION
);
940 bool l2_broadcast
= requested_broadcast(message
) || message_type
== DHCP_NAK
;
941 const be32_t destination
= message_type
== DHCP_NAK
? INADDR_ANY
: message
->ciaddr
;
942 return dhcp_server_send(server
, message
->hlen
, message
->chaddr
, destination
, DHCP_PORT_CLIENT
, packet
, opt_length
, l2_broadcast
);
947 static int prepare_new_lease(
948 DHCPLease
**ret_lease
,
950 const DHCPClientId
*client_id
,
953 const uint8_t *chaddr
,
957 _cleanup_(dhcp_lease_freep
) DHCPLease
*lease
= NULL
;
959 lease
= new(DHCPLease
, 1);
963 *lease
= (DHCPLease
) {
965 .client_id
.length
= client_id
->length
,
969 .expiration
= expiration
,
971 lease
->client_id
.data
= memdup(client_id
->data
, client_id
->length
);
972 if (!lease
->client_id
.data
)
975 memcpy(lease
->chaddr
, chaddr
, hlen
);
977 *ret_lease
= TAKE_PTR(lease
);
982 static int server_ack_request(sd_dhcp_server
*server
, DHCPRequest
*req
, DHCPLease
*existing_lease
, be32_t address
) {
983 usec_t time_now
, expiration
;
988 assert(address
!= 0);
990 r
= sd_event_now(server
->event
, CLOCK_BOOTTIME
, &time_now
);
994 expiration
= usec_add(req
->lifetime
* USEC_PER_SEC
, time_now
);
996 if (existing_lease
) {
997 assert(existing_lease
->server
);
998 assert(existing_lease
->address
== address
);
999 existing_lease
->expiration
= expiration
;
1002 _cleanup_(dhcp_lease_freep
) DHCPLease
*lease
= NULL
;
1004 r
= prepare_new_lease(&lease
, address
, &req
->client_id
,
1005 req
->message
->htype
, req
->message
->hlen
,
1006 req
->message
->chaddr
, req
->message
->giaddr
, expiration
);
1008 return log_dhcp_server_errno(server
, r
, "Failed to create new lease: %m");
1010 lease
->server
= server
; /* This must be set just before hashmap_put(). */
1012 r
= hashmap_ensure_put(&server
->bound_leases_by_client_id
, &dhcp_lease_hash_ops
, &lease
->client_id
, lease
);
1014 return log_dhcp_server_errno(server
, r
, "Could not save lease: %m");
1016 r
= hashmap_ensure_put(&server
->bound_leases_by_address
, NULL
, UINT32_TO_PTR(lease
->address
), lease
);
1018 return log_dhcp_server_errno(server
, r
, "Could not save lease: %m");
1023 r
= server_send_offer_or_ack(server
, req
, address
, DHCP_ACK
);
1025 return log_dhcp_server_errno(server
, r
, "Could not send ACK: %m");
1027 log_dhcp_server(server
, "ACK (0x%x)", be32toh(req
->message
->xid
));
1029 if (server
->callback
)
1030 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
1035 static int dhcp_server_cleanup_expired_leases(sd_dhcp_server
*server
) {
1042 r
= sd_event_now(server
->event
, CLOCK_BOOTTIME
, &time_now
);
1046 HASHMAP_FOREACH(lease
, server
->bound_leases_by_client_id
)
1047 if (lease
->expiration
< time_now
) {
1048 log_dhcp_server(server
, "CLEAN (0x%x)", be32toh(lease
->address
));
1049 dhcp_lease_free(lease
);
1055 static bool address_available(sd_dhcp_server
*server
, be32_t address
) {
1058 if (hashmap_contains(server
->bound_leases_by_address
, UINT32_TO_PTR(address
)) ||
1059 hashmap_contains(server
->static_leases_by_address
, UINT32_TO_PTR(address
)) ||
1060 address
== server
->address
)
1066 #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
1068 int dhcp_server_handle_message(sd_dhcp_server
*server
, DHCPMessage
*message
, size_t length
) {
1069 _cleanup_(dhcp_request_freep
) DHCPRequest
*req
= NULL
;
1070 _cleanup_free_
char *error_message
= NULL
;
1071 DHCPLease
*existing_lease
, *static_lease
;
1077 if (message
->op
!= BOOTREQUEST
)
1080 req
= new0(DHCPRequest
, 1);
1084 type
= dhcp_option_parse(message
, length
, parse_request
, req
, &error_message
);
1088 r
= ensure_sane_request(server
, req
, message
);
1092 r
= dhcp_server_cleanup_expired_leases(server
);
1096 existing_lease
= hashmap_get(server
->bound_leases_by_client_id
, &req
->client_id
);
1097 static_lease
= hashmap_get(server
->static_leases_by_client_id
, &req
->client_id
);
1101 case DHCP_DISCOVER
: {
1102 be32_t address
= INADDR_ANY
;
1104 log_dhcp_server(server
, "DISCOVER (0x%x)", be32toh(req
->message
->xid
));
1106 if (server
->pool_size
== 0)
1107 /* no pool allocated */
1110 /* for now pick a random free address from the pool */
1112 address
= static_lease
->address
;
1113 else if (existing_lease
)
1114 address
= existing_lease
->address
;
1116 struct siphash state
;
1119 /* even with no persistence of leases, we try to offer the same client
1120 the same IP address. we do this by using the hash of the client id
1121 as the offset into the pool of leases when finding the next free one */
1123 siphash24_init(&state
, HASH_KEY
.bytes
);
1124 client_id_hash_func(&req
->client_id
, &state
);
1125 hash
= htole64(siphash24_finalize(&state
));
1127 for (unsigned i
= 0; i
< server
->pool_size
; i
++) {
1130 tmp_address
= server
->subnet
| htobe32(server
->pool_offset
+ (hash
+ i
) % server
->pool_size
);
1131 if (address_available(server
, tmp_address
)) {
1132 address
= tmp_address
;
1138 if (address
== INADDR_ANY
)
1139 /* no free addresses left */
1142 r
= server_send_offer_or_ack(server
, req
, address
, DHCP_OFFER
);
1144 /* this only fails on critical errors */
1145 return log_dhcp_server_errno(server
, r
, "Could not send offer: %m");
1147 log_dhcp_server(server
, "OFFER (0x%x)", be32toh(req
->message
->xid
));
1151 log_dhcp_server(server
, "DECLINE (0x%x): %s", be32toh(req
->message
->xid
), strna(error_message
));
1153 /* TODO: make sure we don't offer this address again */
1157 case DHCP_REQUEST
: {
1159 bool init_reboot
= false;
1161 /* see RFC 2131, section 4.3.2 */
1163 if (req
->server_id
!= 0) {
1164 log_dhcp_server(server
, "REQUEST (selecting) (0x%x)",
1165 be32toh(req
->message
->xid
));
1168 if (req
->server_id
!= server
->address
)
1169 /* client did not pick us */
1172 if (req
->message
->ciaddr
!= 0)
1173 /* this MUST be zero */
1176 if (req
->requested_ip
== 0)
1177 /* this must be filled in with the yiaddr
1178 from the chosen OFFER */
1181 address
= req
->requested_ip
;
1182 } else if (req
->requested_ip
!= 0) {
1183 log_dhcp_server(server
, "REQUEST (init-reboot) (0x%x)",
1184 be32toh(req
->message
->xid
));
1187 if (req
->message
->ciaddr
!= 0)
1188 /* this MUST be zero */
1191 /* TODO: check more carefully if IP is correct */
1192 address
= req
->requested_ip
;
1195 log_dhcp_server(server
, "REQUEST (rebinding/renewing) (0x%x)",
1196 be32toh(req
->message
->xid
));
1198 /* REBINDING / RENEWING */
1199 if (req
->message
->ciaddr
== 0)
1200 /* this MUST be filled in with clients IP address */
1203 address
= req
->message
->ciaddr
;
1206 /* disallow our own address */
1207 if (address
== server
->address
)
1211 /* Found a static lease for the client ID. */
1213 if (static_lease
->address
!= address
)
1214 /* The client requested an address which is different from the static lease. Refuse. */
1215 return server_send_nak_or_ignore(server
, init_reboot
, req
);
1217 return server_ack_request(server
, req
, existing_lease
, address
);
1220 if (address_is_in_pool(server
, address
)) {
1221 /* The requested address is in the pool. */
1223 if (existing_lease
&& existing_lease
->address
!= address
)
1224 /* We previously assigned an address, but the client requested another one. Refuse. */
1225 return server_send_nak_or_ignore(server
, init_reboot
, req
);
1227 return server_ack_request(server
, req
, existing_lease
, address
);
1230 return server_send_nak_or_ignore(server
, init_reboot
, req
);
1233 case DHCP_RELEASE
: {
1234 log_dhcp_server(server
, "RELEASE (0x%x)",
1235 be32toh(req
->message
->xid
));
1237 if (!existing_lease
)
1240 if (existing_lease
->address
!= req
->message
->ciaddr
)
1243 dhcp_lease_free(existing_lease
);
1245 if (server
->callback
)
1246 server
->callback(server
, SD_DHCP_SERVER_EVENT_LEASE_CHANGED
, server
->callback_userdata
);
1254 static size_t relay_agent_information_length(const char* agent_circuit_id
, const char* agent_remote_id
) {
1256 if (agent_circuit_id
)
1257 sum
+= 2 + strlen(agent_circuit_id
);
1258 if (agent_remote_id
)
1259 sum
+= 2 + strlen(agent_remote_id
);
1263 static int server_receive_message(sd_event_source
*s
, int fd
,
1264 uint32_t revents
, void *userdata
) {
1265 _cleanup_free_ DHCPMessage
*message
= NULL
;
1266 CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct in_pktinfo
))) control
;
1267 sd_dhcp_server
*server
= userdata
;
1268 struct iovec iov
= {};
1269 struct msghdr msg
= {
1272 .msg_control
= &control
,
1273 .msg_controllen
= sizeof(control
),
1275 struct cmsghdr
*cmsg
;
1276 ssize_t datagram_size
, len
;
1281 datagram_size
= next_datagram_size_fd(fd
);
1282 if (datagram_size
< 0) {
1283 if (ERRNO_IS_TRANSIENT(datagram_size
) || ERRNO_IS_DISCONNECT(datagram_size
))
1286 log_dhcp_server_errno(server
, datagram_size
, "Failed to determine datagram size to read, ignoring: %m");
1290 size_t buflen
= datagram_size
;
1291 if (sd_dhcp_server_is_in_relay_mode(server
))
1292 /* Preallocate the additional size for DHCP Relay Agent Information Option if needed */
1293 buflen
+= relay_agent_information_length(server
->agent_circuit_id
, server
->agent_remote_id
) + 2;
1295 message
= malloc(buflen
);
1299 iov
= IOVEC_MAKE(message
, datagram_size
);
1301 len
= recvmsg_safe(fd
, &msg
, 0);
1303 if (ERRNO_IS_TRANSIENT(len
) || ERRNO_IS_DISCONNECT(len
))
1306 log_dhcp_server_errno(server
, len
, "Could not receive message, ignoring: %m");
1310 if ((size_t) len
< sizeof(DHCPMessage
))
1313 CMSG_FOREACH(cmsg
, &msg
)
1314 if (cmsg
->cmsg_level
== IPPROTO_IP
&&
1315 cmsg
->cmsg_type
== IP_PKTINFO
&&
1316 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct in_pktinfo
))) {
1317 struct in_pktinfo
*info
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
1319 /* TODO figure out if this can be done as a filter on
1320 * the socket, like for IPv6 */
1321 if (server
->ifindex
!= info
->ipi_ifindex
)
1327 if (sd_dhcp_server_is_in_relay_mode(server
)) {
1328 r
= dhcp_server_relay_message(server
, message
, len
- sizeof(DHCPMessage
), buflen
);
1330 log_dhcp_server_errno(server
, r
, "Couldn't relay message, ignoring: %m");
1332 r
= dhcp_server_handle_message(server
, message
, (size_t) len
);
1334 log_dhcp_server_errno(server
, r
, "Couldn't process incoming message, ignoring: %m");
1339 static void dhcp_server_update_lease_servers(sd_dhcp_server
*server
) {
1341 assert(server
->address
!= 0);
1343 /* Convert null address -> server address */
1345 for (sd_dhcp_lease_server_type_t k
= 0; k
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
; k
++)
1346 for (size_t i
= 0; i
< server
->servers
[k
].size
; i
++)
1347 if (in4_addr_is_null(&server
->servers
[k
].addr
[i
]))
1348 server
->servers
[k
].addr
[i
].s_addr
= server
->address
;
1351 int sd_dhcp_server_start(sd_dhcp_server
*server
) {
1354 assert_return(server
, -EINVAL
);
1355 assert_return(server
->event
, -EINVAL
);
1357 if (sd_dhcp_server_is_running(server
))
1360 assert_return(!server
->receive_message
, -EBUSY
);
1361 assert_return(server
->fd_raw
< 0, -EBUSY
);
1362 assert_return(server
->fd
< 0, -EBUSY
);
1363 assert_return(server
->address
!= htobe32(INADDR_ANY
), -EUNATCH
);
1365 dhcp_server_update_lease_servers(server
);
1367 r
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
1374 if (server
->bind_to_interface
)
1375 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_ANY
, DHCP_PORT_SERVER
, -1);
1377 r
= dhcp_network_bind_udp_socket(0, server
->address
, DHCP_PORT_SERVER
, -1);
1382 r
= sd_event_add_io(server
->event
, &server
->receive_message
,
1383 server
->fd
, EPOLLIN
,
1384 server_receive_message
, server
);
1388 r
= sd_event_source_set_priority(server
->receive_message
,
1389 server
->event_priority
);
1393 if (!server
->bind_to_interface
) {
1394 r
= dhcp_network_bind_udp_socket(server
->ifindex
, INADDR_BROADCAST
, DHCP_PORT_SERVER
, -1);
1398 server
->fd_broadcast
= r
;
1400 r
= sd_event_add_io(server
->event
, &server
->receive_broadcast
,
1401 server
->fd_broadcast
, EPOLLIN
,
1402 server_receive_message
, server
);
1406 r
= sd_event_source_set_priority(server
->receive_broadcast
,
1407 server
->event_priority
);
1412 log_dhcp_server(server
, "STARTED");
1417 sd_dhcp_server_stop(server
);
1421 int sd_dhcp_server_forcerenew(sd_dhcp_server
*server
) {
1425 assert_return(server
, -EINVAL
);
1427 log_dhcp_server(server
, "FORCERENEW");
1429 HASHMAP_FOREACH(lease
, server
->bound_leases_by_client_id
) {
1430 k
= server_send_forcerenew(server
, lease
->address
, lease
->gateway
,
1431 lease
->htype
, lease
->hlen
, lease
->chaddr
);
1439 int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server
*server
, int enabled
) {
1440 assert_return(server
, -EINVAL
);
1441 assert_return(!sd_dhcp_server_is_running(server
), -EBUSY
);
1443 if (!!enabled
== server
->bind_to_interface
)
1446 server
->bind_to_interface
= enabled
;
1451 int sd_dhcp_server_set_timezone(sd_dhcp_server
*server
, const char *tz
) {
1454 assert_return(server
, -EINVAL
);
1455 assert_return(timezone_is_valid(tz
, LOG_DEBUG
), -EINVAL
);
1457 if (streq_ptr(tz
, server
->timezone
))
1460 r
= free_and_strdup(&server
->timezone
, tz
);
1467 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1468 assert_return(server
, -EINVAL
);
1470 if (t
== server
->max_lease_time
)
1473 server
->max_lease_time
= t
;
1477 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server
*server
, uint32_t t
) {
1478 assert_return(server
, -EINVAL
);
1480 if (t
== server
->default_lease_time
)
1483 server
->default_lease_time
= t
;
1487 int sd_dhcp_server_set_servers(
1488 sd_dhcp_server
*server
,
1489 sd_dhcp_lease_server_type_t what
,
1490 const struct in_addr addresses
[],
1491 size_t n_addresses
) {
1493 struct in_addr
*c
= NULL
;
1495 assert_return(server
, -EINVAL
);
1496 assert_return(!sd_dhcp_server_is_running(server
), -EBUSY
);
1497 assert_return(addresses
|| n_addresses
== 0, -EINVAL
);
1498 assert_return(what
>= 0, -EINVAL
);
1499 assert_return(what
< _SD_DHCP_LEASE_SERVER_TYPE_MAX
, -EINVAL
);
1501 if (server
->servers
[what
].size
== n_addresses
&&
1502 memcmp(server
->servers
[what
].addr
, addresses
, sizeof(struct in_addr
) * n_addresses
) == 0)
1505 if (n_addresses
> 0) {
1506 c
= newdup(struct in_addr
, addresses
, n_addresses
);
1511 free_and_replace(server
->servers
[what
].addr
, c
);
1512 server
->servers
[what
].size
= n_addresses
;
1516 int sd_dhcp_server_set_dns(sd_dhcp_server
*server
, const struct in_addr dns
[], size_t n
) {
1517 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_DNS
, dns
, n
);
1519 int sd_dhcp_server_set_ntp(sd_dhcp_server
*server
, const struct in_addr ntp
[], size_t n
) {
1520 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_NTP
, ntp
, n
);
1522 int sd_dhcp_server_set_sip(sd_dhcp_server
*server
, const struct in_addr sip
[], size_t n
) {
1523 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SIP
, sip
, n
);
1525 int sd_dhcp_server_set_pop3(sd_dhcp_server
*server
, const struct in_addr pop3
[], size_t n
) {
1526 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_POP3
, pop3
, n
);
1528 int sd_dhcp_server_set_smtp(sd_dhcp_server
*server
, const struct in_addr smtp
[], size_t n
) {
1529 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_SMTP
, smtp
, n
);
1531 int sd_dhcp_server_set_lpr(sd_dhcp_server
*server
, const struct in_addr lpr
[], size_t n
) {
1532 return sd_dhcp_server_set_servers(server
, SD_DHCP_LEASE_LPR
, lpr
, n
);
1535 int sd_dhcp_server_set_router(sd_dhcp_server
*server
, const struct in_addr
*router
) {
1536 assert_return(server
, -EINVAL
);
1538 /* router is NULL: router option will not be appended.
1539 * router is null address (0.0.0.0): the server address will be used as the router address.
1540 * otherwise: the specified address will be used as the router address.*/
1542 server
->emit_router
= router
;
1544 server
->router_address
= *router
;
1549 int sd_dhcp_server_add_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1552 assert_return(server
, -EINVAL
);
1553 assert_return(v
, -EINVAL
);
1555 r
= ordered_set_ensure_put(&server
->extra_options
, &dhcp_option_hash_ops
, v
);
1559 sd_dhcp_option_ref(v
);
1563 int sd_dhcp_server_add_vendor_option(sd_dhcp_server
*server
, sd_dhcp_option
*v
) {
1566 assert_return(server
, -EINVAL
);
1567 assert_return(v
, -EINVAL
);
1569 r
= ordered_set_ensure_put(&server
->vendor_options
, &dhcp_option_hash_ops
, v
);
1573 sd_dhcp_option_ref(v
);
1578 int sd_dhcp_server_set_callback(sd_dhcp_server
*server
, sd_dhcp_server_callback_t cb
, void *userdata
) {
1579 assert_return(server
, -EINVAL
);
1581 server
->callback
= cb
;
1582 server
->callback_userdata
= userdata
;
1587 int sd_dhcp_server_set_relay_target(sd_dhcp_server
*server
, const struct in_addr
*address
) {
1588 assert_return(server
, -EINVAL
);
1589 assert_return(!sd_dhcp_server_is_running(server
), -EBUSY
);
1591 if (memcmp(address
, &server
->relay_target
, sizeof(struct in_addr
)) == 0)
1594 server
->relay_target
= *address
;
1598 int sd_dhcp_server_set_relay_agent_information(
1599 sd_dhcp_server
*server
,
1600 const char *agent_circuit_id
,
1601 const char *agent_remote_id
) {
1602 _cleanup_free_
char *circuit_id_dup
= NULL
, *remote_id_dup
= NULL
;
1604 assert_return(server
, -EINVAL
);
1606 if (relay_agent_information_length(agent_circuit_id
, agent_remote_id
) > UINT8_MAX
)
1609 if (agent_circuit_id
) {
1610 circuit_id_dup
= strdup(agent_circuit_id
);
1611 if (!circuit_id_dup
)
1615 if (agent_remote_id
) {
1616 remote_id_dup
= strdup(agent_remote_id
);
1621 free_and_replace(server
->agent_circuit_id
, circuit_id_dup
);
1622 free_and_replace(server
->agent_remote_id
, remote_id_dup
);
1626 int sd_dhcp_server_set_static_lease(
1627 sd_dhcp_server
*server
,
1628 const struct in_addr
*address
,
1630 size_t client_id_size
) {
1632 _cleanup_(dhcp_lease_freep
) DHCPLease
*lease
= NULL
;
1635 assert_return(server
, -EINVAL
);
1636 assert_return(client_id
, -EINVAL
);
1637 assert_return(client_id_size
> 0, -EINVAL
);
1638 assert_return(!sd_dhcp_server_is_running(server
), -EBUSY
);
1640 /* Static lease with an empty or omitted address is a valid entry,
1641 * the server removes any static lease with the specified mac address. */
1642 if (!address
|| address
->s_addr
== 0) {
1645 c
= (DHCPClientId
) {
1646 .length
= client_id_size
,
1650 dhcp_lease_free(hashmap_get(server
->static_leases_by_client_id
, &c
));
1654 lease
= new(DHCPLease
, 1);
1658 *lease
= (DHCPLease
) {
1659 .address
= address
->s_addr
,
1660 .client_id
.length
= client_id_size
,
1662 lease
->client_id
.data
= memdup(client_id
, client_id_size
);
1663 if (!lease
->client_id
.data
)
1666 lease
->server
= server
; /* This must be set just before hashmap_put(). */
1668 r
= hashmap_ensure_put(&server
->static_leases_by_client_id
, &dhcp_lease_hash_ops
, &lease
->client_id
, lease
);
1671 r
= hashmap_ensure_put(&server
->static_leases_by_address
, NULL
, UINT32_TO_PTR(lease
->address
), lease
);