dbus.c revision 8f8f05a919355095518911135c3d630f4620a9b0
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2010 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poetteringstatic void destroy_bus(Manager *m, sd_bus **bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* If we cannot get rid of this message we won't dispatch any
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * D-Bus messages, so that we won't end up wanting to queue
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * another message. */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_warning("Failed to send queued message: %s", strerror(-r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering m->queued_message = sd_bus_message_unref(m->queued_message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_read(message, "s", &cgroup);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* If we are running as system manager, forward the
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler * message to the system bus */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_send(m->system_bus, message, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_warning("Failed to forward Released message: %s", strerror(-r));
178cc7700c23ac088cd7190d7854282075028d91Lennart Poetteringstatic int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_debug("Got disconnect on private connection.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *name, *old_owner, *new_owner;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_read(message, "s", &name);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_load_unit(m, name, NULL, &error, &u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Successfully queued, that's it for us */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_new_signal(bus, &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_error("Failed to respond with to bus activation request: %s", strerror(-r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Our own method calls are all protected individually with
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * selinux checks, but the built-in interfaces need to be
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * protected too. */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8Filipe Brandenburger path = sd_bus_message_get_path(message);
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek if (object_path_startswith("/org/freedesktop/systemd1", path)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = selinux_access_check(bus, message, verb, error);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = manager_get_job_from_dbus_path(m, path, &j);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering manager_load_unit_from_dbus_path(m, path, NULL, &u);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = selinux_unit_access_check(u, bus, message, verb, error);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = manager_get_job_from_dbus_path(m, path, &j);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering r = manager_load_unit_from_dbus_path(m, path, error, &u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen return find_unit(m, bus, path, (Unit**) found, error);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poetteringstatic int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
*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, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
r = sd_bus_add_fallback_vtable(bus, "/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, "/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, "/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, "/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, "/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, "/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,
"path='/org/freedesktop/DBus/Local',"
signal_disconnected, m);
assert(s);
assert(m);
if (nfd < 0) {
log_oom();
r = sd_bus_add_match(
bus,
"interface='org.freedesktop.systemd1.Agent',"
"path='/org/freedesktop/systemd1/agent'",
assert(m);
assert(m);
r = sd_bus_add_match(
bus,
"path='/org/freedesktop/DBus',"
r = sd_bus_add_match(
bus,
"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,
"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)
if (m->private_listen_fd >= 0) {
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(t);
assert(f);
assert(l);
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;