Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions include/rtaco/core/nl_control.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -87,27 +87,27 @@ public:
* @param address IPv6/IPv4 address bytes (16-byte span).
* @return Expected void or error on failure.
*/
auto probe_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto probe_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> void_result_t;

/** @brief Flush a neighbour entry (synchronous). */
auto flush_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto flush_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> void_result_t;

/** @brief Get a neighbor entry synchronously. */
auto get_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto get_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> neighbor_result_t;

/** @brief Asynchronously probe a neighbor. */
auto async_probe_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto async_probe_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> boost::asio::awaitable<void_result_t>;

/** @brief Asynchronously flush a neighbor. */
auto async_flush_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto async_flush_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> boost::asio::awaitable<void_result_t>;

/** @brief Asynchronously get a neighbor. */
auto async_get_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto async_get_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> boost::asio::awaitable<neighbor_result_t>;

/** @brief Stop ongoing operations and release control resources. */
Expand All @@ -121,13 +121,13 @@ private:
auto async_dump_links_impl() -> boost::asio::awaitable<link_list_result_t>;
auto async_dump_neighbors_impl() -> boost::asio::awaitable<neighbor_list_result>;

auto async_probe_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16> address)
auto async_probe_neighbor_impl(uint32_t ifindex, std::span<uint8_t, 16> address)
-> boost::asio::awaitable<void_result_t>;

auto async_flush_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16> address)
auto async_flush_neighbor_impl(uint32_t ifindex, std::span<uint8_t, 16> address)
-> boost::asio::awaitable<void_result_t>;

auto async_get_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16> address)
auto async_get_neighbor_impl(uint32_t ifindex, std::span<uint8_t, 16> address)
-> boost::asio::awaitable<neighbor_result_t>;

boost::asio::io_context& io_;
Expand Down
7 changes: 3 additions & 4 deletions include/rtaco/core/nl_signal.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/use_future.hpp>
Expand Down Expand Up @@ -139,9 +138,9 @@ public:
std::apply(slot_fn, *args_pack);
};

boost::asio::co_spawn(executor, std::move(coroutine),
boost::asio::detached);
return detail::make_ready_shared_future();
auto future = boost::asio::co_spawn(executor, std::move(coroutine),
boost::asio::use_future);
return future.share();
}

