From 9a2036193d3af3aacfac6996914577d5d6ae8f14 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sun, 28 Sep 2025 12:04:46 +0000 Subject: [PATCH] daemon: Connect to dbus Signed-off-by: Michael Tremer --- Makefile.am | 2 + src/daemon/bus.c | 193 ++++++++++++++++++++++++++++++++++++++++++++ src/daemon/bus.h | 51 ++++++++++++ src/daemon/daemon.c | 23 ++++++ src/daemon/daemon.h | 4 + 5 files changed, 273 insertions(+) create mode 100644 src/daemon/bus.c create mode 100644 src/daemon/bus.h diff --git a/Makefile.am b/Makefile.am index b6ba415..352aef3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -92,6 +92,8 @@ bin_PROGRAMS += \ dist_collectyd_SOURCES = \ src/daemon/args.c \ src/daemon/args.h \ + src/daemon/bus.c \ + src/daemon/bus.h \ src/daemon/ctx.c \ src/daemon/ctx.h \ src/daemon/daemon.c \ diff --git a/src/daemon/bus.c b/src/daemon/bus.c new file mode 100644 index 0000000..223e134 --- /dev/null +++ b/src/daemon/bus.c @@ -0,0 +1,193 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#include +#include + +#include +#include + +#include "bus.h" +#include "ctx.h" +#include "daemon.h" +#include "util.h" + +#define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/run/dbus/system_bus_socket" + +static int collecty_bus_on_connect(sd_bus_message* m, void* data, sd_bus_error* error) { + collecty_ctx* ctx = data; + + // Log action + DEBUG(ctx, "Connected to D-Bus\n"); + + return 0; +} + +static int collecty_bus_register_implementation(collecty_ctx* ctx, + sd_bus* bus, const struct collecty_bus_implementation* impl, void* data) { + int r; + + DEBUG(ctx, "Registering bus object implementation for path=%s iface=%s\n", + impl->path, impl->interface); + + // Register vtables + for (const sd_bus_vtable** vtable = impl->vtables; vtable && *vtable; vtable++) { + r = sd_bus_add_object_vtable(bus, NULL, impl->path, impl->interface, *vtable, data); + if (r < 0) { + ERROR(ctx, "Could not register bus path %s with interface %s: %m\n", + impl->path, impl->interface); + return r; + } + } + + // Register fallback vtables + for (const struct collecty_bus_vtable_pair* p = impl->fallback_vtables; p && p->vtable; p++) { + r = sd_bus_add_fallback_vtable(bus, NULL, impl->path, impl->interface, + p->vtable, p->object_find, data); + if (r < 0) { + ERROR(ctx, "Could not register bus path %s with interface %s: %m\n", + impl->path, impl->interface); + return r; + } + } + + // Register the node enumerator + if (impl->node_enumerator) { + r = sd_bus_add_node_enumerator(bus, NULL, impl->path, impl->node_enumerator, data); + if (r < 0) { + ERROR(ctx, "Could not add the node enumerator for %s: %m\n", impl->path); + return r; + } + } + + // Register any child implementations + for (int i = 0; impl->children && impl->children[i]; i++) { + r = collecty_bus_register_implementation(ctx, bus, impl->children[i], data); + if (r) + return r; + } + + return 0; +} + +int collecty_bus_connect(collecty_ctx* ctx, sd_bus** bus, sd_event* loop, collecty_daemon* daemon) { + const char* address = NULL; + sd_bus* b = NULL; + int r; + + // Create a bus object + r = sd_bus_new(&b); + if (r < 0) { + ERROR(ctx, "Could not allocate a bus object: %s\n", strerror(-r)); + goto ERROR; + } + + // Set description + r = sd_bus_set_description(b, "collectyd"); + if (r < 0) { + ERROR(ctx, "Could not set bus description: %s\n", strerror(-r)); + goto ERROR; + } + + // Fetch the bus address + address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS"); + if (!address) + address = DEFAULT_SYSTEM_BUS_ADDRESS; + + // Set bus address + r = sd_bus_set_address(b, address); + if (r < 0) { + ERROR(ctx, "Could not set bus address: %s\n", strerror(-r)); + goto ERROR; + } + + // Set bus client + r = sd_bus_set_bus_client(b, 1); + if (r < 0) { + ERROR(ctx, "Could not set bus client: %s\n", strerror(-r)); + goto ERROR; + } + + // Request some credentials for all messages + r = sd_bus_negotiate_creds(b, 1, + SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS); + if (r < 0) { + ERROR(ctx, "Could not negotiate creds: %s\n", strerror(-r)); + goto ERROR; + } + + // Automatically bind when the socket is available + r = sd_bus_set_watch_bind(b, 1); + if (r < 0) { + ERROR(ctx, "Could not watch socket: %s\n", strerror(-r)); + goto ERROR; + } + + // Emit a connected signal when we are connected + r = sd_bus_set_connected_signal(b, 1); + if (r < 0) { + ERROR(ctx, "Could not enable sending a connect signal: %s\n", strerror(-r)); + goto ERROR; + } + + // Connect to the bus + r = sd_bus_start(b); + if (r < 0) { + ERROR(ctx, "Could not connect to bus: %s\n", strerror(-r)); + goto ERROR; + } + + // Register the implementation + r = collecty_bus_register_implementation(ctx, b, &daemon_bus_impl, daemon); + if (r < 0) + goto ERROR; + + // Request interface name + r = sd_bus_request_name_async(b, NULL, "org.ipfire.collecty1", 0, NULL, NULL); + if (r < 0) { + ERROR(ctx, "Could not request bus name: %s\n", strerror(-r)); + goto ERROR; + } + + // Attach the event loop + r = sd_bus_attach_event(b, loop, 0); + if (r < 0) { + ERROR(ctx, "Could not attach bus to event loop: %s\n", strerror(-r)); + goto ERROR; + } + + // Request receiving a connect signal + r = sd_bus_match_signal_async(b, NULL, "org.freedesktop.DBus.Local", NULL, + "org.freedesktop.DBus.Local", "Connected", collecty_bus_on_connect, NULL, ctx); + if (r < 0) { + ERROR(ctx, "Could not request match on Connected signal: %s\n", strerror(-r)); + goto ERROR; + } + + // Return reference + *bus = b; + return 0; + +ERROR: + if (b) + sd_bus_unref(b); + + return r; +} diff --git a/src/daemon/bus.h b/src/daemon/bus.h new file mode 100644 index 0000000..a996099 --- /dev/null +++ b/src/daemon/bus.h @@ -0,0 +1,51 @@ +/*############################################################################# +# # +# collecty - A system statistics collection daemon for IPFire # +# Copyright (C) 2025 IPFire Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#ifndef COLLECTY_BUS_H +#define COLLECTY_BUS_H + +#include +#include + +struct collecty_bus_vtable_pair { + const sd_bus_vtable* vtable; + sd_bus_object_find_t object_find; +}; + +typedef struct collecty_bus_implementation { + const char* path; + const char* interface; + const sd_bus_vtable** vtables; + const struct collecty_bus_vtable_pair* fallback_vtables; + sd_bus_node_enumerator_t node_enumerator; + const struct collecty_bus_implementation** children; +} collecty_bus_implementation; + +#include "ctx.h" +#include "daemon.h" + +#define BUS_FALLBACK_VTABLES(...) ((const struct collecty_bus_vtable_pair[]) { __VA_ARGS__, {} }) +#define BUS_IMPLEMENTATIONS(...) ((const collecty_bus_implementation* []) { __VA_ARGS__, NULL }) +#define BUS_VTABLES(...) ((const sd_bus_vtable* []){ __VA_ARGS__, NULL }) + +int collecty_bus_connect(collecty_ctx* ctx, + sd_bus** bus, sd_event* loop, collecty_daemon* daemon); + +#endif /* COLLECTY_BUS_H */ diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index f49f349..1539a99 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -25,6 +25,7 @@ #include #include +#include "bus.h" #include "ctx.h" #include "daemon.h" #include "module.h" @@ -46,6 +47,9 @@ struct collecty_daemon { sd_event_source* modules_init; } events; + // Bus + sd_bus* bus; + // Queue collecty_queue* queue; }; @@ -139,6 +143,8 @@ static void collecty_daemon_free(collecty_daemon* self) { collecty_ctx_unref(self->ctx); if (self->loop) sd_event_unref(self->loop); + if (self->bus) + sd_bus_unref(self->bus); free(self); } @@ -162,6 +168,11 @@ int collecty_daemon_create(collecty_daemon** daemon, collecty_ctx* ctx) { if (r < 0) goto ERROR; + // Connect to the bus + r = collecty_bus_connect(self->ctx, &self->bus, self->loop, self); + if (r < 0) + goto ERROR; + // Setup the write queue r = collecty_queue_create(&self->queue, self->ctx, self); if (r < 0) @@ -227,3 +238,15 @@ int collecty_daemon_submit(collecty_daemon* self, return collecty_queue_submit(self->queue, module, object, value); } + +static const sd_bus_vtable daemon_vtable[] = { + SD_BUS_VTABLE_START(0), + // XXX TODO + SD_BUS_VTABLE_END, +}; + +const collecty_bus_implementation daemon_bus_impl = { + .path = "/org/ipfire/collecty1", + .interface = "org.ipfire.collecty1", + .vtables = BUS_VTABLES(daemon_vtable), +}; diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h index 8c88645..5d965e7 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -25,6 +25,7 @@ typedef struct collecty_daemon collecty_daemon; +#include "bus.h" #include "ctx.h" #include "module.h" @@ -40,4 +41,7 @@ int collecty_daemon_run(collecty_daemon* self); int collecty_daemon_submit(collecty_daemon* self, collecty_module* module, const char* object, const char* value); +// Bus +extern const collecty_bus_implementation daemon_bus_impl; + #endif /* COLLECTY_DAEMON_H */ -- 2.47.3