bus: add support for attaching name to bus connections for debugging purposes

This commit is contained in:
Lennart Poettering 2014-01-22 16:09:59 +01:00
parent 7f96b1d814
commit 5972fe953e
6 changed files with 104 additions and 5 deletions

View 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;

View 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))

View 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);
}

View 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;
}

View 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_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);

View 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);