bus-control.c revision 52cfc0379a9d63f99cdb3d9f63c839bbc8889b4c
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek This file is part of systemd.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek Copyright 2013 Lennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek (at your option) any later version.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(!bus_pid_changed(bus), -ECHILD);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering n->flags = request_name_flags_to_kdbus(flags);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek param |= BUS_NAME_ALLOW_REPLACEMENT;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering if (flags & SD_BUS_NAME_REPLACE_EXISTING)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek r = sd_bus_message_read(reply, "u", &ret);
fff40a51ccbb02e8dec4ff2ee505bc84f75e445cZbigniew Jędrzejewski-Szmek if (ret == BUS_NAME_ALREADY_OWNER)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek else if (ret == BUS_NAME_EXISTS)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek else if (ret == BUS_NAME_IN_QUEUE)
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek else if (ret == BUS_NAME_PRIMARY_OWNER)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek assert_return(bus->bus_client, -EINVAL);
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek assert_return(!bus_pid_changed(bus), -ECHILD);
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(service_name_is_valid(name), -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(name[0] != ':', -EINVAL);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering return bus_request_name_kernel(bus, name, flags);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering return bus_request_name_dbus1(bus, name, flags);
29a5ca9baa58e55c4d9e1d008cdd014aa9c3c3e1Lennart Poetteringstatic int bus_release_name_kernel(sd_bus *bus, const char *name) {
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek memcpy(n->items[0].str, name, l);
5b84559a76f30755019d6a0e6b2ccc9bbe0b3c56Lennart Poettering r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmekstatic int bus_release_name_dbus1(sd_bus *bus, const char *name) {
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read(reply, "u", &ret);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (ret == BUS_NAME_NON_EXISTENT)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(bus->bus_client, -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(!bus_pid_changed(bus), -ECHILD);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(service_name_is_valid(name), -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(name[0] != ':', -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_release_name_kernel(bus, name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_release_name_dbus1(bus, name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek struct kdbus_cmd_name_list cmd = {};
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek struct kdbus_name_list *name_list;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek /* Caller will free half-constructed list on failure... */
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek KDBUS_ITEM_FOREACH(name, name_list, names) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (entry_name && service_name_is_valid(entry_name)) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek bus_kernel_cmd_free(bus, cmd.offset);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
e9c1ea9de87d4d508ac38ce87a2fa56e7529a91aJason St. John _cleanup_strv_free_ char **x = NULL, **y = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek _cleanup_strv_free_ char **x = NULL, **y = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read_strv(reply, &x);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek reply = sd_bus_message_unref(reply);
ed6556920c1a6cdfe0bb04e806bc1f54ea191545Mantas Mikulėnas "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering "ListActivatableNames",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read_strv(reply, &y);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert_return(acquired || activatable, -EINVAL);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert_return(!bus_pid_changed(bus), -ECHILD);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_list_names_kernel(bus, acquired, activatable);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_list_names_dbus1(bus, acquired, activatable);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int bus_populate_creds_from_items(
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek KDBUS_ITEM_FOREACH(item, info, items) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->pid = (pid_t) item->pids.pid;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_PID_STARTTIME && item->pids.starttime > 0) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->mask |= SD_BUS_CREDS_PID_STARTTIME;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != (uid_t) -1) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->uid = (uid_t) item->creds.uid;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != (uid_t) -1) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->euid = (uid_t) item->creds.euid;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != (uid_t) -1) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->suid = (uid_t) item->creds.suid;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != (uid_t) -1) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->fsuid = (uid_t) item->creds.fsuid;
case KDBUS_ITEM_PID_COMM:
case KDBUS_ITEM_TID_COMM:
case KDBUS_ITEM_EXE:
case KDBUS_ITEM_CMDLINE:
if (!c->cmdline)
return -ENOMEM;
case KDBUS_ITEM_CGROUP:
c->mask |= m;
case KDBUS_ITEM_CAPS:
if (!c->capability)
return -ENOMEM;
c->mask |= m;
case KDBUS_ITEM_SECLABEL:
case KDBUS_ITEM_AUDIT:
case KDBUS_ITEM_OWNED_NAME:
case KDBUS_ITEM_AUXGROUPS:
size_t n;
uid_t *g;
return -ENOMEM;
c->supplementary_gids = g;
c->n_supplementary_gids = n;
static int bus_get_name_creds_kdbus(
const char *name,
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
return -errno;
r = -ENXIO;
r = -ESRCH;
goto fail;
c = bus_creds_new();
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
goto fail;
goto fail;
if (creds) {
*creds = c;
c = NULL;
fail:
static int bus_get_name_creds_dbus1(
const char *name,
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
name);
if (mask != 0) {
c = bus_creds_new();
return -ENOMEM;
if (!c->unique_name)
return -ENOMEM;
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
uint32_t u;
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
&reply,
pid = u;
c->pid = u;
uint32_t u;
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
&reply,
c->uid = u;
const void *p = NULL;
r = sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
&error,
&reply,
if (!c->label)
return -ENOMEM;
if (creds) {
*creds = c;
c = NULL;
const char *name,
return -ENOTCONN;
c = bus_creds_new();
return -ENOMEM;
SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
return -errno;
*ret = c;
c = NULL;
return -ENODATA;
c = bus_creds_new();
return -ENOMEM;
if (!c->label)
return -ENOMEM;
*ret = c;
c = NULL;
return -ENOTCONN;
const char *name,
const char *old_owner,
const char *new_owner) {
if (name) {
if (is_name_id < 0)
if (is_name_id <= 0) {
struct kdbus_cmd_match *m;
if (name)
return -errno;
return -errno;
return -errno;
if (is_name_id != 0) {
struct kdbus_cmd_match *m;
sizeof(struct kdbus_notify_id_change));
sizeof(struct kdbus_notify_id_change);
return -errno;
return -errno;
unsigned n_components,
struct kdbus_cmd_match *m;
bool using_bloom = false;
bool matches_name_change = true;
for (i = 0; i < n_components; i++) {
switch (c->type) {
case BUS_MATCH_SENDER:
matches_name_change = false;
case BUS_MATCH_MESSAGE_TYPE:
matches_name_change = false;
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
using_bloom = true;
case BUS_MATCH_INTERFACE:
matches_name_change = false;
using_bloom = true;
case BUS_MATCH_MEMBER:
matches_name_change = false;
using_bloom = true;
case BUS_MATCH_PATH:
matches_name_change = false;
using_bloom = true;
case BUS_MATCH_PATH_NAMESPACE:
using_bloom = true;
using_bloom = true;
using_bloom = true;
using_bloom = true;
case BUS_MATCH_DESTINATION:
case BUS_MATCH_ROOT:
case BUS_MATCH_VALUE:
case BUS_MATCH_LEAF:
case _BUS_MATCH_NODE_TYPE_MAX:
if (using_bloom)
if (using_bloom) {
if (sender) {
return -errno;
if (matches_name_change) {
static int bus_add_match_internal_dbus1(
const char *match) {
return sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
NULL,
const char *match,
unsigned n_components,
struct kdbus_cmd_match m;
zero(m);
return -errno;
static int bus_remove_match_internal_dbus1(
const char *match) {
return sd_bus_call_method(
bus,
"/org/freedesktop/DBus",
NULL,
NULL,
const char *match,
const char *mid;
return -ENOTCONN;
bus,
name,
r = sd_bus_message_set_auto_start(m, false);