]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-server: drop legacy DHCP relay mode
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 3 May 2026 23:43:41 +0000 (08:43 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 21 May 2026 07:55:59 +0000 (16:55 +0900)
src/libsystemd-network/dhcp-option.c
src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/fuzz-dhcp-server-relay.c [deleted file]
src/libsystemd-network/meson.build
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd-network/test-dhcp-server.c
src/systemd/sd-dhcp-server.h
test/fuzz/fuzz-dhcp-relay/sample1 [moved from test/fuzz/fuzz-dhcp-server-relay/sample1 with 100% similarity]
test/fuzz/fuzz-dhcp-relay/sample2 [moved from test/fuzz/fuzz-dhcp-server-relay/sample2 with 100% similarity]
test/fuzz/fuzz-dhcp-relay/too-large-packet [moved from test/fuzz/fuzz-dhcp-server-relay/too-large-packet with 100% similarity]

index c5e8b2979443316c1cf41b1b73c27f372c8299ca..7ad203f183db8d81d7afbd653acb7a641cf0fd9c 100644 (file)
@@ -7,7 +7,6 @@
 
 #include "alloc-util.h"
 #include "dhcp-option.h"
-#include "dhcp-server-internal.h"
 #include "dns-domain.h"
 #include "hostname-util.h"
 #include "memory-util.h"
@@ -39,8 +38,6 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
         assert(size > 0);
         assert(offset);
 
-        int r;
-
         if (code != SD_DHCP_OPTION_END)
                 /* always make sure there is space for an END option */
                 size--;
@@ -68,34 +65,6 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
                 *offset += 3 + optlen;
 
                 break;
-        case SD_DHCP_OPTION_RELAY_AGENT_INFORMATION: {
-                /* When called with raw data (optlen > 0), e.g. from SendOption=, append as a plain TLV.
-                 * The structured handling below expects optval to be an sd_dhcp_server*. */
-                if (optlen > 0)
-                        return dhcp_option_append_tlv(options, size, offset, code, optlen, optval);
-
-                sd_dhcp_server *server = (sd_dhcp_server *) optval;
-                size_t current_offset = *offset + 2;
-
-                if (server->agent_circuit_id) {
-                        r = dhcp_option_append_tlv(options, size, &current_offset, SD_DHCP_RELAY_AGENT_CIRCUIT_ID,
-                                                   strlen(server->agent_circuit_id), server->agent_circuit_id);
-                        if (r < 0)
-                                return r;
-                }
-                if (server->agent_remote_id) {
-                        r = dhcp_option_append_tlv(options, size, &current_offset, SD_DHCP_RELAY_AGENT_REMOTE_ID,
-                                                   strlen(server->agent_remote_id), server->agent_remote_id);
-                        if (r < 0)
-                                return r;
-                }
-
-                options[*offset] = code;
-                options[*offset + 1] = current_offset - *offset - 2;
-                assert(current_offset - *offset - 2 <= UINT8_MAX);
-                *offset = current_offset;
-                break;
-        }
         default:
                 return dhcp_option_append_tlv(options, size, offset, code, optlen, optval);
         }
