From: Yu Watanabe Date: Sun, 3 May 2026 23:43:41 +0000 (+0900) Subject: sd-dhcp-server: drop legacy DHCP relay mode X-Git-Tag: v261-rc1~39^2~1 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=54c97ce6a478bdaa8a4fe88450696fd51fdeaa8c;p=thirdparty%2Fsystemd.git sd-dhcp-server: drop legacy DHCP relay mode --- diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c index c5e8b297944..7ad203f183d 100644 --- a/src/libsystemd-network/dhcp-option.c +++ b/src/libsystemd-network/dhcp-option.c @@ -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, ¤t_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, ¤t_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); } diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index a8e2cbf5c70..d4caae66d42 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -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 index b2c881c0677..00000000000 --- a/src/libsystemd-network/fuzz-dhcp-server-relay.c +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include - -#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; -} diff --git a/src/libsystemd-network/meson.build b/src/libsystemd-network/meson.build index 5d2368cc988..9b36f6edf2c 100644 --- a/src/libsystemd-network/meson.build +++ b/src/libsystemd-network/meson.build @@ -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'), }, diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index fc28469a86c..07f15ef6dc2 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -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; diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index 4da4fdb116b..34263f044d0 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -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(); diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index 1fb7d2e9ee6..8c3dbab9b42 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -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); diff --git a/test/fuzz/fuzz-dhcp-server-relay/sample1 b/test/fuzz/fuzz-dhcp-relay/sample1 similarity index 100% rename from test/fuzz/fuzz-dhcp-server-relay/sample1 rename to test/fuzz/fuzz-dhcp-relay/sample1 diff --git a/test/fuzz/fuzz-dhcp-server-relay/sample2 b/test/fuzz/fuzz-dhcp-relay/sample2 similarity index 100% rename from test/fuzz/fuzz-dhcp-server-relay/sample2 rename to test/fuzz/fuzz-dhcp-relay/sample2 diff --git a/test/fuzz/fuzz-dhcp-server-relay/too-large-packet b/test/fuzz/fuzz-dhcp-relay/too-large-packet similarity index 100% rename from test/fuzz/fuzz-dhcp-server-relay/too-large-packet rename to test/fuzz/fuzz-dhcp-relay/too-large-packet