#############################################################################*/
#include <stdlib.h>
-#include <string.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include "bus.h"
#include "daemon.h"
+#include "daemon-bus.h"
#include "logging.h"
-static int nw_bus_daemon_reload(sd_bus_message* m, void* data, sd_bus_error* error) {
- return 1;
-}
-
static int nw_bus_on_connect(sd_bus_message* m, void* data, sd_bus_error* error) {
- struct nw_daemon* daemon = (struct nw_daemon*)data;
+ nw_daemon* daemon = (nw_daemon*)data;
DEBUG("Connected to D-Bus\n");
return 0;
}
-static const sd_bus_vtable daemon_vtable[] = {
- SD_BUS_VTABLE_START(0),
- SD_BUS_METHOD("Reload", SD_BUS_NO_ARGS, SD_BUS_NO_RESULT,
- nw_bus_daemon_reload, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_VTABLE_END,
-};
-
-int nw_bus_connect(sd_bus* bus, sd_event* loop) {
+int nw_bus_connect(sd_bus** bus, sd_event* loop, nw_daemon* daemon) {
+ sd_bus* b = NULL;
int r;
// Create a bus object
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&b);
if (r < 0) {
ERROR("Could not allocate a bus object: %s\n", strerror(-r));
return 1;
}
// Set description
- r = sd_bus_set_description(bus, NETWORKD_BUS_DESCRIPTION);
+ r = sd_bus_set_description(b, NETWORKD_BUS_DESCRIPTION);
if (r < 0) {
ERROR("Could not set bus description: %s\n", strerror(-r));
return 1;
address = DEFAULT_SYSTEM_BUS_ADDRESS;
// Set bus address
- r = sd_bus_set_address(bus, address);
+ r = sd_bus_set_address(b, address);
if (r < 0) {
ERROR("Could not set bus address: %s\n", strerror(-r));
return 1;
}
// Set bus client
- r = sd_bus_set_bus_client(bus, 1);
+ r = sd_bus_set_bus_client(b, 1);
if (r < 0) {
ERROR("Could not set bus client: %s\n", strerror(-r));
return 1;
}
// Request some credentials for all messages
- r = sd_bus_negotiate_creds(bus, 1,
+ r = sd_bus_negotiate_creds(b, 1,
SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
if (r < 0) {
ERROR("Could not negotiate creds: %s\n", strerror(-r));
}
// Automatically bind when the socket is available
- r = sd_bus_set_watch_bind(bus, 1);
+ r = sd_bus_set_watch_bind(b, 1);
if (r < 0) {
ERROR("Could not watch socket: %s\n", strerror(-r));
return 1;
}
// Emit a connected signal when we are connected
- r = sd_bus_set_connected_signal(bus, 1);
+ r = sd_bus_set_connected_signal(b, 1);
if (r < 0) {
ERROR("Could not enable sending a connect signal: %s\n", strerror(-r));
return 1;
}
// Connect to the bus
- r = sd_bus_start(bus);
+ r = sd_bus_start(b);
if (r < 0) {
ERROR("Could not connect to bus: %s\n", strerror(-r));
return 1;
}
- // Register any functions
- r = sd_bus_add_object_vtable(bus, NULL,
- NETWORKD_BUS_OBJECT_PATH, NETWORKD_BUS_INTERFACE_NAME, daemon_vtable, NULL);
- if (r < 0) {
- ERROR("Could not add object vtable: %s\n", strerror(-r));
- return 1;
- }
+ // Register the implementation
+ r = nw_bus_register_implementation(b, &daemon_bus_impl, daemon);
+ if (r)
+ return r;
// Request interface name
- // XXX Should this be async?
- // XXX How do we get the actual error message from dbus?
- r = sd_bus_request_name(bus, NETWORKD_BUS_INTERFACE_NAME, 0);
+ r = sd_bus_request_name_async(b, NULL, "org.ipfire.network1", 0, NULL, NULL);
if (r < 0) {
ERROR("Could not request bus name: %s\n", strerror(-r));
return 1;
}
// Attach the event loop
- r = sd_bus_attach_event(bus, loop, 0);
+ r = sd_bus_attach_event(b, loop, 0);
if (r < 0) {
ERROR("Could not attach bus to event loop: %s\n", strerror(-r));
return 1;
}
// Request receiving a connect signal
- r = sd_bus_match_signal_async(bus, NULL, "org.freedesktop.DBus.Local",
+ r = sd_bus_match_signal_async(b, NULL, "org.freedesktop.DBus.Local",
NULL, "org.freedesktop.DBus.Local", "Connected", nw_bus_on_connect, NULL, NULL);
if (r < 0) {
ERROR("Could not request match on Connected signal: %s\n", strerror(-r));
return 1;
}
+ // Return reference
+ *bus = b;
+
+ return 0;
+}
+
+int nw_bus_register_implementation(sd_bus* bus,
+ const struct nw_bus_implementation* impl, void* data) {
+ int r;
+
+ DEBUG("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("Could not register bus path %s with interface %s: %m\n",
+ impl->path, impl->interface);
+ return 1;
+ }
+ }
+
+ // Register fallback vtables
+ for (const struct nw_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("Could not register bus path %s with interface %s: %m\n",
+ impl->path, impl->interface);
+ return 1;
+ }
+ }
+
+ // 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("Could not add the node enumerator for %s: %m\n", impl->path);
+ return 1;
+ }
+ }
+
+ // Register any child implementations
+ for (int i = 0; impl->children && impl->children[i]; i++) {
+ r = nw_bus_register_implementation(bus, impl->children[i], data);
+ if (r)
+ return r;
+ }
+
return 0;
}