index a8e2cbf5c706d82ab881533b7fc06f6e70ab37f7..d4caae66d42b7402bb6a34a8a0a52e4c60c8696e 100644 (file)
@@ -32,14 +32,11 @@ typedef struct sd_dhcp_server {
         sd_event *event;
         int event_priority;
         sd_event_source *receive_message;
-        sd_event_source *receive_broadcast;
         int fd;
         int fd_raw;
-        int fd_broadcast;
 
         int ifindex;
         char *ifname;
-        bool bind_to_interface;
         be32_t address;
         be32_t netmask;
         be32_t subnet;
@@ -73,11 +70,6 @@ typedef struct sd_dhcp_server {
         sd_dhcp_server_callback_t callback;
         void *callback_userdata;
 
-        struct in_addr relay_target;
-
-        char *agent_circuit_id;
-        char *agent_remote_id;
-
         int lease_dir_fd;
         char *lease_file;
 } sd_dhcp_server;
diff --git a/src/libsystemd-network/fuzz-dhcp-server-relay.c b/src/libsystemd-network/fuzz-dhcp-server-relay.c
deleted file mode 100644 (file)
index b2c881c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <fcntl.h>
-
-#include "fuzz.h"
-#include "sd-dhcp-server.c"
-
-ssize_t sendto(int __fd, const void *__buf, size_t __n, int flags, const struct sockaddr *__addr, socklen_t __addr_len) {
-        return __n;
-}
-
-ssize_t sendmsg(int __fd, const struct msghdr *__message, int flags) {
-        return 0;
-}
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-        _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
-        struct in_addr address = {.s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))};
-        union in_addr_union relay_address;
-        _cleanup_free_ uint8_t *message = NULL;
-
-        if (size < sizeof(DHCPMessage))
-                return 0;
-
-        fuzz_setup_logging();
-
-        assert_se(sd_dhcp_server_new(&server, 1) >= 0);
-        assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
-        assert_se(sd_dhcp_server_configure_pool(server, &address, 24, 0, 0) >= 0);
-        assert_se(in_addr_from_string(AF_INET, "192.168.5.1", &relay_address) >= 0);
-        assert_se(sd_dhcp_server_set_relay_target(server, &relay_address.in) >= 0);
-        assert_se(sd_dhcp_server_set_bind_to_interface(server, false) >= 0);
-        assert_se(sd_dhcp_server_set_relay_agent_information(server, "string:sample_circuit_id", "string:sample_remote_id") >= 0);
-
-        size_t buflen = size;
-        buflen += relay_agent_information_length(server->agent_circuit_id, server->agent_remote_id) + 2;
-        assert_se(message = malloc(buflen));
-        memcpy(message, data, size);
-
-        server->fd = open("/dev/null", O_RDWR|O_CLOEXEC|O_NOCTTY);
-        assert_se(server->fd >= 0);
-
-        (void) dhcp_server_relay_message(server, (DHCPMessage *) message, size - sizeof(DHCPMessage), buflen);
-        return 0;
-}
index 5d2368cc9881a10810962dfcc4849ab1b5689e33..9b36f6edf2cf6380b7471e96b41259bc80b830e4 100644 (file)
@@ -145,9 +145,6 @@ executables += [
         network_fuzz_template + {
                 'sources' : files('fuzz-dhcp-server.c'),
         },
-        network_fuzz_template + {
-                'sources' : files('fuzz-dhcp-server-relay.c'),
-        },
         network_fuzz_template + {
                 'sources' : files('fuzz-lldp-rx.c'),
         },
index fc28469a86ccbf53c05b141a9bbe747f161bebe9..07f15ef6dc20c158168ceb00efac3fc18a51560d 100644 (file)
@@ -113,12 +113,6 @@ int sd_dhcp_server_is_running(sd_dhcp_server *server) {
         return !!server->receive_message;
 }
 
-int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server) {
-        assert_return(server, -EINVAL);
-
-        return in4_addr_is_set(&server->relay_target);
-}
-
 static sd_dhcp_server* dhcp_server_free(sd_dhcp_server *server) {
         assert(server);
 
@@ -142,9 +136,6 @@ static sd_dhcp_server* dhcp_server_free(sd_dhcp_server *server) {
         tlv_unref(server->extra_options);
         tlv_unref(server->vendor_options);
 
-        free(server->agent_circuit_id);
-        free(server->agent_remote_id);
-
         safe_close(server->lease_dir_fd);
         free(server->lease_file);
 
@@ -168,11 +159,9 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
                 .n_ref = 1,
                 .fd_raw = -EBADF,
                 .fd = -EBADF,
-                .fd_broadcast = -EBADF,
                 .address = htobe32(INADDR_ANY),
                 .netmask = htobe32(INADDR_ANY),
                 .ifindex = ifindex,
-                .bind_to_interface = true,
                 .default_lease_time = DHCP_DEFAULT_LEASE_TIME_USEC,
                 .max_lease_time = DHCP_MAX_LEASE_TIME_USEC,
                 .rapid_commit = true,
@@ -289,11 +278,9 @@ int sd_dhcp_server_stop(sd_dhcp_server *server) {
         running = sd_dhcp_server_is_running(server);
 
         server->receive_message = sd_event_source_disable_unref(server->receive_message);
-        server->receive_broadcast = sd_event_source_disable_unref(server->receive_broadcast);
 
         server->fd_raw = safe_close(server->fd_raw);
         server->fd = safe_close(server->fd);
-        server->fd_broadcast = safe_close(server->fd_broadcast);
 
         if (running)
                 log_dhcp_server(server, "STOPPED");
@@ -385,27 +372,21 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
         assert(message);
         assert(len >= sizeof(DHCPMessage));
 
-        if (server->bind_to_interface) {
-                msg.msg_control = &control;
-                msg.msg_controllen = sizeof(control);
+        msg.msg_control = &control;
+        msg.msg_controllen = sizeof(control);
 
-                cmsg = CMSG_FIRSTHDR(&msg);
-                assert(cmsg);
+        cmsg = CMSG_FIRSTHDR(&msg);
+        assert(cmsg);
 
-                cmsg->cmsg_level = IPPROTO_IP;
-                cmsg->cmsg_type = IP_PKTINFO;
-                cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+        cmsg->cmsg_level = IPPROTO_IP;
+        cmsg->cmsg_type = IP_PKTINFO;
+        cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
 
-                /* we attach source interface and address info to the message
-                   rather than binding the socket. This will be mostly useful
-                   when we gain support for arbitrary number of server addresses
-                 */
-                pktinfo = CMSG_TYPED_DATA(cmsg, struct in_pktinfo);
-                assert(pktinfo);
+        pktinfo = CMSG_TYPED_DATA(cmsg, struct in_pktinfo);
+        assert(pktinfo);
 
-                pktinfo->ipi_ifindex = server->ifindex;
-                pktinfo->ipi_spec_dst.s_addr = server->address;
-        }
+        pktinfo->ipi_ifindex = server->ifindex;
+        pktinfo->ipi_spec_dst.s_addr = server->address;
 
         if (sendmsg(server->fd, &msg, 0) < 0)
                 return -errno;
@@ -1000,83 +981,6 @@ static bool address_is_in_pool(sd_dhcp_server *server, be32_t address) {
         return true;
 }
 
-static int append_agent_information_option(sd_dhcp_server *server, DHCPMessage *message, size_t opt_length, size_t size) {
-        int r;
-        size_t offset;
-
-        assert(server);
-        assert(message);
-
-        r = dhcp_option_find_option(message->options, opt_length, SD_DHCP_OPTION_END, &offset);
-        if (r < 0)
-                return r;
-
-        r = dhcp_option_append(message, size, &offset, 0, SD_DHCP_OPTION_RELAY_AGENT_INFORMATION, 0, server);
-        if (r < 0)
-                return r;
-
-        r = dhcp_option_append(message, size, &offset, 0, SD_DHCP_OPTION_END, 0, NULL);
-        if (r < 0)
-                return r;
-        return offset;
-}
-
-static int dhcp_server_relay_message(sd_dhcp_server *server, DHCPMessage *message, size_t opt_length, size_t buflen) {
-        _cleanup_free_ DHCPPacket *packet = NULL;
-        int r;
-
-        assert(server);
-        assert(message);
-        assert(sd_dhcp_server_is_in_relay_mode(server));
-
-        if (message->hlen == 0 || message->hlen > sizeof(message->chaddr) || memeqzero(message->chaddr, message->hlen))
-                return log_dhcp_server_errno(server, SYNTHETIC_ERRNO(EBADMSG),
-                                             "(relay agent) received message without/invalid hardware address, discarding.");
-
-        if (message->op == BOOTREQUEST) {
-                log_dhcp_server(server, "(relay agent) BOOTREQUEST (0x%x)", be32toh(message->xid));
-                if (message->hops >= 16)
-                        return -ETIME;
-                message->hops++;
-
-                /* https://tools.ietf.org/html/rfc1542#section-4.1.1 */
-                if (message->giaddr == 0)
-                        message->giaddr = server->address;
-
-                if (server->agent_circuit_id || server->agent_remote_id) {
-                        r = append_agent_information_option(server, message, opt_length, buflen - sizeof(DHCPMessage));
-                        if (r < 0)
-                                return log_dhcp_server_errno(server, r, "could not append relay option: %m");
-                        opt_length = r;
-                }
-
-                return dhcp_server_send_udp(server, server->relay_target.s_addr, DHCP_PORT_SERVER, message, sizeof(DHCPMessage) + opt_length);
-        } else if (message->op == BOOTREPLY) {
-                log_dhcp_server(server, "(relay agent) BOOTREPLY (0x%x)", be32toh(message->xid));
-                if (message->giaddr != server->address)
-                        return log_dhcp_server_errno(server, SYNTHETIC_ERRNO(EBADMSG),
-                                                     "(relay agent) BOOTREPLY giaddr mismatch, discarding");
-
-                int message_type = dhcp_option_parse(message, sizeof(DHCPMessage) + opt_length, NULL, NULL, NULL);
-                if (message_type < 0)
-                        return message_type;
-
-                packet = malloc0(sizeof(DHCPPacket) + opt_length);
-                if (!packet)
-                        return -ENOMEM;
-                memcpy(&packet->dhcp, message, sizeof(DHCPMessage) + opt_length);
-
-                r = dhcp_option_remove_option(packet->dhcp.options, opt_length, SD_DHCP_OPTION_RELAY_AGENT_INFORMATION);
-                if (r > 0)
-                        opt_length = r;
-
-                bool l2_broadcast = requested_broadcast(message) || message_type == DHCP_NAK;
-                const be32_t destination = message_type == DHCP_NAK ? INADDR_ANY : message->ciaddr;
-                return dhcp_server_send(server, message->hlen, message->chaddr, destination, DHCP_PORT_CLIENT, packet, opt_length, l2_broadcast);
-        }
-        return -EBADMSG;
-}
-
 static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, be32_t address) {
         usec_t expiration;
         int r;
@@ -1315,15 +1219,6 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
         return 0;
 }
 
-static size_t relay_agent_information_length(const char* agent_circuit_id, const char* agent_remote_id) {
-        size_t sum = 0;
-        if (agent_circuit_id)
-                sum += 2 + strlen(agent_circuit_id);
-        if (agent_remote_id)
-                sum += 2 + strlen(agent_remote_id);
-        return sum;
-}
-
 static int server_receive_message(sd_event_source *s, int fd,
                                   uint32_t revents, void *userdata) {
         _cleanup_free_ DHCPMessage *message = NULL;
@@ -1351,10 +1246,6 @@ static int server_receive_message(sd_event_source *s, int fd,
         }
 
         size_t buflen = datagram_size;
-        if (sd_dhcp_server_is_in_relay_mode(server))
-                /* Preallocate the additional size for DHCP Relay Agent Information Option if needed */
-                buflen += relay_agent_information_length(server->agent_circuit_id, server->agent_remote_id) + 2;
-
         message = malloc0(buflen);
         if (!message)
                 return -ENOMEM;
@@ -1377,15 +1268,10 @@ static int server_receive_message(sd_event_source *s, int fd,
         if (info && info->ipi_ifindex != server->ifindex)
                 return 0;
 
-        if (sd_dhcp_server_is_in_relay_mode(server)) {
-                r = dhcp_server_relay_message(server, message, len - sizeof(DHCPMessage), buflen);
-                if (r < 0)
-                        log_dhcp_server_errno(server, r, "Couldn't relay message, ignoring: %m");
-        } else {
-                r = dhcp_server_handle_message(server, message, (size_t) len, TRIPLE_TIMESTAMP_FROM_CMSG(&msg));
-                if (r < 0)
-                        log_dhcp_server_errno(server, r, "Couldn't process incoming message, ignoring: %m");
-        }
+        r = dhcp_server_handle_message(server, message, (size_t) len, TRIPLE_TIMESTAMP_FROM_CMSG(&msg));
+        if (r < 0)
+                log_dhcp_server_errno(server, r, "Couldn't process incoming message, ignoring: %m");
+
         return 0;
 }
 
@@ -1424,10 +1310,7 @@ int sd_dhcp_server_start(sd_dhcp_server *server) {
         }
         server->fd_raw = r;
 
-        if (server->bind_to_interface)
-                r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER, -1);
-        else
-                r = dhcp_network_bind_udp_socket(0, server->address, DHCP_PORT_SERVER, -1);
+        r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER, -1);
         if (r < 0)
                 goto on_error;
         server->fd = r;
@@ -1443,25 +1326,6 @@ int sd_dhcp_server_start(sd_dhcp_server *server) {
         if (r < 0)
                 goto on_error;
 
-        if (!server->bind_to_interface) {
-                r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_BROADCAST, DHCP_PORT_SERVER, -1);
-                if (r < 0)
-                        goto on_error;
-
-                server->fd_broadcast = r;
-
-                r = sd_event_add_io(server->event, &server->receive_broadcast,
-                                    server->fd_broadcast, EPOLLIN,
-                                    server_receive_message, server);
-                if (r < 0)
-                        goto on_error;
-
-                r = sd_event_source_set_priority(server->receive_broadcast,
-                                                 server->event_priority);
-                if (r < 0)
-                        goto on_error;
-        }
-
         r = dhcp_server_load_leases(server);
         if (r < 0)
                 log_dhcp_server_errno(server, r, "Failed to load lease file %s, ignoring: %m", strna(server->lease_file));
@@ -1490,18 +1354,6 @@ int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
         return r;
 }
 
