From: Michael Tremer Date: Fri, 28 Nov 2025 17:58:19 +0000 (+0000) Subject: daemon: Create a single, global Netlink Route socket X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c13297d328044fdc59be72116e78ab3d294779d3;p=collecty.git daemon: Create a single, global Netlink Route socket Signed-off-by: Michael Tremer --- diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 4bc1943..801f102 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -26,6 +26,13 @@ #include #include +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE +# include +# include +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ + #include "bus.h" #include "ctx.h" #include "daemon.h" @@ -71,6 +78,15 @@ struct td_daemon { // udev struct udev* udev; + + // Netlink Sockets +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE + struct { + struct nl_sock* route; + } nl_sockets; +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ }; static int td_daemon_init(sd_event_source* source, void* data) { @@ -242,6 +258,14 @@ static int td_daemon_setup_udev(td_daemon* self) { } static void td_daemon_free(td_daemon* self) { + // Free Netlink Sockets +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE + if (self->nl_sockets.route) + nl_socket_free(self->nl_sockets.route); +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ + if (self->events.memory_pressure) sd_event_source_unref(self->events.memory_pressure); if (self->events.sigchld) @@ -394,6 +418,42 @@ int td_daemon_flush_source( return td_queue_flush_source(self->queue, source, object); } +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE +struct nl_sock* td_daemon_get_nl_route_socket(td_daemon* self) { + int r; + + // Create socket if not already done + if (!self->nl_sockets.route) { + // Allocate a new socket + self->nl_sockets.route = nl_socket_alloc(); + if (!self->nl_sockets.route) { + ERROR(self->ctx, "Failed to allocate a new Netlink socket: %m\n"); + goto ERROR; + } + + // Select routing + r = nl_connect(self->nl_sockets.route, NETLINK_ROUTE); + if (r < 0) { + ERROR(self->ctx, "Failed to select routing: %s\n", nl_geterror(r)); + errno = ENOTSUP; + goto ERROR; + } + } + + return self->nl_sockets.route; + +ERROR: + if (self->nl_sockets.route) { + nl_socket_free(self->nl_sockets.route); + self->nl_sockets.route = NULL; + } + + return NULL; +} +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ + static int td_daemon_bus_version(sd_bus* bus, const char* path, const char* interface, const char* property, sd_bus_message* reply, void* data, sd_bus_error* error) { return sd_bus_message_append(reply, "s", PACKAGE_VERSION); diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h index a34e712..574af63 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -24,6 +24,13 @@ #include #include +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE +# include +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ + + typedef struct td_daemon td_daemon; #include "bus.h" @@ -51,6 +58,12 @@ int td_daemon_submit_metrics(td_daemon* self, td_metrics* metrics); int td_daemon_flush_source( td_daemon* self, td_source* source, const char* object); +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE +struct nl_sock* td_daemon_get_nl_route_socket(td_daemon* self); +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ + // Bus extern const td_bus_implementation daemon_bus_impl; diff --git a/src/daemon/source.c b/src/daemon/source.c index 6cbbe2e..678ca5b 100644 --- a/src/daemon/source.c +++ b/src/daemon/source.c @@ -547,6 +547,10 @@ struct udev* td_source_get_udev(td_source* self) { return td_daemon_get_udev(self->daemon); } +struct nl_sock* td_source_get_nl_route_socket(td_source* self) { + return td_daemon_get_nl_route_socket(self->daemon); +} + unsigned int td_source_num_data_sources(td_source* self) { unsigned int num_sources = 0; diff --git a/src/daemon/source.h b/src/daemon/source.h index e66b881..9df02fc 100644 --- a/src/daemon/source.h +++ b/src/daemon/source.h @@ -23,6 +23,12 @@ #include +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE +# include +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ + typedef struct td_source td_source; #include "args.h" @@ -85,6 +91,12 @@ int td_source_disable(td_source* self); struct udev* td_source_get_udev(td_source* self); +#ifdef HAVE_LIBNL3 +# ifdef HAVE_LIBNL3_ROUTE +struct nl_sock* td_source_get_nl_route_socket(td_source* self); +# endif /* HAVE_LIBNL3_ROUTE */ +#endif /* HAVE_LIBNL3 */ + unsigned int td_source_num_data_sources(td_source* self); const td_rrd_ds* td_source_get_data_sources(td_source* self); diff --git a/src/daemon/sources/interfaces.c b/src/daemon/sources/interfaces.c index 263f990..a218313 100644 --- a/src/daemon/sources/interfaces.c +++ b/src/daemon/sources/interfaces.c @@ -33,58 +33,11 @@ #include "../time.h" #include "interfaces.h" -// Netlink Socket -static struct nl_sock* sock = NULL; - typedef struct interfaces_stats { const char* field; rtnl_link_stat_id_t id; } interfaces_stats; -static int interfaces_init(td_ctx* ctx, td_source* source) { - int r; - - // Don't open the socket again - if (sock) - return 0; - - // Create a new netlink socket - sock = nl_socket_alloc(); - if (!sock) { - ERROR(ctx, "Failed to create a netlink socket: %m\n"); - r = -errno; - goto ERROR; - } - - // Select routing - r = nl_connect(sock, NETLINK_ROUTE); - if (r < 0) { - ERROR(ctx, "Failed to select routing: %s\n", nl_geterror(r)); - r = -ENOTSUP; - goto ERROR; - } - - // Success - return 0; - -ERROR: - if (sock) { - nl_socket_free(sock); - sock = NULL; - } - - return r; -} - -static int interfaces_free(td_ctx* ctx) { - if (sock) { - nl_socket_free(sock); - sock = NULL; - } - - return 0; -} - static const interfaces_stats stats[] = { // Packets Received/Sent { "rx_packets", RTNL_LINK_RX_PACKETS }, @@ -188,6 +141,11 @@ static int interfaces_heartbeat(td_ctx* ctx, td_source* source) { struct nl_cache* links = NULL; int r; + // Fetch the Netlink socket + struct nl_sock* sock = td_source_get_nl_route_socket(source); + if (!sock) + return -errno; + // Fetch the links r = rtnl_link_alloc_cache(sock, AF_UNSPEC, &links); if (r < 0) { @@ -272,7 +230,5 @@ const td_source_impl interfaces_source = { }, // Methods - .init = interfaces_init, - .free = interfaces_free, .heartbeat = interfaces_heartbeat, }; diff --git a/src/daemon/sources/legacy-gateway-latency4.c b/src/daemon/sources/legacy-gateway-latency4.c index 5226bec..2040d48 100644 --- a/src/daemon/sources/legacy-gateway-latency4.c +++ b/src/daemon/sources/legacy-gateway-latency4.c @@ -34,9 +34,8 @@ #include "../time.h" #include "legacy-gateway-latency4.h" -static int fetch_default_gateway(td_ctx* ctx, +static int fetch_default_gateway(td_ctx* ctx, td_source* source, char* address, size_t length, unsigned int* type) { - struct nl_sock* sock = NULL; struct nl_cache* routes = NULL; struct rtnl_route* route = NULL; struct nl_cache* links = NULL; @@ -46,21 +45,10 @@ static int fetch_default_gateway(td_ctx* ctx, int ifindex = -1; int r; - // Create a new netlink socket - sock = nl_socket_alloc(); - if (!sock) { - ERROR(ctx, "Failed to create a netlink socket: %m\n"); - r = -errno; - goto ERROR; - } - - // Select routing - r = nl_connect(sock, NETLINK_ROUTE); - if (r < 0) { - ERROR(ctx, "Failed to select routing: %s\n", nl_geterror(r)); - r = -ENOTSUP; - goto ERROR; - } + // Fetch the Netlink socket + struct nl_sock* sock = td_source_get_nl_route_socket(source); + if (!sock) + return -errno; // Fetch the route cache r = rtnl_route_alloc_cache(sock, AF_INET, 0, &routes); @@ -125,8 +113,6 @@ ERROR: nl_cache_free(routes); if (links) nl_cache_free(links); - if (sock) - nl_socket_free(sock); return r; } @@ -216,7 +202,7 @@ static int legacy_gateway_latency4_heartbeat(td_ctx* ctx, td_source* source) { int r; // Fetch the IP address of the default gateway - r = fetch_default_gateway(ctx, address, sizeof(address), &type); + r = fetch_default_gateway(ctx, source, address, sizeof(address), &type); if (r < 0) return r;