auto coroutine = [slot_fn, args_pack,
Expand Down
2 changes: 1 addition & 1 deletion include/rtaco/tasks/nl_neighbor_flush_task.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public:
* @param sequence Netlink message sequence number.
* @param address Address bytes to identify the neighbor.
*/
NeighborFlushTask(SocketGuard& socket_guard, uint16_t ifindex, uint32_t sequence,
NeighborFlushTask(SocketGuard& socket_guard, uint32_t ifindex, uint32_t sequence,
std::span<uint8_t, 16> address);

/** @brief Prepare the netlink request to flush the neighbor entry. */
Expand Down
2 changes: 1 addition & 1 deletion include/rtaco/tasks/nl_neighbor_get_task.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public:
* @param sequence Netlink message sequence number.
* @param address Address bytes identifying the neighbor.
*/
NeighborGetTask(SocketGuard& socket_guard, uint16_t uint16_t, uint32_t sequence,
NeighborGetTask(SocketGuard& socket_guard, uint32_t ifindex, uint32_t sequence,
std::span<uint8_t, 16> address);

/** @brief Prepare the netlink request to get the neighbor. */
Expand Down
2 changes: 1 addition & 1 deletion include/rtaco/tasks/nl_neighbor_probe_task.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public:
* @param sequence Netlink message sequence number.
* @param address Address bytes to probe.
*/
NeighborProbeTask(SocketGuard& socket_guard, uint16_t uint16_t, uint32_t sequence,
NeighborProbeTask(SocketGuard& socket_guard, uint32_t ifindex, uint32_t sequence,
std::span<uint8_t, 16> address);

/** @brief Prepare the netlink request to probe the neighbor. */
Expand Down
24 changes: 20 additions & 4 deletions include/rtaco/tasks/nl_request_task.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@
namespace llmx {
namespace rtaco {

namespace detail {

inline auto validate_received_size(size_t bytes, size_t capacity)
-> std::expected<void, std::error_code> {
if (bytes >= capacity) {
return std::unexpected(std::make_error_code(std::errc::message_size));
}

return {};
}

} // namespace detail

template<typename Derived, typename Result>
concept request_behavior =
requires(Derived& derived, const Derived& const_derived, const nlmsghdr& header) {
Expand All @@ -48,7 +61,7 @@ class RequestTask {
std::array<uint8_t, MAX_RESPONSE_BYTES> receive_buffer_;

SocketGuard& socket_guard_;
uint16_t ifindex_;
uint32_t ifindex_;
uint32_t sequence_;

public:
Expand All @@ -58,7 +71,7 @@ public:
* @param ifindex Interface index associated with the request.
* @param sequence Netlink sequence number for messages.
*/
RequestTask(SocketGuard& socket_guard, uint16_t ifindex, uint32_t sequence) noexcept
RequestTask(SocketGuard& socket_guard, uint32_t ifindex, uint32_t sequence) noexcept
: socket_guard_{socket_guard}
, ifindex_{ifindex}
, sequence_{sequence} {}
Expand Down Expand Up @@ -90,7 +103,7 @@ protected:
return sequence_;
}

auto ifindex() const noexcept -> uint16_t {
auto ifindex() const noexcept -> uint32_t {
return ifindex_;
}

Expand Down Expand Up @@ -136,7 +149,10 @@ private:
std::error_code{ec.value(), std::generic_category()});
}

if (bytes >= receive_buffer_.size()) {
if (auto size_ok = detail::validate_received_size(
bytes, receive_buffer_.size());
!size_ok) {
co_return std::unexpected(size_ok.error());
}

auto remaining = static_cast<unsigned int>(bytes);
Expand Down
18 changes: 9 additions & 9 deletions src/core/nl_control.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -95,43 +95,43 @@ auto Control::async_dump_neighbors()
asio::use_awaitable);
}

auto Control::flush_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::flush_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> std::expected<void, std::error_code> {
auto future = asio::co_spawn(strand_, async_flush_neighbor_impl(ifindex, address),
asio::use_future);

return future.get();
}

auto Control::async_flush_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::async_flush_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> asio::awaitable<std::expected<void, std::error_code>> {
co_return co_await asio::co_spawn(strand_,
async_flush_neighbor_impl(ifindex, address), asio::use_awaitable);
}

auto Control::probe_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::probe_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> std::expected<void, std::error_code> {
auto future = asio::co_spawn(strand_, async_probe_neighbor_impl(ifindex, address),
asio::use_future);

return future.get();
}

auto Control::async_probe_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::async_probe_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> asio::awaitable<std::expected<void, std::error_code>> {
co_return co_await asio::co_spawn(strand_,
async_probe_neighbor_impl(ifindex, address), asio::use_awaitable);
}

auto Control::get_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::get_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> std::expected<NeighborEvent, std::error_code> {
auto future = asio::co_spawn(strand_, async_get_neighbor_impl(ifindex, address),
asio::use_future);

return future.get();
}

auto Control::async_get_neighbor(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::async_get_neighbor(uint32_t ifindex, std::span<uint8_t, 16> address)
-> asio::awaitable<std::expected<NeighborEvent, std::error_code>> {
co_return co_await asio::co_spawn(strand_, async_get_neighbor_impl(ifindex, address),
asio::use_awaitable);
Expand Down Expand Up @@ -209,7 +209,7 @@ auto Control::async_dump_links_impl() -> asio::awaitable<link_list_result_t> {
co_return co_await task.async_run();
}

auto Control::async_probe_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::async_probe_neighbor_impl(uint32_t ifindex, std::span<uint8_t, 16> address)
-> asio::awaitable<void_result_t> {
if (auto gate_error = co_await acquire_socket_token(); gate_error) {
co_return std::unexpected{gate_error};
Expand All @@ -225,7 +225,7 @@ auto Control::async_probe_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16>
co_return co_await task.async_run();
}

auto Control::async_flush_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::async_flush_neighbor_impl(uint32_t ifindex, std::span<uint8_t, 16> address)
-> asio::awaitable<void_result_t> {
if (auto gate_error = co_await acquire_socket_token(); gate_error) {
co_return std::unexpected{gate_error};
Expand All @@ -241,7 +241,7 @@ auto Control::async_flush_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16>
co_return co_await task.async_run();
}

auto Control::async_get_neighbor_impl(uint16_t ifindex, std::span<uint8_t, 16> address)
auto Control::async_get_neighbor_impl(uint32_t ifindex, std::span<uint8_t, 16> address)
-> asio::awaitable<neighbor_result_t> {
if (auto gate_error = co_await acquire_socket_token(); gate_error) {
co_return std::unexpected{gate_error};
Expand Down
23 changes: 12 additions & 11 deletions src/core/nl_listener.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <iostream>
#include <span>
#include <system_error>
#include <unordered_map>

#include <boost/asio/error.hpp>
#include <boost/system/error_code.hpp>
Expand Down Expand Up @@ -136,17 +137,17 @@ void Listener::process_messages(std::span<const uint8_t> data) {
void Listener::handle_message(const nlmsghdr& header) {
using HandlerEntry12 = std::pair<size_t, void (Listener::*)(const nlmsghdr&)>;

static std::unordered_map<int, HandlerEntry12> handlers;

handlers[RTM_NEWLINK] = {sizeof(ifinfomsg), &Listener::handle_link_message};
handlers[RTM_DELLINK] = {sizeof(ifinfomsg), &Listener::handle_link_message};
handlers[RTM_NEWADDR] = {sizeof(ifaddrmsg), &Listener::handle_address_message};
handlers[RTM_DELADDR] = {sizeof(ifaddrmsg), &Listener::handle_address_message};
handlers[RTM_NEWROUTE] = {sizeof(rtmsg), &Listener::handle_route_message};
handlers[RTM_DELROUTE] = {sizeof(rtmsg), &Listener::handle_route_message};
handlers[RTM_NEWNEIGH] = {sizeof(ndmsg), &Listener::handle_neighbor_message};
handlers[RTM_DELNEIGH] = {sizeof(ndmsg), &Listener::handle_neighbor_message};
handlers[NLMSG_ERROR] = {sizeof(nlmsgerr), &Listener::handle_error_message};
static const std::unordered_map<int, HandlerEntry12> handlers = {
{RTM_NEWLINK, {sizeof(ifinfomsg), &Listener::handle_link_message}},
{RTM_DELLINK, {sizeof(ifinfomsg), &Listener::handle_link_message}},
{RTM_NEWADDR, {sizeof(ifaddrmsg), &Listener::handle_address_message}},
{RTM_DELADDR, {sizeof(ifaddrmsg), &Listener::handle_address_message}},
{RTM_NEWROUTE, {sizeof(rtmsg), &Listener::handle_route_message}},
{RTM_DELROUTE, {sizeof(rtmsg), &Listener::handle_route_message}},
{RTM_NEWNEIGH, {sizeof(ndmsg), &Listener::handle_neighbor_message}},
{RTM_DELNEIGH, {sizeof(ndmsg), &Listener::handle_neighbor_message}},
{NLMSG_ERROR, {sizeof(nlmsgerr), &Listener::handle_error_message}},
};

if (!handlers.contains(header.nlmsg_type)) {
return;
Expand Down
3 changes: 2 additions & 1 deletion src/tasks/nl_neighbor_dump_task.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/rtnetlink.h>

#include "rtaco/events/nl_neighbor_event.hxx"
#include "rtaco/core/nl_common.hxx"
#include "rtaco/tasks/nl_neighbor_task.hxx"

namespace llmx {
Expand Down Expand Up @@ -53,7 +54,7 @@ auto NeighborDumpTask::handle_done()

auto NeighborDumpTask::handle_error(const nlmsghdr& header)
-> std::expected<NeighborEventList, std::error_code> {
const auto* err = reinterpret_cast<const nlmsgerr*>(NLMSG_DATA(&header));
const auto* err = checked_nlmsgerr(header);
const auto code = err != nullptr ? -err->error : EPROTO;
const auto error_code = std::make_error_code(static_cast<std::errc>(code));

Expand Down
5 changes: 3 additions & 2 deletions src/tasks/nl_neighbor_flush_task.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
#include <linux/rtnetlink.h>

#include "rtaco/tasks/nl_neighbor_task.hxx"
#include "rtaco/core/nl_common.hxx"

namespace llmx {
namespace rtaco {

NeighborFlushTask::NeighborFlushTask(SocketGuard& socket_guard, uint16_t ifindex,
NeighborFlushTask::NeighborFlushTask(SocketGuard& socket_guard, uint32_t ifindex,
uint32_t sequence, std::span<uint8_t, 16> address)
: NeighborTask{socket_guard, ifindex, sequence} {
for (std::size_t i = 0; i < 16; ++i) {
Expand All @@ -42,7 +43,7 @@ auto NeighborFlushTask::process_message(const nlmsghdr& header)

auto NeighborFlushTask::handle_error(const nlmsghdr& header)
-> std::expected<void, std::error_code> {
const auto* err = reinterpret_cast<const nlmsgerr*>(NLMSG_DATA(&header));
const auto* err = checked_nlmsgerr(header);
const auto code = err != nullptr ? -err->error : EPROTO;
const auto error_code = std::make_error_code(static_cast<std::errc>(code));

Expand Down
5 changes: 3 additions & 2 deletions src/tasks/nl_neighbor_get_task.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
#include <linux/rtnetlink.h>

#include "rtaco/events/nl_neighbor_event.hxx"
#include "rtaco/core/nl_common.hxx"
#include "rtaco/tasks/nl_neighbor_task.hxx"

namespace llmx {
namespace rtaco {

NeighborGetTask::NeighborGetTask(SocketGuard& socket_guard, uint16_t ifindex,
NeighborGetTask::NeighborGetTask(SocketGuard& socket_guard, uint32_t ifindex,
uint32_t sequence, std::span<uint8_t, 16> address)
: NeighborTask{socket_guard, ifindex, sequence} {
for (std::size_t i = 0; i < 16; ++i) {
Expand Down Expand Up @@ -50,7 +51,7 @@ auto NeighborGetTask::handle_done() -> std::expected<NeighborEvent, std::error_c

auto NeighborGetTask::handle_error(const nlmsghdr& header)
-> std::expected<NeighborEvent, std::error_code> {
const auto* err = reinterpret_cast<const nlmsgerr*>(NLMSG_DATA(&header));
const auto* err = checked_nlmsgerr(header);
const auto code = err != nullptr ? -err->error : EPROTO;
const auto error_code = std::make_error_code(static_cast<std::errc>(code));

Expand Down
7 changes: 4 additions & 3 deletions src/tasks/nl_neighbor_probe_task.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
#include <linux/rtnetlink.h>

#include "rtaco/tasks/nl_neighbor_task.hxx"
#include "rtaco/core/nl_common.hxx"

namespace llmx {
namespace rtaco {

NeighborProbeTask::NeighborProbeTask(SocketGuard& socket_guard, uint16_t uint16_t,
NeighborProbeTask::NeighborProbeTask(SocketGuard& socket_guard, uint32_t ifindex,
uint32_t sequence, std::span<uint8_t, 16> address)
: NeighborTask{socket_guard, uint16_t, sequence} {
: NeighborTask{socket_guard, ifindex, sequence} {
for (std::size_t i = 0; i < 16; ++i) {
address_[i] = address[i];
}
Expand All @@ -44,7 +45,7 @@ auto NeighborProbeTask::process_message(const nlmsghdr& header)

auto NeighborProbeTask::handle_error(const nlmsghdr& header)
-> std::expected<void, std::error_code> {
const auto* err = reinterpret_cast<const nlmsgerr*>(NLMSG_DATA(&header));
const auto* err = checked_nlmsgerr(header);
const auto code = err != nullptr ? -err->error : EPROTO;
const auto error_code = std::make_error_code(static_cast<std::errc>(code));

Expand Down
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ FetchContent_MakeAvailable(googletest)
add_executable(test_rtaco
test_signal.cpp
test_requesttask_compile.cpp
test_requesttask.cpp
test_socket.cpp
test_control.cpp
test_nl_common.cpp
test_neighbor_tasks.cpp
)

set(rtaco_test_sources)
Expand Down
Loading
Loading