bus-control.c revision 52cfc0379a9d63f99cdb3d9f63c839bbc8889b4c
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek/***
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek This file is part of systemd.
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek Copyright 2013 Lennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
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
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
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***/
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#ifdef HAVE_VALGRIND_MEMCHECK_H
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include <valgrind/memcheck.h>
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#endif
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include <stddef.h>
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include <errno.h>
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "strv.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "sd-bus.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "bus-internal.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "bus-message.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "bus-control.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "bus-bloom.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "bus-util.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek#include "cgroup-util.h"
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek int r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert_return(bus, -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(unique, -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(!bus_pid_changed(bus), -ECHILD);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering r = bus_ensure_running(bus);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek *unique = bus->unique_name;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek}
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
603938e0a9b5379984d7397e3cf81683c0037a53Lennart Poettering struct kdbus_cmd_name *n;
603938e0a9b5379984d7397e3cf81683c0037a53Lennart Poettering size_t size, l;
603938e0a9b5379984d7397e3cf81683c0037a53Lennart Poettering int r;
603938e0a9b5379984d7397e3cf81683c0037a53Lennart Poettering
603938e0a9b5379984d7397e3cf81683c0037a53Lennart Poettering assert(bus);
603938e0a9b5379984d7397e3cf81683c0037a53Lennart Poettering assert(name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek l = strlen(name) + 1;
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering n = alloca0_align(size, 8);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering n->size = size;
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering n->flags = request_name_flags_to_kdbus(flags);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering n->items[0].type = KDBUS_ITEM_NAME;
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering memcpy(n->items[0].str, name, l);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering#ifdef HAVE_VALGRIND_MEMCHECK_H
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering VALGRIND_MAKE_MEM_DEFINED(n, n->size);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering#endif
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering if (r < 0)
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering return -errno;
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering if (n->flags & KDBUS_NAME_IN_QUEUE)
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering return 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering return 1;
29a5ca9baa58e55c4d9e1d008cdd014aa9c3c3e1Lennart Poettering}
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
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;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek uint32_t ret, param = 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek int r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert(bus);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert(name);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering
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)
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering param |= BUS_NAME_REPLACE_EXISTING;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering if (!(flags & SD_BUS_NAME_QUEUE))
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering param |= BUS_NAME_DO_NOT_QUEUE;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering r = sd_bus_call_method(
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering bus,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "/org/freedesktop/DBus",
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek "RequestName",
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek NULL,
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek &reply,
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek "su",
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek name,
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek param);
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek if (r < 0)
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek return r;
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek r = sd_bus_message_read(reply, "u", &ret);
fff40a51ccbb02e8dec4ff2ee505bc84f75e445cZbigniew Jędrzejewski-Szmek if (r < 0)
fff40a51ccbb02e8dec4ff2ee505bc84f75e445cZbigniew Jędrzejewski-Szmek return r;
fff40a51ccbb02e8dec4ff2ee505bc84f75e445cZbigniew Jędrzejewski-Szmek
fff40a51ccbb02e8dec4ff2ee505bc84f75e445cZbigniew Jędrzejewski-Szmek if (ret == BUS_NAME_ALREADY_OWNER)
fff40a51ccbb02e8dec4ff2ee505bc84f75e445cZbigniew Jędrzejewski-Szmek return -EALREADY;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek else if (ret == BUS_NAME_EXISTS)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return -EEXIST;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek else if (ret == BUS_NAME_IN_QUEUE)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return 0;
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek else if (ret == BUS_NAME_PRIMARY_OWNER)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return 1;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return -EIO;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek}
175a3d25d0e8596d4ba0759aea3f89ee228e7d6dLennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(bus, -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(name, -EINVAL);
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);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (!BUS_IS_OPEN(bus->state))
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return -ENOTCONN;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (bus->is_kernel)
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering return bus_request_name_kernel(bus, name, flags);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering else
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering return bus_request_name_dbus1(bus, name, flags);
2c408cb6276e3b8d18fb4e2a81a1128d8bbaa70dLennart Poettering}
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering
29a5ca9baa58e55c4d9e1d008cdd014aa9c3c3e1Lennart Poetteringstatic int bus_release_name_kernel(sd_bus *bus, const char *name) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek struct kdbus_cmd_name *n;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek size_t size, l;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek int r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert(bus);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert(name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
23ea3dab15181a3966ec45fa2ccbb81e59d2e0a7Zbigniew Jędrzejewski-Szmek l = strlen(name) + 1;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek n = alloca0_align(size, 8);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering n->size = size;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering n->items[0].type = KDBUS_ITEM_NAME;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek memcpy(n->items[0].str, name, l);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek#ifdef HAVE_VALGRIND_MEMCHECK_H
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering VALGRIND_MAKE_MEM_DEFINED(n, n->size);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek#endif
5b84559a76f30755019d6a0e6b2ccc9bbe0b3c56Lennart Poettering r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering if (r < 0)
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering return -errno;
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek return 0;
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek}
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek
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;
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek uint32_t ret;
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek int r;
23ea3dab15181a3966ec45fa2ccbb81e59d2e0a7Zbigniew Jędrzejewski-Szmek
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert(bus);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert(name);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek r = sd_bus_call_method(
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek bus,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
23ea3dab15181a3966ec45fa2ccbb81e59d2e0a7Zbigniew Jędrzejewski-Szmek "/org/freedesktop/DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "ReleaseName",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek NULL,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek &reply,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "s",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read(reply, "u", &ret);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (ret == BUS_NAME_NON_EXISTENT)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return -ESRCH;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (ret == BUS_NAME_NOT_OWNER)
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering return -EADDRINUSE;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (ret == BUS_NAME_RELEASED)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
23ea3dab15181a3966ec45fa2ccbb81e59d2e0a7Zbigniew Jędrzejewski-Szmek return -EINVAL;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering}
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(bus, -EINVAL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert_return(name, -EINVAL);
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
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (!BUS_IS_OPEN(bus->state))
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return -ENOTCONN;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (bus->is_kernel)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_release_name_kernel(bus, name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek else
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_release_name_dbus1(bus, name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek}
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
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 struct kdbus_name_info *name;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek uint64_t previous_id = 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek int r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek /* Caller will free half-constructed list on failure... */
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek cmd.flags = flags;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return -errno;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek KDBUS_ITEM_FOREACH(name, name_list, names) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek struct kdbus_item *item;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek const char *entry_name = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek char *n;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = -ENOMEM;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek goto fail;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = strv_consume(x, n);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek goto fail;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek previous_id = name->owner_id;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering KDBUS_ITEM_FOREACH(item, name, items)
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering if (item->type == KDBUS_ITEM_OWNED_NAME)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek entry_name = item->name.name;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (entry_name && service_name_is_valid(entry_name)) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = strv_extend(x, entry_name);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = -ENOMEM;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek goto fail;
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering }
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering }
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
30374ebe5e9f0b37e99dcbdc965c00fcf542f89dLennart Poettering r = 0;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekfail:
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek bus_kernel_cmd_free(bus, cmd.offset);
e9c1ea9de87d4d508ac38ce87a2fa56e7529a91aJason St. John return r;
9d458c0902cdc5d993fd2f78d36fb83a8130c81bLennart Poettering}
9d458c0902cdc5d993fd2f78d36fb83a8130c81bLennart Poettering
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;
e9c1ea9de87d4d508ac38ce87a2fa56e7529a91aJason St. John int r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (acquired) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek return r;
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek }
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek
c099716487df4a4f5394e57e7ca14da1d358166aZbigniew Jędrzejewski-Szmek if (activatable) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek *activatable = y;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek y = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (acquired) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek *acquired = x;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek x = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return 0;
df49ccafc0d57c731a3da3014ad55d5bb9ed3e1bMantas Mikulėnas}
df49ccafc0d57c731a3da3014ad55d5bb9ed3e1bMantas Mikulėnas
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 int r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (acquired) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_call_method(
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek bus,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "/org/freedesktop/DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "ListNames",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek NULL,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek &reply,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek NULL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read_strv(reply, &x);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek if (r < 0)
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek reply = sd_bus_message_unref(reply);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (activatable) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_call_method(
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek bus,
ed6556920c1a6cdfe0bb04e806bc1f54ea191545Mantas Mikulėnas "org.freedesktop.DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "/org/freedesktop/DBus",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek "org.freedesktop.DBus",
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering "ListActivatableNames",
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek NULL,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek &reply,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek NULL);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read_strv(reply, &y);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (r < 0)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek *activatable = y;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek y = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (acquired) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek *acquired = x;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek x = NULL;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek return 0;
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek}
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert_return(bus, -EINVAL);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert_return(acquired || activatable, -EINVAL);
5e65c93a433447b15180249166f7b3944c3e6156Zbigniew Jędrzejewski-Szmek assert_return(!bus_pid_changed(bus), -ECHILD);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (!BUS_IS_OPEN(bus->state))
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return -ENOTCONN;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering if (bus->is_kernel)
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_list_names_kernel(bus, acquired, activatable);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek else
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek return bus_list_names_dbus1(bus, acquired, activatable);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek}
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmekstatic int bus_populate_creds_from_items(
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek sd_bus *bus,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek struct kdbus_info *info,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek uint64_t mask,
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek sd_bus_creds *c) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek struct kdbus_item *item;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek uint64_t m;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek int r;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert(bus);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert(info);
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek assert(c);
eceb8483e5a02e8e337486b89719a3b99cfcb7ceLennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek KDBUS_ITEM_FOREACH(item, info, items) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek switch (item->type) {
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek case KDBUS_ITEM_PIDS:
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
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 c->mask |= SD_BUS_CREDS_PID;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
2c408cb6276e3b8d18fb4e2a81a1128d8bbaa70dLennart Poettering c->tid = (pid_t) item->pids.tid;
2c408cb6276e3b8d18fb4e2a81a1128d8bbaa70dLennart Poettering c->mask |= SD_BUS_CREDS_TID;
2c408cb6276e3b8d18fb4e2a81a1128d8bbaa70dLennart Poettering }
2c408cb6276e3b8d18fb4e2a81a1128d8bbaa70dLennart Poettering
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek if (mask & SD_BUS_CREDS_PID_STARTTIME && item->pids.starttime > 0) {
eceb8483e5a02e8e337486b89719a3b99cfcb7ceLennart Poettering c->pid_starttime = item->pids.starttime;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->mask |= SD_BUS_CREDS_PID_STARTTIME;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek break;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek case KDBUS_ITEM_CREDS:
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
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 c->mask |= SD_BUS_CREDS_UID;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2c408cb6276e3b8d18fb4e2a81a1128d8bbaa70dLennart Poettering
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 c->mask |= SD_BUS_CREDS_EUID;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
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 c->mask |= SD_BUS_CREDS_SUID;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek }
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek
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;
2ca0435be9359bde3020eeb528c2a6d72ac1e0b0Zbigniew Jędrzejewski-Szmek c->mask |= SD_BUS_CREDS_FSUID;
}
if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != (gid_t) -1) {
c->gid = (gid_t) item->creds.gid;
c->mask |= SD_BUS_CREDS_GID;
}
if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != (gid_t) -1) {
c->egid = (gid_t) item->creds.egid;
c->mask |= SD_BUS_CREDS_EGID;
}
if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != (gid_t) -1) {
c->sgid = (gid_t) item->creds.sgid;
c->mask |= SD_BUS_CREDS_SGID;
}
if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != (gid_t) -1) {
c->fsgid = (gid_t) item->creds.fsgid;
c->mask |= SD_BUS_CREDS_FSGID;
}
break;
case KDBUS_ITEM_PID_COMM:
if (mask & SD_BUS_CREDS_COMM) {
r = free_and_strdup(&c->comm, item->str);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_COMM;
}
break;
case KDBUS_ITEM_TID_COMM:
if (mask & SD_BUS_CREDS_TID_COMM) {
r = free_and_strdup(&c->tid_comm, item->str);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_TID_COMM;
}
break;
case KDBUS_ITEM_EXE:
if (mask & SD_BUS_CREDS_EXE) {
r = free_and_strdup(&c->exe, item->str);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_EXE;
}
break;
case KDBUS_ITEM_CMDLINE:
if (mask & SD_BUS_CREDS_CMDLINE) {
c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
c->cmdline = memdup(item->data, c->cmdline_size);
if (!c->cmdline)
return -ENOMEM;
c->mask |= SD_BUS_CREDS_CMDLINE;
}
break;
case KDBUS_ITEM_CGROUP:
m = (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) & mask;
if (m) {
r = free_and_strdup(&c->cgroup, item->str);
if (r < 0)
return r;
r = bus_get_root_path(bus);
if (r < 0)
return r;
r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
if (r < 0)
return r;
c->mask |= m;
}
break;
case KDBUS_ITEM_CAPS:
m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
if (m) {
c->capability_size = item->size - offsetof(struct kdbus_item, caps.caps);
c->capability = memdup(item->caps.caps, c->capability_size);
if (!c->capability)
return -ENOMEM;
c->mask |= m;
}
break;
case KDBUS_ITEM_SECLABEL:
if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
r = free_and_strdup(&c->label, item->str);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
}
break;
case KDBUS_ITEM_AUDIT:
if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
c->audit_session_id = (uint32_t) item->audit.sessionid;
c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
}
if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != (uid_t) -1) {
c->audit_login_uid = (uid_t) item->audit.loginuid;
c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
}
break;
case KDBUS_ITEM_OWNED_NAME:
if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
r = strv_extend(&c->well_known_names, item->name.name);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
}
break;
case KDBUS_ITEM_CONN_DESCRIPTION:
if (mask & SD_BUS_CREDS_DESCRIPTION) {
r = free_and_strdup(&c->description, item->str);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_DESCRIPTION;
}
break;
case KDBUS_ITEM_AUXGROUPS:
if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
size_t n;
uid_t *g;
assert_cc(sizeof(gid_t) == sizeof(uint32_t));
n = (item->size - offsetof(struct kdbus_item, data32)) / sizeof(uint32_t);
g = newdup(gid_t, item->data32, n);
if (!g)
return -ENOMEM;
free(c->supplementary_gids);
c->supplementary_gids = g;
c->n_supplementary_gids = n;
c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
}
break;
}
}
return 0;
}
static int bus_get_name_creds_kdbus(
sd_bus *bus,
const char *name,
uint64_t mask,
sd_bus_creds **creds) {
_cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
struct kdbus_cmd_info *cmd;
struct kdbus_info *conn_info;
size_t size, l;
uint64_t id;
int r;
r = bus_kernel_parse_unique_name(name, &id);
if (r < 0)
return r;
if (r > 0) {
size = offsetof(struct kdbus_cmd_info, items);
cmd = alloca0_align(size, 8);
cmd->id = id;
} else {
l = strlen(name) + 1;
size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
cmd = alloca0_align(size, 8);
cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
cmd->items[0].type = KDBUS_ITEM_NAME;
memcpy(cmd->items[0].str, name, l);
}
cmd->size = size;
cmd->flags = attach_flags_to_kdbus(mask);
/* If augmentation is on, and the bus doesn't didn't allow us
* to get the bits we want, then ask for the PID/TID so that we
* can read the rest from /proc. */
if ((mask & SD_BUS_CREDS_AUGMENT) &&
(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
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|
SD_BUS_CREDS_SELINUX_CONTEXT|
SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
cmd->flags |= KDBUS_ATTACH_PIDS;
r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
if (r < 0)
return -errno;
conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
/* Non-activated names are considered not available */
if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
if (name[0] == ':')
r = -ENXIO;
else
r = -ESRCH;
goto fail;
}
c = bus_creds_new();
if (!c) {
r = -ENOMEM;
goto fail;
}
if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
r = -ENOMEM;
goto fail;
}
c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
}
/* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
them in case the service has no names. This does not mean
however that the list of owned names could not be
acquired. Hence, let's explicitly clarify that the data is
complete. */
c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
r = bus_populate_creds_from_items(bus, conn_info, mask, c);
if (r < 0)
goto fail;
r = bus_creds_add_more(c, mask, 0, 0);
if (r < 0)
goto fail;
if (creds) {
*creds = c;
c = NULL;
}
r = 0;
fail:
bus_kernel_cmd_free(bus, cmd->offset);
return r;
}
static int bus_get_name_creds_dbus1(
sd_bus *bus,
const char *name,
uint64_t mask,
sd_bus_creds **creds) {
_cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
_cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
const char *unique = NULL;
pid_t pid = 0;
int r;
/* Only query the owner if the caller wants to know it or if
* the caller just wants to check whether a name exists */
if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
r = sd_bus_call_method(
bus,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"GetNameOwner",
NULL,
&reply_unique,
"s",
name);
if (r < 0)
return r;
r = sd_bus_message_read(reply_unique, "s", &unique);
if (r < 0)
return r;
}
if (mask != 0) {
c = bus_creds_new();
if (!c)
return -ENOMEM;
if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
c->unique_name = strdup(unique);
if (!c->unique_name)
return -ENOMEM;
c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
}
if ((mask & SD_BUS_CREDS_PID) ||
((mask & SD_BUS_CREDS_AUGMENT) &&
(mask & (SD_BUS_CREDS_PID_STARTTIME|
SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
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|
SD_BUS_CREDS_SELINUX_CONTEXT|
SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
uint32_t u;
r = sd_bus_call_method(
bus,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"GetConnectionUnixProcessID",
NULL,
&reply,
"s",
unique ? unique : name);
if (r < 0)
return r;
r = sd_bus_message_read(reply, "u", &u);
if (r < 0)
return r;
pid = u;
if (mask & SD_BUS_CREDS_PID) {
c->pid = u;
c->mask |= SD_BUS_CREDS_PID;
}
reply = sd_bus_message_unref(reply);
}
if (mask & SD_BUS_CREDS_UID) {
uint32_t u;
r = sd_bus_call_method(
bus,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"GetConnectionUnixUser",
NULL,
&reply,
"s",
unique ? unique : name);
if (r < 0)
return r;
r = sd_bus_message_read(reply, "u", &u);
if (r < 0)
return r;
c->uid = u;
c->mask |= SD_BUS_CREDS_UID;
reply = sd_bus_message_unref(reply);
}
if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
const void *p = NULL;
size_t sz = 0;
r = sd_bus_call_method(
bus,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"GetConnectionSELinuxSecurityContext",
&error,
&reply,
"s",
unique ? unique : name);
if (r < 0) {
if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
return r;
} else {
r = sd_bus_message_read_array(reply, 'y', &p, &sz);
if (r < 0)
return r;
c->label = strndup(p, sz);
if (!c->label)
return -ENOMEM;
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
}
}
r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
return r;
}
if (creds) {
*creds = c;
c = NULL;
}
return 0;
}
_public_ int sd_bus_get_name_creds(
sd_bus *bus,
const char *name,
uint64_t mask,
sd_bus_creds **creds) {
assert_return(bus, -EINVAL);
assert_return(name, -EINVAL);
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
assert_return(mask == 0 || creds, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
assert_return(service_name_is_valid(name), -EINVAL);
assert_return(bus->bus_client, -ENODATA);
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->is_kernel)
return bus_get_name_creds_kdbus(bus, name, mask, creds);
else
return bus_get_name_creds_dbus1(bus, name, mask, creds);
}
static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
_cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
struct kdbus_cmd_info cmd = {
.size = sizeof(struct kdbus_cmd_info)
};
struct kdbus_info *creator_info;
pid_t pid = 0;
int r;
c = bus_creds_new();
if (!c)
return -ENOMEM;
cmd.flags = attach_flags_to_kdbus(mask);
/* If augmentation is on, and the bus doesn't didn't allow us
* to get the bits we want, then ask for the PID/TID so that we
* can read the rest from /proc. */
if ((mask & SD_BUS_CREDS_AUGMENT) &&
(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
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|
SD_BUS_CREDS_SELINUX_CONTEXT|
SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
cmd.flags |= KDBUS_ATTACH_PIDS;
r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
if (r < 0)
return -errno;
creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
r = bus_populate_creds_from_items(bus, creator_info, mask, c);
bus_kernel_cmd_free(bus, cmd.offset);
if (r < 0)
return r;
r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
return r;
*ret = c;
c = NULL;
return 0;
}
static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
_cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
pid_t pid = 0;
int r;
if (!bus->ucred_valid && !isempty(bus->label))
return -ENODATA;
c = bus_creds_new();
if (!c)
return -ENOMEM;
if (bus->ucred_valid) {
if (bus->ucred.pid > 0) {
pid = c->pid = bus->ucred.pid;
c->mask |= SD_BUS_CREDS_PID & mask;
}
if (bus->ucred.uid != (uid_t) -1) {
c->uid = bus->ucred.uid;
c->mask |= SD_BUS_CREDS_UID & mask;
}
if (bus->ucred.gid != (gid_t) -1) {
c->gid = bus->ucred.gid;
c->mask |= SD_BUS_CREDS_GID & mask;
}
}
if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
c->label = strdup(bus->label);
if (!c->label)
return -ENOMEM;
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
}
r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
return r;
*ret = c;
c = NULL;
return 0;
}
_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
assert_return(bus, -EINVAL);
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
assert_return(ret, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (bus->is_kernel)
return bus_get_owner_creds_kdbus(bus, mask, ret);
else
return bus_get_owner_creds_dbus1(bus, mask, ret);
}
static int add_name_change_match(sd_bus *bus,
uint64_t cookie,
const char *name,
const char *old_owner,
const char *new_owner) {
uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
int is_name_id = -1, r;
struct kdbus_item *item;
assert(bus);
/* If we encounter a match that could match against
* NameOwnerChanged messages, then we need to create
* KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
* KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
* multiple if the match is underspecified.
*
* The NameOwnerChanged signals take three parameters with
* unique or well-known names, but only some forms actually
* exist:
*
* WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
* WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
* WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
* UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
* UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
*
* For the latter two the two unique names must be identical.
*
* */
if (name) {
is_name_id = bus_kernel_parse_unique_name(name, &name_id);
if (is_name_id < 0)
return 0;
}
if (!isempty(old_owner)) {
r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
if (r < 0)
return 0;
if (r == 0)
return 0;
if (is_name_id > 0 && old_owner_id != name_id)
return 0;
} else
old_owner_id = KDBUS_MATCH_ID_ANY;
if (!isempty(new_owner)) {
r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
if (r < 0)
return r;
if (r == 0)
return 0;
if (is_name_id > 0 && new_owner_id != name_id)
return 0;
} else
new_owner_id = KDBUS_MATCH_ID_ANY;
if (is_name_id <= 0) {
struct kdbus_cmd_match *m;
size_t sz, l;
/* If the name argument is missing or is a well-known
* name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
* matches for it */
l = name ? strlen(name) + 1 : 0;
sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
offsetof(struct kdbus_item, name_change) +
offsetof(struct kdbus_notify_name_change, name) +
l);
m = alloca0_align(sz, 8);
m->size = sz;
m->cookie = cookie;
item = m->items;
item->size =
offsetof(struct kdbus_item, name_change) +
offsetof(struct kdbus_notify_name_change, name) +
l;
item->name_change.old_id.id = old_owner_id;
item->name_change.new_id.id = new_owner_id;
if (name)
memcpy(item->name_change.name, name, l);
/* If the old name is unset or empty, then
* this can match against added names */
if (!old_owner || old_owner[0] == 0) {
item->type = KDBUS_ITEM_NAME_ADD;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
return -errno;
}
/* If the new name is unset or empty, then
* this can match against removed names */
if (!new_owner || new_owner[0] == 0) {
item->type = KDBUS_ITEM_NAME_REMOVE;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
return -errno;
}
/* The CHANGE match we need in either case, because
* what is reported as a name change by the kernel
* might just be an owner change between starter and
* normal clients. For userspace such a change should
* be considered a removal/addition, hence let's
* subscribe to this unconditionally. */
item->type = KDBUS_ITEM_NAME_CHANGE;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
return -errno;
}
if (is_name_id != 0) {
struct kdbus_cmd_match *m;
uint64_t sz;
/* If the name argument is missing or is a unique
* name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
* for it */
sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
offsetof(struct kdbus_item, id_change) +
sizeof(struct kdbus_notify_id_change));
m = alloca0_align(sz, 8);
m->size = sz;
m->cookie = cookie;
item = m->items;
item->size =
offsetof(struct kdbus_item, id_change) +
sizeof(struct kdbus_notify_id_change);
item->id_change.id = name_id;
/* If the old name is unset or empty, then this can
* match against added ids */
if (!old_owner || old_owner[0] == 0) {
item->type = KDBUS_ITEM_ID_ADD;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
return -errno;
}
/* If thew new name is unset or empty, then this can
* match against removed ids */
if (!new_owner || new_owner[0] == 0) {
item->type = KDBUS_ITEM_ID_REMOVE;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
return -errno;
}
}
return 0;
}
int bus_add_match_internal_kernel(
sd_bus *bus,
struct bus_match_component *components,
unsigned n_components,
uint64_t cookie) {
struct kdbus_cmd_match *m;
struct kdbus_item *item;
uint64_t *bloom;
size_t sz;
const char *sender = NULL;
size_t sender_length = 0;
uint64_t src_id = KDBUS_MATCH_ID_ANY;
bool using_bloom = false;
unsigned i;
bool matches_name_change = true;
const char *name_change_arg[3] = {};
int r;
assert(bus);
bloom = alloca0(bus->bloom_size);
sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
for (i = 0; i < n_components; i++) {
struct bus_match_component *c = &components[i];
switch (c->type) {
case BUS_MATCH_SENDER:
if (!streq(c->value_str, "org.freedesktop.DBus"))
matches_name_change = false;
r = bus_kernel_parse_unique_name(c->value_str, &src_id);
if (r < 0)
return r;
else if (r > 0)
sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
else {
sender = c->value_str;
sender_length = strlen(sender);
sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
}
break;
case BUS_MATCH_MESSAGE_TYPE:
if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
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;
break;
case BUS_MATCH_INTERFACE:
if (!streq(c->value_str, "org.freedesktop.DBus"))
matches_name_change = false;
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
using_bloom = true;
break;
case BUS_MATCH_MEMBER:
if (!streq(c->value_str, "NameOwnerChanged"))
matches_name_change = false;
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
using_bloom = true;
break;
case BUS_MATCH_PATH:
if (!streq(c->value_str, "/org/freedesktop/DBus"))
matches_name_change = false;
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
using_bloom = true;
break;
case BUS_MATCH_PATH_NAMESPACE:
if (!streq(c->value_str, "/")) {
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
using_bloom = true;
}
break;
case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
char buf[sizeof("arg")-1 + 2 + 1];
if (c->type - BUS_MATCH_ARG < 3)
name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
using_bloom = true;
break;
}
case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
using_bloom = true;
break;
}
case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
using_bloom = true;
break;
}
case BUS_MATCH_DESTINATION:
/* The bloom filter does not include
the destination, since it is only
available for broadcast messages
which do not carry a destination
since they are undirected. */
break;
case BUS_MATCH_ROOT:
case BUS_MATCH_VALUE:
case BUS_MATCH_LEAF:
case _BUS_MATCH_NODE_TYPE_MAX:
case _BUS_MATCH_NODE_TYPE_INVALID:
assert_not_reached("Invalid match type?");
}
}
if (using_bloom)
sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
m = alloca0_align(sz, 8);
m->size = sz;
m->cookie = cookie;
item = m->items;
if (src_id != KDBUS_MATCH_ID_ANY) {
item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
item->type = KDBUS_ITEM_ID;
item->id = src_id;
item = KDBUS_ITEM_NEXT(item);
}
if (using_bloom) {
item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
item->type = KDBUS_ITEM_BLOOM_MASK;
memcpy(item->data64, bloom, bus->bloom_size);
item = KDBUS_ITEM_NEXT(item);
}
if (sender) {
item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
item->type = KDBUS_ITEM_NAME;
memcpy(item->str, sender, sender_length + 1);
}
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
if (r < 0)
return -errno;
if (matches_name_change) {
/* If this match could theoretically match
* NameOwnerChanged messages, we need to
* install a second non-bloom filter explitly
* for it */
r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
if (r < 0)
return r;
}
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",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"AddMatch",
NULL,
NULL,
"s",
e);
}
int bus_add_match_internal(
sd_bus *bus,
const char *match,
struct bus_match_component *components,
unsigned n_components,
uint64_t cookie) {
assert(bus);
if (bus->is_kernel)
return bus_add_match_internal_kernel(bus, components, n_components, cookie);
else
return bus_add_match_internal_dbus1(bus, match);
}
int bus_remove_match_internal_kernel(
sd_bus *bus,
uint64_t cookie) {
struct kdbus_cmd_match m;
int r;
assert(bus);
zero(m);
m.size = offsetof(struct kdbus_cmd_match, items);
m.cookie = cookie;
r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
if (r < 0)
return -errno;
return 0;
}
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",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
"RemoveMatch",
NULL,
NULL,
"s",
e);
}
int bus_remove_match_internal(
sd_bus *bus,
const char *match,
uint64_t cookie) {
assert(bus);
if (bus->is_kernel)
return bus_remove_match_internal_kernel(bus, cookie);
else
return bus_remove_match_internal_dbus1(bus, match);
}
_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
const char *mid;
int r;
assert_return(bus, -EINVAL);
assert_return(name, -EINVAL);
assert_return(machine, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
assert_return(service_name_is_valid(name), -EINVAL);
if (!BUS_IS_OPEN(bus->state))
return -ENOTCONN;
if (streq_ptr(name, bus->unique_name))
return sd_id128_get_machine(machine);
r = sd_bus_message_new_method_call(
bus,
&m,
name,
"/",
"org.freedesktop.DBus.Peer",
"GetMachineId");
if (r < 0)
return r;
r = sd_bus_message_set_auto_start(m, false);
if (r < 0)
return r;
r = sd_bus_call(bus, m, 0, NULL, &reply);
if (r < 0)
return r;
r = sd_bus_message_read(reply, "s", &mid);
if (r < 0)
return r;
return sd_id128_from_string(mid, machine);
}