dbus.c revision 8fd00193803fd20bed163832ec4d0d5ba2958b87
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering This file is part of systemd.
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering Copyright 2010 Lennart Poettering
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering systemd is free software; you can redistribute it and/or modify it
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering under the terms of the GNU Lesser General Public License as published by
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering (at your option) any later version.
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering systemd is distributed in the hope that it will be useful, but
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering Lesser General Public License for more details.
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering You should have received a copy of the GNU Lesser General Public License
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
#include "mkdir.h"
#include "missing.h"
#include "dbus-unit.h"
#include "dbus-job.h"
#include "dbus-manager.h"
#include "dbus-execute.h"
#include "dbus-kill.h"
#include "dbus-cgroup.h"
#include "special.h"
#include "dbus.h"
#include "bus-util.h"
#include "bus-error.h"
#include "bus-errors.h"
#include "strxcpyx.h"
#include "bus-internal.h"
#include "selinux-access.h"
assert(m);
if (!m->queued_message)
static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *cgroup;
assert(m);
static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
m, name,
static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
const char *name;
Unit *u;
assert(m);
r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
goto failed;
goto failed;
if (u->refuse_manual_start) {
r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
goto failed;
goto failed;
r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
#ifdef HAVE_SELINUX
static int mac_selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Job *j;
u = j->unit;
static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Job *j;
assert(m);
*found = j;
Unit *u;
assert(m);
if (!message)
*unit = u;
static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
assert(m);
static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Unit *u;
assert(m);
*found = u;
static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Unit *u;
assert(m);
if (!unit_get_cgroup_context(u))
*found = u;
static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
CGroupContext *c;
Unit *u;
assert(m);
c = unit_get_cgroup_context(u);
*found = c;
static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
ExecContext *c;
Unit *u;
assert(m);
c = unit_get_exec_context(u);
*found = c;
static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
KillContext *c;
Unit *u;
assert(m);
c = unit_get_kill_context(u);
*found = c;
static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
Iterator i;
Job *j;
return -ENOMEM;
l[k] = job_dbus_path(j);
return -ENOMEM;
*nodes = l;
l = NULL;
static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
Iterator i;
Unit *u;
return -ENOMEM;
l[k] = unit_dbus_path(u);
return -ENOMEM;
*nodes = l;
l = NULL;
UnitType t;
assert(m);
#ifdef HAVE_SELINUX
r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
for (t = 0; t < _UNIT_TYPE_MAX; t++) {
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
assert(m);
r = sd_bus_add_match(
bus,
NULL,
"path='/org/freedesktop/DBus/Local',"
signal_disconnected, m);
assert(s);
assert(m);
if (nfd < 0) {
log_oom();
r = sd_bus_add_match(
bus,
NULL,
"interface='org.freedesktop.systemd1.Agent',"
"path='/org/freedesktop/systemd1/agent'",
assert(m);
assert(m);
/* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
r = sd_bus_add_match(
bus,
NULL,
"path='/org/freedesktop/DBus',"
r = sd_bus_add_match(
bus,
NULL,
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.systemd1.Activator',"
r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
if (m->api_bus)
assert(m);
r = sd_bus_add_match(
bus,
NULL,
"interface='org.freedesktop.systemd1.Agent',"
"path='/org/freedesktop/systemd1/agent'",
if (m->system_bus)
sd_event_source *s;
assert(m);
if (m->private_listen_fd >= 0)
if (m->kdbus_fd >= 0)
return -EHOSTDOWN;
if (fd < 0) {
return -errno;
return -errno;
return -errno;
m->private_listen_event_source = s;
if (try_bus_connect) {
r = bus_init_system(m);
r = bus_init_api(m);
r = bus_init_private(m);
Iterator i;
Job *j;
assert(m);
if (!*bus)
if (m->queued_message)
sd_bus *b;
assert(m);
if (m->api_bus)
if (m->system_bus)
destroy_bus(m, &b);
if (m->private_listen_event_source)
Iterator i;
sd_bus *b;
int fd;
assert(m);
if (m->api_bus) {
if (fd >= 0) {
if (fd < 0)
return fd;
if (fd >= 0) {
if (fd < 0)
return fd;
int bus_foreach_bus(
Manager *m,
void *userdata) {
Iterator i;
sd_bus *b;
int r, ret = 0;
ret = r;
ret = r;
return ret;
assert(f);
assert(l);
return -EINVAL;
return strv_extend(l, e);
assert(m);
assert(t);
assert(l);
STRV_FOREACH(i, *l) {
k = sd_bus_track_add_name(*t, *i);
strv_free(*l);
*l = NULL;
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, &m->polkit_registry, error);
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, &m->polkit_registry, error);
return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, &m->polkit_registry, error);