summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-03-19 04:17:00 +0100
committerLennart Poettering <lennart@poettering.net>2014-03-19 04:17:00 +0100
commit09365592341b4ba4ceca677bb551dcde811e0333 (patch)
tree662f7de7e71fe5d05226164cc3a90088dfbf7cf6
parent4f10118016f9b2fd7e1d26c9ef7d91eb33fba694 (diff)
sd-bus: add proper monitoring API
-rw-r--r--src/libsystemd/libsystemd.sym.m41
-rw-r--r--src/libsystemd/sd-bus/bus-control.c17
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h5
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c9
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c3
-rw-r--r--src/libsystemd/sd-bus/busctl.c56
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c206
-rw-r--r--src/systemd/sd-bus.h1
8 files changed, 206 insertions, 92 deletions
diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4
index e9c42d0044..8589d605ab 100644
--- a/src/libsystemd/libsystemd.sym.m4
+++ b/src/libsystemd/libsystemd.sym.m4
@@ -154,6 +154,7 @@ m4_ifdef(`ENABLE_KDBUS',
sd_bus_set_server;
sd_bus_set_anonymous;
sd_bus_set_trusted;
+ sd_bus_set_monitor;
sd_bus_set_name;
sd_bus_negotiate_fds;
sd_bus_negotiate_timestamp;
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index db0c11b0fe..bb6683efff 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -1098,13 +1098,22 @@ int bus_add_match_internal_kernel(
return 0;
}
+#define internal_match(bus, m) \
+ ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
+ ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
+ : (m))
+
static int bus_add_match_internal_dbus1(
sd_bus *bus,
const char *match) {
+ const char *e;
+
assert(bus);
assert(match);
+ e = internal_match(bus, match);
+
return sd_bus_call_method(
bus,
"org.freedesktop.DBus",
@@ -1114,7 +1123,7 @@ static int bus_add_match_internal_dbus1(
NULL,
NULL,
"s",
- match);
+ e);
}
int bus_add_match_internal(
@@ -1159,9 +1168,13 @@ static int bus_remove_match_internal_dbus1(
sd_bus *bus,
const char *match) {
+ const char *e;
+
assert(bus);
assert(match);
+ e = internal_match(bus, match);
+
return sd_bus_call_method(
bus,
"org.freedesktop.DBus",
@@ -1171,7 +1184,7 @@ static int bus_remove_match_internal_dbus1(
NULL,
NULL,
"s",
- match);
+ e);
}
int bus_remove_match_internal(
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index ae5f66288f..3dceb8a5da 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -335,3 +335,8 @@ char *bus_address_escape(const char *v);
* on */
#define BUS_DONT_DESTROY(bus) \
_cleanup_bus_unref_ _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
+
+int bus_set_address_system(sd_bus *bus);
+int bus_set_address_user(sd_bus *bus);
+int bus_set_address_system_remote(sd_bus *b, const char *host);
+int bus_set_address_system_container(sd_bus *b, const char *machine);
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index 00f58114ac..af42b9f5e1 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1339,9 +1339,13 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) {
return fd;
}
-static void bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item)
-{
+static void bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
+
+ assert(policy);
+ assert(item);
+
switch (policy->type) {
+
case BUSNAME_POLICY_TYPE_USER:
item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
item->policy_access.id = policy->uid;
@@ -1361,6 +1365,7 @@ static void bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbu
}
switch (policy->access) {
+
case BUSNAME_POLICY_ACCESS_SEE:
item->policy_access.access = KDBUS_POLICY_SEE;
break;
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
index 7d325fab33..08792fea22 100644
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -1304,6 +1304,9 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) {
assert(bus);
assert(m);
+ if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ return 0;
+
if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
return 0;
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
index e326cc047a..b4fb364716 100644
--- a/src/libsystemd/sd-bus/busctl.c
+++ b/src/libsystemd/sd-bus/busctl.c
@@ -494,29 +494,57 @@ int main(int argc, char *argv[]) {
if (r <= 0)
goto finish;
- if (arg_address) {
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&bus);
+ if (r < 0) {
+ log_error("Failed to allocate bus: %s", strerror(-r));
+ goto finish;
+ }
+
+ if (streq_ptr(argv[optind], "monitor")) {
+
+ r = sd_bus_set_monitor(bus, true);
if (r < 0) {
- log_error("Failed to allocate bus: %s", strerror(-r));
+ log_error("Failed to set monitor mode: %s", strerror(-r));
goto finish;
}
+ }
+ if (arg_address)
r = sd_bus_set_address(bus, arg_address);
- if (r < 0) {
- log_error("Failed to set address: %s", strerror(-r));
- goto finish;
- }
+ else {
+ switch (arg_transport) {
- r = sd_bus_set_bus_client(bus, true);
- if (r < 0) {
- log_error("Failed to set bus client: %s", strerror(-r));
- goto finish;
+ case BUS_TRANSPORT_LOCAL:
+ if (arg_user)
+ r = bus_set_address_user(bus);
+ else
+ r = bus_set_address_system(bus);
+ break;
+
+ case BUS_TRANSPORT_REMOTE:
+ r = bus_set_address_system_remote(bus, arg_host);
+ break;
+
+ case BUS_TRANSPORT_CONTAINER:
+ r = bus_set_address_system_container(bus, arg_host);
+ break;
+
+ default:
+ assert_not_reached("Hmm, unknown transport type.");
}
+ }
+ if (r < 0) {
+ log_error("Failed to set address: %s", strerror(-r));
+ goto finish;
+ }
- r = sd_bus_start(bus);
- } else
- r = bus_open_transport(arg_transport, arg_host, arg_user, &bus);
+ r = sd_bus_set_bus_client(bus, true);
+ if (r < 0) {
+ log_error("Failed to set bus client: %s", strerror(-r));
+ goto finish;
+ }
+ r = sd_bus_start(bus);
if (r < 0) {
log_error("Failed to connect to bus: %s", strerror(-r));
goto finish;
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 6a1f459044..6f5ba5bd5b 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -284,6 +284,15 @@ _public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
return 0;
}
+_public_ int sd_bus_set_monitor(sd_bus *bus, int b) {
+ assert_return(bus, -EINVAL);
+ assert_return(bus->state == BUS_UNSET, -EPERM);
+ assert_return(!bus_pid_changed(bus), -ECHILD);
+
+ SET_FLAG(bus->hello_flags, KDBUS_HELLO_MONITOR, b);
+ return 0;
+}
+
_public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) {
assert_return(bus, -EINVAL);
assert_return(bus->state == BUS_UNSET, -EPERM);
@@ -1075,7 +1084,7 @@ _public_ int sd_bus_open(sd_bus **ret) {
if (e) {
if (streq(e, "system"))
return sd_bus_open_system(ret);
- else if (streq(e, "session") || streq(e, "user"))
+ else if (STR_IN_SET(e, "session", "user"))
return sd_bus_open_user(ret);
}
@@ -1114,8 +1123,18 @@ fail:
return r;
}
-_public_ int sd_bus_open_system(sd_bus **ret) {
+int bus_set_address_system(sd_bus *b) {
const char *e;
+ assert(b);
+
+ e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
+ if (e)
+ return sd_bus_set_address(b, e);
+
+ return sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_PATH);
+}
+
+_public_ int sd_bus_open_system(sd_bus **ret) {
sd_bus *b;
int r;
@@ -1125,11 +1144,7 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
if (r < 0)
return r;
- e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
- if (e)
- r = sd_bus_set_address(b, e);
- else
- r = sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_PATH);
+ r = bus_set_address_system(b);
if (r < 0)
goto fail;
@@ -1153,53 +1168,56 @@ fail:
return r;
}
-_public_ int sd_bus_open_user(sd_bus **ret) {
+int bus_set_address_user(sd_bus *b) {
const char *e;
- sd_bus *b;
- int r;
- assert_return(ret, -EINVAL);
-
- r = sd_bus_new(&b);
- if (r < 0)
- return r;
+ assert(b);
e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
+ if (e)
+ return sd_bus_set_address(b, e);
+
+ e = secure_getenv("XDG_RUNTIME_DIR");
if (e) {
- r = sd_bus_set_address(b, e);
- if (r < 0)
- goto fail;
- } else {
- e = secure_getenv("XDG_RUNTIME_DIR");
- if (e) {
- _cleanup_free_ char *ee = NULL;
+ _cleanup_free_ char *ee = NULL;
- ee = bus_address_escape(e);
- if (!ee) {
- r = -ENOMEM;
- goto fail;
- }
+ ee = bus_address_escape(e);
+ if (!ee)
+ return -ENOMEM;
#ifdef ENABLE_KDBUS
- asprintf(&b->address, KERNEL_USER_BUS_FMT ";" UNIX_USER_BUS_FMT, (unsigned long) getuid(), ee);
+ asprintf(&b->address, KERNEL_USER_BUS_FMT ";" UNIX_USER_BUS_FMT, (unsigned long) getuid(), ee);
#else
- asprintf(&b->address, UNIX_USER_BUS_FMT, ee);
+ asprintf(&b->address, UNIX_USER_BUS_FMT, ee);
#endif
- } else {
+ } else {
#ifdef ENABLE_KDBUS
- asprintf(&b->address, KERNEL_USER_BUS_FMT, (unsigned long) getuid());
+ asprintf(&b->address, KERNEL_USER_BUS_FMT, (unsigned long) getuid());
#else
- r = -ECONNREFUSED;
- goto fail;
+ return -ECONNREFUSED;
#endif
- }
-
- if (!b->address) {
- r = -ENOMEM;
- goto fail;
- }
}
+ if (!b->address)
+ return -ENOMEM;
+
+ return 0;
+}
+
+_public_ int sd_bus_open_user(sd_bus **ret) {
+ sd_bus *b;
+ int r;
+
+ assert_return(ret, -EINVAL);
+
+ r = sd_bus_new(&b);
+ if (r < 0)
+ return r;
+
+ r = bus_set_address_user(b);
+ if (r < 0)
+ return r;
+
b->bus_client = true;
b->is_user = true;
@@ -1219,81 +1237,103 @@ fail:
return r;
}
-_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
+int bus_set_address_system_remote(sd_bus *b, const char *host) {
_cleanup_free_ char *e = NULL;
- char *p = NULL;
- sd_bus *bus;
- int r;
- assert_return(host, -EINVAL);
- assert_return(ret, -EINVAL);
+ assert(b);
+ assert(host);
e = bus_address_escape(host);
if (!e)
return -ENOMEM;
- p = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL);
- if (!p)
+ b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL);
+ if (!b->address)
return -ENOMEM;
+ return 0;
+ }
+
+_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
+ sd_bus *bus;
+ int r;
+
+ assert_return(host, -EINVAL);
+ assert_return(ret, -EINVAL);
+
r = sd_bus_new(&bus);
- if (r < 0) {
- free(p);
+ if (r < 0)
return r;
- }
- bus->address = p;
+ r = bus_set_address_system_remote(bus, host);
+ if (r < 0)
+ goto fail;
+
bus->bus_client = true;
+ bus->trusted = false;
r = sd_bus_start(bus);
- if (r < 0) {
- bus_free(bus);
- return r;
- }
+ if (r < 0)
+ goto fail;
*ret = bus;
return 0;
+
+fail:
+ bus_free(bus);
+ return r;
}
-_public_ int sd_bus_open_system_container(sd_bus **ret, const char *machine) {
+int bus_set_address_system_container(sd_bus *b, const char *machine) {
_cleanup_free_ char *e = NULL;
- sd_bus *bus;
- char *p;
- int r;
- assert_return(machine, -EINVAL);
- assert_return(ret, -EINVAL);
- assert_return(filename_is_safe(machine), -EINVAL);
+ assert(b);
+ assert(machine);
e = bus_address_escape(machine);
if (!e)
return -ENOMEM;
#ifdef ENABLE_KDBUS
- p = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
+ b->address = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
#else
- p = strjoin("x-container-unix:machine=", e, NULL);
+ b->address = strjoin("x-container-unix:machine=", e, NULL);
#endif
- if (!p)
+ if (!b->address)
return -ENOMEM;
+ return 0;
+}
+
+_public_ int sd_bus_open_system_container(sd_bus **ret, const char *machine) {
+ sd_bus *bus;
+ int r;
+
+ assert_return(machine, -EINVAL);
+ assert_return(ret, -EINVAL);
+ assert_return(filename_is_safe(machine), -EINVAL);
+
r = sd_bus_new(&bus);
- if (r < 0) {
- free(p);
+ if (r < 0)
return r;
- }
- bus->address = p;
+ r = bus_set_address_system_container(bus, machine);
+ if (r < 0)
+ goto fail;
+
bus->bus_client = true;
+ bus->trusted = false;
r = sd_bus_start(bus);
- if (r < 0) {
- bus_free(bus);
- return r;
- }
+ if (r < 0)
+ goto fail;
*ret = bus;
return 0;
+
+fail:
+ bus_free(bus);
+ return r;
}
_public_ void sd_bus_close(sd_bus *bus) {
@@ -1397,6 +1437,9 @@ _public_ int sd_bus_can_send(sd_bus *bus, char type) {
assert_return(bus->state != BUS_UNSET, -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
+ if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ return 0;
+
if (type == SD_BUS_TYPE_UNIX_FD) {
if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
return 0;
@@ -1598,6 +1641,7 @@ static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie,
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(m, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
if (m->n_fds > 0) {
r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
@@ -1735,6 +1779,7 @@ _public_ int sd_bus_call_async(
assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
if (r < 0)
@@ -1848,6 +1893,7 @@ _public_ int sd_bus_call(
assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
assert_return(!bus_error_is_dirty(error), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
+ assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
r = bus_ensure_running(bus);
if (r < 0)
@@ -2125,6 +2171,12 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
return 0;
+ if (bus->is_kernel && (bus->hello_flags & KDBUS_HELLO_MONITOR))
+ return 0;
+
+ if (m->destination && bus->unique_name && !streq_ptr(m->destination, bus->unique_name))
+ return 0;
+
c = hashmap_remove(bus->reply_callbacks, &m->reply_cookie);
if (!c)
return 0;
@@ -2225,6 +2277,9 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) {
assert(bus);
assert(m);
+ if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ return 0;
+
if (bus->manual_peer_interface)
return 0;
@@ -2280,6 +2335,9 @@ static int process_fd_check(sd_bus *bus, sd_bus_message *m) {
* delivered to us later even though we ourselves did not
* negotiate it. */
+ if (bus->hello_flags & KDBUS_HELLO_MONITOR)
+ return 0;
+
if (m->n_fds <= 0)
return 0;
@@ -3077,7 +3135,7 @@ _public_ int sd_bus_default(sd_bus **ret) {
if (e) {
if (streq(e, "system"))
return sd_bus_default_system(ret);
- else if (streq(e, "user") || streq(e, "session"))
+ else if (STR_IN_SET(e, "user", "session"))
return sd_bus_default_user(ret);
}
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 8817380f1a..ff2333fb4a 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -116,6 +116,7 @@ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id);
int sd_bus_set_anonymous(sd_bus *bus, int b);
int sd_bus_set_trusted(sd_bus *bus, int b);
int sd_bus_set_name(sd_bus *bus, const char *name);
+int sd_bus_set_monitor(sd_bus *bus, int b);
int sd_bus_negotiate_fds(sd_bus *bus, int b);
int sd_bus_negotiate_timestamp(sd_bus *bus, int b);
int sd_bus_negotiate_creds(sd_bus *bus, uint64_t creds_mask);