1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
26 #include <dbus/dbus.h>
34 #include "dbus-unit.h"
36 #include "dbus-manager.h"
37 #include "dbus-service.h"
38 #include "dbus-socket.h"
39 #include "dbus-target.h"
40 #include "dbus-device.h"
41 #include "dbus-mount.h"
42 #include "dbus-automount.h"
43 #include "dbus-snapshot.h"
44 #include "dbus-swap.h"
45 #include "dbus-timer.h"
46 #include "dbus-path.h"
47 #include "bus-errors.h"
49 #include "dbus-common.h"
51 #define CONNECTIONS_MAX 52
53 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
54 #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
55 /* Only used as a fallback */
56 #define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
58 static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
59 static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
61 const char *const bus_interface_table[] = {
62 "org.freedesktop.DBus.Properties", bus_properties_interface,
63 "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
64 "org.freedesktop.systemd1.Manager", bus_manager_interface,
65 "org.freedesktop.systemd1.Job", bus_job_interface,
66 "org.freedesktop.systemd1.Unit", bus_unit_interface,
67 "org.freedesktop.systemd1.Service", bus_service_interface,
68 "org.freedesktop.systemd1.Socket", bus_socket_interface,
69 "org.freedesktop.systemd1.Target", bus_target_interface,
70 "org.freedesktop.systemd1.Device", bus_device_interface,
71 "org.freedesktop.systemd1.Mount", bus_mount_interface,
72 "org.freedesktop.systemd1.Automount", bus_automount_interface,
73 "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface,
74 "org.freedesktop.systemd1.Swap", bus_swap_interface,
75 "org.freedesktop.systemd1.Timer", bus_timer_interface,
76 "org.freedesktop.systemd1.Path", bus_path_interface,
80 static void bus_done_api(Manager *m);
81 static void bus_done_system(Manager *m);
82 static void bus_done_private(Manager *m);
83 static void shutdown_connection(Manager *m, DBusConnection *c);
85 static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data) {
91 /* We maintain two sets, one for those connections where we
92 * requested a dispatch, and another where we didn't. And then,
93 * we move the connections between the two sets. */
95 if (status == DBUS_DISPATCH_COMPLETE)
96 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
98 set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
101 void bus_watch_event(Manager *m, Watch *w, int events) {
105 /* This is called by the event loop whenever there is
106 * something happening on D-Bus' file handles. */
108 if (!dbus_watch_get_enabled(w->data.bus_watch))
111 dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
114 static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
117 struct epoll_event ev;
122 if (!(w = new0(Watch, 1)))
125 w->fd = dbus_watch_get_unix_fd(bus_watch);
126 w->type = WATCH_DBUS_WATCH;
127 w->data.bus_watch = bus_watch;
130 ev.events = bus_flags_to_events(bus_watch);
133 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
135 if (errno != EEXIST) {
140 /* Hmm, bloody D-Bus creates multiple watches on the
141 * same fd. epoll() does not like that. As a dirty
142 * hack we simply dup() the fd and hence get a second
143 * one we can safely add to the epoll(). */
145 if ((w->fd = dup(w->fd)) < 0) {
150 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
151 close_nointr_nofail(w->fd);
156 w->fd_is_dupped = true;
159 dbus_watch_set_data(bus_watch, w, NULL);
164 static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
171 w = dbus_watch_get_data(bus_watch);
175 assert(w->type == WATCH_DBUS_WATCH);
176 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
179 close_nointr_nofail(w->fd);
184 static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
187 struct epoll_event ev;
192 w = dbus_watch_get_data(bus_watch);
196 assert(w->type == WATCH_DBUS_WATCH);
199 ev.events = bus_flags_to_events(bus_watch);
202 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
205 static int bus_timeout_arm(Manager *m, Watch *w) {
206 struct itimerspec its = {};
211 if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
212 timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
213 its.it_interval = its.it_value;
216 if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
222 void bus_timeout_event(Manager *m, Watch *w, int events) {
226 /* This is called by the event loop whenever there is
227 * something happening on D-Bus' file handles. */
229 if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
232 dbus_timeout_handle(w->data.bus_timeout);
235 static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
238 struct epoll_event ev;
243 if (!(w = new0(Watch, 1)))
246 if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
249 w->type = WATCH_DBUS_TIMEOUT;
250 w->data.bus_timeout = timeout;
252 if (bus_timeout_arm(m, w) < 0)
259 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
262 dbus_timeout_set_data(timeout, w, NULL);
268 close_nointr_nofail(w->fd);
274 static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
281 w = dbus_timeout_get_data(timeout);
285 assert(w->type == WATCH_DBUS_TIMEOUT);
287 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
288 close_nointr_nofail(w->fd);
292 static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
300 w = dbus_timeout_get_data(timeout);
304 assert(w->type == WATCH_DBUS_TIMEOUT);
306 if ((r = bus_timeout_arm(m, w)) < 0)
307 log_error("Failed to rearm timer: %s", strerror(-r));
310 static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
313 DBusMessage *reply = NULL;
319 dbus_error_init(&error);
321 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
322 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
323 log_debug("Got D-Bus request: %s.%s() on %s",
324 dbus_message_get_interface(message),
325 dbus_message_get_member(message),
326 dbus_message_get_path(message));
328 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
329 log_debug("API D-Bus connection terminated.");
332 } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
333 const char *name, *old_owner, *new_owner;
335 if (!dbus_message_get_args(message, &error,
336 DBUS_TYPE_STRING, &name,
337 DBUS_TYPE_STRING, &old_owner,
338 DBUS_TYPE_STRING, &new_owner,
340 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
342 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
343 log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
345 if (old_owner[0] == 0)
348 if (new_owner[0] == 0)
351 manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
353 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
356 if (!dbus_message_get_args(message, &error,
357 DBUS_TYPE_STRING, &name,
359 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
364 log_debug("Got D-Bus activation request for %s", name);
366 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
367 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
369 dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
371 r = manager_load_unit(m, name, NULL, &error, &u);
373 if (r >= 0 && u->refuse_manual_start)
377 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
381 const char *id, *text;
383 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
385 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
388 id = error.name ? error.name : bus_errno_to_dbus(r);
389 text = bus_error(&error, r);
391 if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
392 !dbus_message_append_args(reply,
393 DBUS_TYPE_STRING, &name,
394 DBUS_TYPE_STRING, &id,
395 DBUS_TYPE_STRING, &text,
400 /* On success we don't do anything, the service will be spawned now */
404 dbus_error_free(&error);
407 if (!bus_maybe_send_reply(connection, message, reply))
410 dbus_message_unref(reply);
413 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
417 dbus_message_unref(reply);
419 dbus_error_free(&error);
421 return DBUS_HANDLER_RESULT_NEED_MEMORY;
424 static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
432 dbus_error_init(&error);
434 if (m->api_bus != m->system_bus &&
435 (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
436 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
437 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
438 dbus_message_get_interface(message),
439 dbus_message_get_member(message),
440 dbus_message_get_path(message));
442 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
443 log_debug("System D-Bus connection terminated.");
446 } else if (m->running_as != SYSTEMD_SYSTEM &&
447 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
451 if (!dbus_message_get_args(message, &error,
452 DBUS_TYPE_STRING, &cgroup,
454 log_error("Failed to parse Released message: %s", bus_error_message(&error));
456 cgroup_notify_empty(m, cgroup);
459 dbus_error_free(&error);
460 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
463 static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
471 dbus_error_init(&error);
473 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
474 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
475 log_debug("Got D-Bus request: %s.%s() on %s",
476 dbus_message_get_interface(message),
477 dbus_message_get_member(message),
478 dbus_message_get_path(message));
480 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
481 shutdown_connection(m, connection);
482 else if (m->running_as == SYSTEMD_SYSTEM &&
483 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
487 if (!dbus_message_get_args(message, &error,
488 DBUS_TYPE_STRING, &cgroup,
490 log_error("Failed to parse Released message: %s", bus_error_message(&error));
492 cgroup_notify_empty(m, cgroup);
494 /* Forward the message to the system bus, so that user
495 * instances are notified as well */
498 dbus_connection_send(m->system_bus, message, NULL);
501 dbus_error_free(&error);
503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
506 unsigned bus_dispatch(Manager *m) {
511 if (m->queued_message) {
512 /* If we cannot get rid of this message we won't
513 * dispatch any D-Bus messages, so that we won't end
514 * up wanting to queue another message. */
516 if (m->queued_message_connection)
517 if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
520 dbus_message_unref(m->queued_message);
521 m->queued_message = NULL;
522 m->queued_message_connection = NULL;
525 if ((c = set_first(m->bus_connections_for_dispatch))) {
526 if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
527 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
535 static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
539 dbus_error_init(&error);
541 assert_se(reply = dbus_pending_call_steal_reply(pending));
543 switch (dbus_message_get_type(reply)) {
545 case DBUS_MESSAGE_TYPE_ERROR:
547 assert_se(dbus_set_error_from_message(&error, reply));
548 log_warning("RequestName() failed: %s", bus_error_message(&error));
551 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
554 if (!dbus_message_get_args(reply,
556 DBUS_TYPE_UINT32, &r,
557 DBUS_TYPE_INVALID)) {
558 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
563 log_debug("Successfully acquired name.");
565 log_error("Name already owned.");
571 assert_not_reached("Invalid reply message");
574 dbus_message_unref(reply);
575 dbus_error_free(&error);
578 static int request_name(Manager *m) {
579 const char *name = "org.freedesktop.systemd1";
580 /* Allow replacing of our name, to ease implementation of
581 * reexecution, where we keep the old connection open until
582 * after the new connection is set up and the name installed
583 * to allow clients to synchronously wait for reexecution to
585 uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
586 DBusMessage *message = NULL;
587 DBusPendingCall *pending = NULL;
589 if (!(message = dbus_message_new_method_call(
596 if (!dbus_message_append_args(
598 DBUS_TYPE_STRING, &name,
599 DBUS_TYPE_UINT32, &flags,
603 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
606 if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
609 dbus_message_unref(message);
610 dbus_pending_call_unref(pending);
612 /* We simple ask for the name and don't wait for it. Sooner or
613 * later we'll have it. */
619 dbus_pending_call_cancel(pending);
620 dbus_pending_call_unref(pending);
624 dbus_message_unref(message);
629 static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
632 Manager *m = userdata;
636 dbus_error_init(&error);
638 assert_se(reply = dbus_pending_call_steal_reply(pending));
640 switch (dbus_message_get_type(reply)) {
642 case DBUS_MESSAGE_TYPE_ERROR:
644 assert_se(dbus_set_error_from_message(&error, reply));
645 log_warning("ListNames() failed: %s", bus_error_message(&error));
648 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
652 if ((r = bus_parse_strv(reply, &l)) < 0)
653 log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
658 /* This is a bit hacky, we say the
659 * owner of the name is the name
660 * itself, because we don't want the
661 * extra traffic to figure out the
663 manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
672 assert_not_reached("Invalid reply message");
675 dbus_message_unref(reply);
676 dbus_error_free(&error);
679 static int query_name_list(Manager *m) {
680 DBusMessage *message = NULL;
681 DBusPendingCall *pending = NULL;
683 /* Asks for the currently installed bus names */
685 if (!(message = dbus_message_new_method_call(
692 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
695 if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
698 dbus_message_unref(message);
699 dbus_pending_call_unref(pending);
701 /* We simple ask for the list and don't wait for it. Sooner or
702 * later we'll get it. */
708 dbus_pending_call_cancel(pending);
709 dbus_pending_call_unref(pending);
713 dbus_message_unref(message);
718 static int bus_setup_loop(Manager *m, DBusConnection *bus) {
722 dbus_connection_set_exit_on_disconnect(bus, FALSE);
724 if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
725 !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
728 if (set_put(m->bus_connections_for_dispatch, bus) < 0)
731 dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
735 static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
736 return uid == 0 || uid == geteuid();
739 static void bus_new_connection(
741 DBusConnection *new_connection,
748 if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
749 log_error("Too many concurrent connections.");
753 dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
755 if (bus_setup_loop(m, new_connection) < 0)
758 if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
759 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
760 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
761 !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
766 log_debug("Accepted connection on private bus.");
768 dbus_connection_ref(new_connection);
771 static int init_registered_system_bus(Manager *m) {
774 if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
777 if (m->running_as != SYSTEMD_SYSTEM) {
780 dbus_error_init(&error);
782 dbus_bus_add_match(m->system_bus,
784 "interface='org.freedesktop.systemd1.Agent',"
786 "path='/org/freedesktop/systemd1/agent'",
789 if (dbus_error_is_set(&error)) {
790 log_error("Failed to register match: %s", bus_error_message(&error));
791 dbus_error_free(&error);
796 log_debug("Successfully connected to system D-Bus bus %s as %s",
797 strnull((id = dbus_connection_get_server_id(m->system_bus))),
798 strnull(dbus_bus_get_unique_name(m->system_bus)));
804 static int init_registered_api_bus(Manager *m) {
807 if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
808 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
809 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
810 !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
813 /* Get NameOwnerChange messages */
814 dbus_bus_add_match(m->api_bus,
816 "sender='"DBUS_SERVICE_DBUS"',"
817 "interface='"DBUS_INTERFACE_DBUS"',"
818 "member='NameOwnerChanged',"
819 "path='"DBUS_PATH_DBUS"'",
822 /* Get activation requests */
823 dbus_bus_add_match(m->api_bus,
825 "sender='"DBUS_SERVICE_DBUS"',"
826 "interface='org.freedesktop.systemd1.Activator',"
827 "member='ActivationRequest',"
828 "path='"DBUS_PATH_DBUS"'",
835 r = query_name_list(m);
839 if (m->running_as == SYSTEMD_USER) {
841 log_debug("Successfully connected to API D-Bus bus %s as %s",
842 strnull((id = dbus_connection_get_server_id(m->api_bus))),
843 strnull(dbus_bus_get_unique_name(m->api_bus)));
846 log_debug("Successfully initialized API on the system bus");
851 static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
852 Manager *m = userdata;
853 DBusConnection **conn;
859 dbus_error_init(&error);
861 conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
862 assert(conn == &m->system_bus || conn == &m->api_bus);
864 reply = dbus_pending_call_steal_reply(pending);
866 switch (dbus_message_get_type(reply)) {
867 case DBUS_MESSAGE_TYPE_ERROR:
868 assert_se(dbus_set_error_from_message(&error, reply));
869 log_warning("Failed to register to bus: %s", bus_error_message(&error));
872 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
873 if (!dbus_message_get_args(reply, &error,
874 DBUS_TYPE_STRING, &name,
875 DBUS_TYPE_INVALID)) {
876 log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
881 log_debug("Received name %s in reply to Hello", name);
882 if (!dbus_bus_set_unique_name(*conn, name)) {
883 log_error("Failed to set unique name");
888 if (conn == &m->system_bus) {
889 r = init_registered_system_bus(m);
890 if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
891 r = init_registered_api_bus(m);
893 r = init_registered_api_bus(m);
897 assert_not_reached("Invalid reply message");
900 dbus_message_unref(reply);
901 dbus_error_free(&error);
904 if (conn == &m->system_bus) {
905 log_debug("Failed setting up the system bus");
908 log_debug("Failed setting up the API bus");
914 static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
915 DBusMessage *message = NULL;
916 DBusPendingCall *pending = NULL;
918 message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
925 if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
928 if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
931 if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
934 dbus_message_unref(message);
935 dbus_pending_call_unref(pending);
940 dbus_pending_call_cancel(pending);
941 dbus_pending_call_unref(pending);
945 dbus_message_unref(message);
950 static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
952 DBusConnection *connection;
956 case DBUS_BUS_SYSTEM:
957 address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
958 if (!address || !address[0])
959 address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
961 case DBUS_BUS_SESSION:
962 address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
963 if (!address || !address[0])
964 address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
967 assert_not_reached("Invalid bus type");
970 dbus_error_init(&error);
972 connection = dbus_connection_open_private(address, &error);
974 log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
981 dbus_error_free(&error);
985 static int bus_init_system(Manager *m) {
991 m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
992 if (!m->system_bus) {
993 log_debug("Failed to connect to system D-Bus, retrying later");
998 r = bus_setup_loop(m, m->system_bus);
1002 r = manager_bus_async_register(m, &m->system_bus);
1013 static int bus_init_api(Manager *m) {
1019 if (m->running_as == SYSTEMD_SYSTEM) {
1020 m->api_bus = m->system_bus;
1021 /* In this mode there is no distinct connection to the API bus,
1022 * the API is published on the system bus.
1023 * bus_register_cb() is aware of that and will init the API
1024 * when the system bus gets registered.
1025 * No need to setup anything here. */
1029 m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
1031 log_debug("Failed to connect to API D-Bus, retrying later");
1036 r = bus_setup_loop(m, m->api_bus);
1040 r = manager_bus_async_register(m, &m->api_bus);
1051 static int bus_init_private(Manager *m) {
1054 static const char *const external_only[] = {
1061 dbus_error_init(&error);
1066 if (m->running_as == SYSTEMD_SYSTEM) {
1068 /* We want the private bus only when running as init */
1072 unlink("/run/systemd/private");
1073 m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
1079 e = secure_getenv("XDG_RUNTIME_DIR");
1083 if (asprintf(&p, "%s/systemd/private", e) < 0) {
1088 mkdir_parents_label(p, 0755);
1092 escaped = dbus_address_escape_value(e);
1097 if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) {
1104 m->private_bus = dbus_server_listen(p, &error);
1108 if (!m->private_bus) {
1109 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
1114 if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1115 !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1116 !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
1121 dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1123 log_debug("Successfully created private D-Bus server.");
1128 bus_done_private(m);
1129 dbus_error_free(&error);
1134 int bus_init(Manager *m, bool try_bus_connect) {
1137 if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1138 set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1141 if (m->name_data_slot < 0)
1142 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1145 if (m->conn_data_slot < 0)
1146 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1149 if (m->subscribed_data_slot < 0)
1150 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1153 if (try_bus_connect) {
1154 if ((r = bus_init_system(m)) < 0 ||
1155 (r = bus_init_api(m)) < 0)
1159 if ((r = bus_init_private(m)) < 0)
1167 static void shutdown_connection(Manager *m, DBusConnection *c) {
1172 HASHMAP_FOREACH(j, m->jobs, i) {
1173 JobBusClient *cl, *nextcl;
1174 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1176 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
1182 set_remove(m->bus_connections, c);
1183 set_remove(m->bus_connections_for_dispatch, c);
1185 if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
1188 while ((t = set_steal_first(s)))
1194 if (m->queued_message_connection == c) {
1195 m->queued_message_connection = NULL;
1197 if (m->queued_message) {
1198 dbus_message_unref(m->queued_message);
1199 m->queued_message = NULL;
1203 dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1204 /* system manager cannot afford to block on DBus */
1205 if (m->running_as != SYSTEMD_SYSTEM)
1206 dbus_connection_flush(c);
1207 dbus_connection_close(c);
1208 dbus_connection_unref(c);
1211 static void bus_done_api(Manager *m) {
1215 if (m->running_as == SYSTEMD_USER)
1216 shutdown_connection(m, m->api_bus);
1220 if (m->queued_message) {
1221 dbus_message_unref(m->queued_message);
1222 m->queued_message = NULL;
1226 static void bus_done_system(Manager *m) {
1230 if (m->running_as == SYSTEMD_SYSTEM)
1233 shutdown_connection(m, m->system_bus);
1234 m->system_bus = NULL;
1237 static void bus_done_private(Manager *m) {
1238 if (!m->private_bus)
1241 dbus_server_disconnect(m->private_bus);
1242 dbus_server_unref(m->private_bus);
1243 m->private_bus = NULL;
1246 void bus_done(Manager *m) {
1251 bus_done_private(m);
1253 while ((c = set_steal_first(m->bus_connections)))
1254 shutdown_connection(m, c);
1256 while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1257 shutdown_connection(m, c);
1259 set_free(m->bus_connections);
1260 set_free(m->bus_connections_for_dispatch);
1262 if (m->name_data_slot >= 0)
1263 dbus_pending_call_free_data_slot(&m->name_data_slot);
1265 if (m->conn_data_slot >= 0)
1266 dbus_pending_call_free_data_slot(&m->conn_data_slot);
1268 if (m->subscribed_data_slot >= 0)
1269 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1272 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1273 Manager *m = userdata;
1278 dbus_error_init(&error);
1280 assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1281 assert_se(reply = dbus_pending_call_steal_reply(pending));
1283 switch (dbus_message_get_type(reply)) {
1285 case DBUS_MESSAGE_TYPE_ERROR:
1287 assert_se(dbus_set_error_from_message(&error, reply));
1288 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1291 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1294 if (!dbus_message_get_args(reply,
1296 DBUS_TYPE_UINT32, &r,
1297 DBUS_TYPE_INVALID)) {
1298 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1302 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1307 assert_not_reached("Invalid reply message");
1310 dbus_message_unref(reply);
1311 dbus_error_free(&error);
1314 int bus_query_pid(Manager *m, const char *name) {
1315 DBusMessage *message = NULL;
1316 DBusPendingCall *pending = NULL;
1322 if (!(message = dbus_message_new_method_call(
1325 DBUS_INTERFACE_DBUS,
1326 "GetConnectionUnixProcessID")))
1329 if (!(dbus_message_append_args(
1331 DBUS_TYPE_STRING, &name,
1332 DBUS_TYPE_INVALID)))
1335 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1338 if (!(n = strdup(name)))
1341 if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1346 if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1349 dbus_message_unref(message);
1350 dbus_pending_call_unref(pending);
1358 dbus_pending_call_cancel(pending);
1359 dbus_pending_call_unref(pending);
1363 dbus_message_unref(message);
1368 int bus_broadcast(Manager *m, DBusMessage *message) {
1376 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1377 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1378 oom = !dbus_connection_send(c, message, NULL);
1380 SET_FOREACH(c, m->bus_connections, i)
1381 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1382 oom = !dbus_connection_send(c, message, NULL);
1384 return oom ? -ENOMEM : 0;
1387 bool bus_has_subscriber(Manager *m) {
1393 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1394 if (bus_connection_has_subscriber(m, c))
1397 SET_FOREACH(c, m->bus_connections, i)
1398 if (bus_connection_has_subscriber(m, c))
1404 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1408 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1411 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1418 /* When we are about to reexecute we add all D-Bus fds to the
1419 * set to pass over to the newly executed systemd. They won't
1420 * be used there however, except that they are closed at the
1421 * very end of deserialization, those making it possible for
1422 * clients to synchronously wait for systemd to reexec by
1423 * simply waiting for disconnection */
1425 SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1428 if (dbus_connection_get_unix_fd(c, &fd)) {
1429 fd = fdset_put_dup(fds, fd);
1436 SET_FOREACH(c, m->bus_connections, i) {
1439 if (dbus_connection_get_unix_fd(c, &fd)) {
1440 fd = fdset_put_dup(fds, fd);
1450 void bus_broadcast_finished(
1452 usec_t firmware_usec,
1456 usec_t userspace_usec,
1457 usec_t total_usec) {
1459 DBusMessage *message;
1463 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1469 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1470 if (!dbus_message_append_args(message,
1471 DBUS_TYPE_UINT64, &firmware_usec,
1472 DBUS_TYPE_UINT64, &loader_usec,
1473 DBUS_TYPE_UINT64, &kernel_usec,
1474 DBUS_TYPE_UINT64, &initrd_usec,
1475 DBUS_TYPE_UINT64, &userspace_usec,
1476 DBUS_TYPE_UINT64, &total_usec,
1477 DBUS_TYPE_INVALID)) {
1483 if (bus_broadcast(m, message) < 0) {
1490 dbus_message_unref(message);