--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <sys/socket.h>
+
+#include "sd-event.h"
+
+#include "dhcp-relay-internal.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "in-addr-util.h"
+#include "iovec-util.h"
+#include "tests.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ union in_addr_union a;
+
+ fuzz_setup_logging();
+
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+ ASSERT_OK(sd_event_new(&e));
+
+ _cleanup_(sd_dhcp_relay_unrefp) sd_dhcp_relay *relay = NULL;
+ ASSERT_OK(sd_dhcp_relay_new(&relay));
+ ASSERT_OK(sd_dhcp_relay_attach_event(relay, e, SD_EVENT_PRIORITY_NORMAL));
+ ASSERT_OK(in_addr_from_string(AF_INET, "198.51.100.1", &a));
+ ASSERT_OK(sd_dhcp_relay_set_server_address(relay, &a.in));
+ ASSERT_OK(sd_dhcp_relay_set_remote_id(relay, &IOVEC_MAKE_STRING("test-remote-id")));
+ ASSERT_OK(sd_dhcp_relay_set_server_identifier_override(relay, true));
+
+ _cleanup_(sd_dhcp_relay_interface_unrefp) sd_dhcp_relay_interface *upstream = NULL;
+ ASSERT_OK(sd_dhcp_relay_add_interface(relay, 4242, /* is_upstream= */ true, &upstream));
+ ASSERT_OK(sd_dhcp_relay_interface_set_ifname(upstream, "test-upstream"));
+ ASSERT_OK(in_addr_from_string(AF_INET, "198.51.100.2", &a));
+ ASSERT_OK(sd_dhcp_relay_interface_set_address(upstream, &a.in, 24));
+
+ _cleanup_close_pair_ int upstream_fd[2] = EBADF_PAIR;
+ ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, upstream_fd));
+ upstream->socket_fd = TAKE_FD(upstream_fd[0]);
+ ASSERT_OK(sd_dhcp_relay_interface_start(upstream));
+
+ _cleanup_(sd_dhcp_relay_interface_unrefp) sd_dhcp_relay_interface *downstream = NULL;
+ ASSERT_OK(sd_dhcp_relay_add_interface(relay, 4343, /* is_upstream= */ false, &downstream));
+ ASSERT_OK(sd_dhcp_relay_interface_set_ifname(downstream, "test-downstream"));
+ ASSERT_OK(in_addr_from_string(AF_INET, "192.0.2.1", &a));
+ ASSERT_OK(sd_dhcp_relay_interface_set_address(downstream, &a.in, 24));
+
+ ASSERT_OK(in_addr_from_string(AF_INET, "203.0.113.1", &a));
+ ASSERT_OK(sd_dhcp_relay_downstream_set_gateway_address(downstream, &a.in));
+ ASSERT_OK(sd_dhcp_relay_downstream_set_circuit_id(downstream, &IOVEC_MAKE_STRING("test-circuit-id")));
+ ASSERT_OK(sd_dhcp_relay_downstream_set_virtual_subnet_selection(downstream, &IOVEC_MAKE_STRING("test-virtual-net")));
+
+ _cleanup_close_pair_ int downstream_fd[2] = EBADF_PAIR;
+ ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, downstream_fd));
+ downstream->socket_fd = TAKE_FD(downstream_fd[0]);
+ ASSERT_OK(sd_dhcp_relay_interface_start(downstream));
+
+ (void) downstream_process_message(downstream, &IOVEC_MAKE(data, size), /* pktinfo= */ NULL);
+ (void) upstream_process_message(upstream, &IOVEC_MAKE(data, size), /* pktinfo= */ NULL);
+
+ return 0;
+}