-int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server *server, int enabled) {
-        assert_return(server, -EINVAL);
-        assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
-
-        if (!!enabled == server->bind_to_interface)
-                return 0;
-
-        server->bind_to_interface = enabled;
-
-        return 1;
-}
-
 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) {
         int r;
 
@@ -1649,46 +1501,6 @@ int sd_dhcp_server_set_callback(sd_dhcp_server *server, sd_dhcp_server_callback_
         return 0;
 }
 
-int sd_dhcp_server_set_relay_target(sd_dhcp_server *server, const struct in_addr *address) {
-        assert_return(server, -EINVAL);
-        assert_return(address, -EINVAL);
-        assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
-
-        if (memcmp(address, &server->relay_target, sizeof(struct in_addr)) == 0)
-                return 0;
-
-        server->relay_target = *address;
-        return 1;
-}
-
-int sd_dhcp_server_set_relay_agent_information(
-                sd_dhcp_server *server,
-                const char *agent_circuit_id,
-                const char *agent_remote_id) {
-        _cleanup_free_ char *circuit_id_dup = NULL, *remote_id_dup = NULL;
-
-        assert_return(server, -EINVAL);
-
-        if (relay_agent_information_length(agent_circuit_id, agent_remote_id) > UINT8_MAX)
-                return -ENOBUFS;
-
-        if (agent_circuit_id) {
-                circuit_id_dup = strdup(agent_circuit_id);
-                if (!circuit_id_dup)
-                        return -ENOMEM;
-        }
-
-        if (agent_remote_id) {
-                remote_id_dup = strdup(agent_remote_id);
-                if (!remote_id_dup)
-                        return -ENOMEM;
-        }
-
-        free_and_replace(server->agent_circuit_id, circuit_id_dup);
-        free_and_replace(server->agent_remote_id, remote_id_dup);
-        return 0;
-}
-
 int sd_dhcp_server_set_lease_file(sd_dhcp_server *server, int dir_fd, const char *path) {
         int r;
 
index 4da4fdb116b5b8a2c673bfe025e135ddef55bf54..34263f044d0829fa31096348df182be227d22a96 100644 (file)
@@ -22,7 +22,7 @@ static void test_pool(struct in_addr *address, unsigned size, int ret) {
                 ASSERT_RETURN_IS_CRITICAL(false, ASSERT_ERROR(sd_dhcp_server_configure_pool(server, address, 8, 0, size), -ret));
 }
 
-static int test_basic(bool bind_to_interface) {
+static int test_basic(void) {
         _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         struct in_addr address_lo = {
@@ -33,14 +33,13 @@ static int test_basic(bool bind_to_interface) {
         };
         int r;
 
-        log_debug("/* %s(bind_to_interface=%s) */", __func__, yes_no(bind_to_interface));
+        log_debug("/* %s */", __func__);
 
         ASSERT_OK(sd_event_new(&event));
 
         /* attach to loopback interface */
         ASSERT_OK(sd_dhcp_server_new(&server, 1));
         ASSERT_NOT_NULL(server);
-        server->bind_to_interface = bind_to_interface;
 
         ASSERT_OK(sd_dhcp_server_attach_event(server, event, 0));
         ASSERT_RETURN_EXPECTED(ASSERT_ERROR(sd_dhcp_server_attach_event(server, event, 0), EBUSY));
@@ -410,13 +409,9 @@ int main(int argc, char *argv[]) {
         test_static_lease();
         test_domain_name();
 
-        r = test_basic(true);
-        if (r < 0)
-                return log_tests_skipped_errno(r, "cannot start dhcp server(bound to interface)");
-
-        r = test_basic(false);
+        r = test_basic();
         if (r < 0)
-                return log_tests_skipped_errno(r, "cannot start dhcp server(non-bound to interface)");
+                return log_tests_skipped_errno(r, "cannot start dhcp server");
 
         test_message_handler();
 
index 1fb7d2e9ee60ef99386f5024b5c914651902844b..8c3dbab9b42384229b189d0b3417d7f72d503e48 100644 (file)
@@ -57,7 +57,6 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, const struct in_addr *
 int sd_dhcp_server_set_boot_server_address(sd_dhcp_server *server, const struct in_addr *address);
 int sd_dhcp_server_set_boot_server_name(sd_dhcp_server *server, const char *name);
 int sd_dhcp_server_set_boot_filename(sd_dhcp_server *server, const char *filename);
-int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server *server, int enabled);
 int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz);
 int sd_dhcp_server_set_domain_name(sd_dhcp_server *server, const char *domain_name);
 int sd_dhcp_server_set_router(sd_dhcp_server *server, const struct in_addr *router);
@@ -90,10 +89,6 @@ int sd_dhcp_server_set_rapid_commit(sd_dhcp_server *server, int enabled);
 
 int sd_dhcp_server_forcerenew(sd_dhcp_server *server);
 
-int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server);
-int sd_dhcp_server_set_relay_target(sd_dhcp_server *server, const struct in_addr* address);
-int sd_dhcp_server_set_relay_agent_information(sd_dhcp_server *server, const char* circuit_id, const char* remote_id);
-
 int sd_dhcp_server_get_lease_address_by_name(sd_dhcp_server *server, const char *name, struct in_addr *ret);
 
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server, sd_dhcp_server_unref);