chiark / gitweb /
bus: add support for attaching name to bus connections for debugging purposes
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Jan 2014 15:09:59 +0000 (16:09 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 22 Jan 2014 15:09:59 +0000 (16:09 +0100)
src/libsystemd/libsystemd.sym
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-kernel.c
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-bus/test-bus-kernel.c
src/systemd/sd-bus.h

index 7798fac..0942a6e 100644 (file)
@@ -26,6 +26,7 @@ global:
         sd_bus_set_server;
         sd_bus_set_anonymous;
         sd_bus_set_trusted;
+        sd_bus_set_name;
         sd_bus_negotiate_fds;
         sd_bus_negotiate_timestamp;
         sd_bus_negotiate_creds;
@@ -38,6 +39,7 @@ global:
         sd_bus_can_send;
         sd_bus_get_server_id;
         sd_bus_get_peer_creds;
+        sd_bus_get_name;
         sd_bus_send;
         sd_bus_send_to;
         sd_bus_get_fd;
index 7c92293..69e0701 100644 (file)
@@ -164,6 +164,8 @@ struct sd_bus {
         bool trusted:1;
         bool fake_creds_valid:1;
         bool manual_peer_interface:1;
+        bool is_system:1;
+        bool is_user:1;
 
         int use_memfd;
 
@@ -267,6 +269,8 @@ struct sd_bus {
         char *fake_label;
 
         char *cgroup_root;
+
+        char *connection_name;
 };
 
 #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
index fdb4dab..78a6c10 100644 (file)
@@ -26,6 +26,7 @@
 #include <fcntl.h>
 #include <malloc.h>
 #include <sys/mman.h>
+#include <sys/prctl.h>
 
 #include "util.h"
 #include "strv.h"
@@ -628,7 +629,9 @@ fail:
 int bus_kernel_take_fd(sd_bus *b) {
         struct kdbus_cmd_hello *hello;
         struct kdbus_item *item;
-        size_t l = 0, sz;
+        _cleanup_free_ char *g = NULL;
+        const char *name;
+        size_t l = 0, m = 0, sz;
         int r;
 
         assert(b);
@@ -638,10 +641,52 @@ int bus_kernel_take_fd(sd_bus *b) {
 
         b->use_memfd = 1;
 
-        sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items));
+        if (b->connection_name) {
+                g = sd_bus_label_escape(b->connection_name);
+                if (!g)
+                        return -ENOMEM;
+
+                name = g;
+        } else {
+                char pr[17] = {};
+
+                /* If no name is explicitly set, we'll include a hint
+                 * indicating the library implementation, a hint which
+                 * kind of bus this is and the thread name */
+
+                assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
+
+                if (isempty(pr)) {
+                        name = b->is_system ? "sd-system" :
+                                b->is_user ? "sd-user" : "sd";
+                } else {
+                        _cleanup_free_ char *e = NULL;
+
+                        e = sd_bus_label_escape(pr);
+                        if (!e)
+                                return -ENOMEM;
+
+                        g = strappend(b->is_system ? "sd-system-" :
+                                      b->is_user ? "sd-user-" : "sd-",
+                                      e);
+                        if (!g)
+                                return -ENOMEM;
+
+                        name = g;
+                }
+
+                b->connection_name = sd_bus_label_unescape(name);
+                if (!b->connection_name)
+                        return -ENOMEM;
+        }
+
+        m = strlen(name);
+
+        sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
+                ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
 
         if (b->fake_creds_valid)
-                sz += ALIGN8(offsetof(struct kdbus_item, creds)) + sizeof(struct kdbus_creds);
+                sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
 
         if (b->fake_label) {
                 l = strlen(b->fake_label);
@@ -656,6 +701,11 @@ int bus_kernel_take_fd(sd_bus *b) {
 
         item = hello->items;
 
+        item->size = offsetof(struct kdbus_item, str) + m + 1;
+        item->type = KDBUS_ITEM_CONN_NAME;
+        memcpy(item->str, name, m + 1);
+        item = KDBUS_ITEM_NEXT(item);
+
         if (b->fake_creds_valid) {
                 item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
                 item->type = KDBUS_ITEM_CREDS;
@@ -666,6 +716,7 @@ int bus_kernel_take_fd(sd_bus *b) {
 
         if (b->fake_label) {
                 item->size = offsetof(struct kdbus_item, str) + l + 1;
+                item->type = KDBUS_ITEM_SECLABEL;
                 memcpy(item->str, b->fake_label, l+1);
         }
 
index edea7c0..a8295b2 100644 (file)
@@ -144,6 +144,7 @@ static void bus_free(sd_bus *b) {
         free(b->machine);
         free(b->fake_label);
         free(b->cgroup_root);
+        free(b->connection_name);
 
         free(b->exec_path);
         strv_free(b->exec_argv);
@@ -334,6 +335,24 @@ _public_ int sd_bus_set_trusted(sd_bus *bus, int b) {
         return 0;
 }
 
+_public_ int sd_bus_set_name(sd_bus *bus, const char *name) {
+        char *n;
+
+        assert_return(bus, -EINVAL);
+        assert_return(name, -EINVAL);
+        assert_return(bus->state == BUS_UNSET, -EPERM);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
+
+        n = strdup(name);
+        if (!n)
+                return -ENOMEM;
+
+        free(bus->connection_name);
+        bus->connection_name = n;
+
+        return 0;
+}
+
 static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
         const char *s;
         int r;
@@ -1053,6 +1072,7 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
                 goto fail;
 
         b->bus_client = true;
+        b->is_system = true;
 
         /* Let's do per-method access control on the system bus. We
          * need the caller's UID and capability set for that. */
@@ -1118,6 +1138,7 @@ _public_ int sd_bus_open_user(sd_bus **ret) {
         }
 
         b->bus_client = true;
+        b->is_user = true;
 
         /* We don't do any per-method access control on the user
          * bus. */
@@ -3034,3 +3055,12 @@ _public_ int sd_bus_try_close(sd_bus *bus) {
         sd_bus_close(bus);
         return 0;
 }
+
+_public_ int sd_bus_get_name(sd_bus *bus, const char **name) {
+        assert_return(bus, -EINVAL);
+        assert_return(name, -EINVAL);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
+
+        *name = bus->connection_name;
+        return 0;
+}
index 3dcc5d3..0fab880 100644 (file)
@@ -39,6 +39,7 @@ int main(int argc, char *argv[]) {
         const char *ua = NULL, *ub = NULL, *the_string = NULL;
         sd_bus *a, *b;
         int r, pipe_fds[2];
+        const char *nn;
 
         log_set_max_level(LOG_DEBUG);
 
@@ -59,6 +60,9 @@ int main(int argc, char *argv[]) {
         r = sd_bus_new(&b);
         assert_se(r >= 0);
 
+        r = sd_bus_set_name(a, "a");
+        assert_se(r >= 0);
+
         r = sd_bus_set_address(a, address);
         assert_se(r >= 0);
 
@@ -79,14 +83,20 @@ int main(int argc, char *argv[]) {
 
         r = sd_bus_get_unique_name(a, &ua);
         assert_se(r >= 0);
-
         printf("unique a: %s\n", ua);
 
-        r = sd_bus_get_unique_name(b, &ub);
+        r = sd_bus_get_name(a, &nn);
         assert_se(r >= 0);
+        printf("name of a: %s\n", nn);
 
+        r = sd_bus_get_unique_name(b, &ub);
+        assert_se(r >= 0);
         printf("unique b: %s\n", ub);
 
+        r = sd_bus_get_name(b, &nn);
+        assert_se(r >= 0);
+        printf("name of b: %s\n", nn);
+
         r = sd_bus_call_method(a, "this.doesnt.exist", "/foo", "meh.mah", "muh", &error, NULL, "s", "yayayay");
         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN));
         assert_se(r == -EHOSTUNREACH);
index 4e6c321..baffd53 100644 (file)
@@ -110,6 +110,7 @@ int sd_bus_set_bus_client(sd_bus *bus, int b);
 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_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);
@@ -125,6 +126,7 @@ int sd_bus_is_open(sd_bus *bus);
 int sd_bus_can_send(sd_bus *bus, char type);
 int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *peer);
 int sd_bus_get_peer_creds(sd_bus *bus, uint64_t creds_mask, sd_bus_creds **ret);
+int sd_bus_get_name(sd_bus *bus, const char **name);
 
 int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie);
 int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie);