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>
33 #include "dbus-unit.h"
35 #include "dbus-manager.h"
36 #include "dbus-service.h"
37 #include "dbus-socket.h"
38 #include "dbus-target.h"
39 #include "dbus-device.h"
40 #include "dbus-mount.h"
41 #include "dbus-automount.h"
42 #include "dbus-snapshot.h"
43 #include "dbus-swap.h"
44 #include "dbus-timer.h"
45 #include "dbus-path.h"
46 #include "bus-errors.h"
48 #include "dbus-common.h"
50 #define CONNECTIONS_MAX 52
52 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
53 #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
54 /* Only used as a fallback */
55 #define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
57 static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
58 static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
60 const char *const bus_interface_table[] = {
61 "org.freedesktop.DBus.Properties", bus_properties_interface,
62 "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
63 "org.freedesktop.systemd1.Manager", bus_manager_interface,
64 "org.freedesktop.systemd1.Job", bus_job_interface,
65 "org.freedesktop.systemd1.Unit", bus_unit_interface,
66 "org.freedesktop.systemd1.Service", bus_service_interface,
67 "org.freedesktop.systemd1.Socket", bus_socket_interface,
68 "org.freedesktop.systemd1.Target", bus_target_interface,
69 "org.freedesktop.systemd1.Device", bus_device_interface,
70 "org.freedesktop.systemd1.Mount", bus_mount_interface,
71 "org.freedesktop.systemd1.Automount", bus_automount_interface,
72 "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface,
73 "org.freedesktop.systemd1.Swap", bus_swap_interface,
74 "org.freedesktop.systemd1.Timer", bus_timer_interface,
75 "org.freedesktop.systemd1.Path", bus_path_interface,
79 static void bus_done_api(Manager *m);
80 static void bus_done_system(Manager *m);
81 static void bus_done_private(Manager *m);
82 static void shutdown_connection(Manager *m, DBusConnection *c);
84 static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data) {
90 /* We maintain two sets, one for those connections where we
91 * requested a dispatch, and another where we didn't. And then,
92 * we move the connections between the two sets. */
94 if (status == DBUS_DISPATCH_COMPLETE)
95 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
97 set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
100 void bus_watch_event(Manager *m, Watch *w, int events) {
104 /* This is called by the event loop whenever there is
105 * something happening on D-Bus' file handles. */
107 if (!dbus_watch_get_enabled(w->data.bus_watch))
110 dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
113 static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
116 struct epoll_event ev;
121 if (!(w = new0(Watch, 1)))
124 w->fd = dbus_watch_get_unix_fd(bus_watch);
125 w->type = WATCH_DBUS_WATCH;
126 w->data.bus_watch = bus_watch;
129 ev.events = bus_flags_to_events(bus_watch);
132 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
134 if (errno != EEXIST) {
139 /* Hmm, bloody D-Bus creates multiple watches on the
140 * same fd. epoll() does not like that. As a dirty
141 * hack we simply dup() the fd and hence get a second
142 * one we can safely add to the epoll(). */
144 if ((w->fd = dup(w->fd)) < 0) {
149 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
150 close_nointr_nofail(w->fd);
155 w->fd_is_dupped = true;
158 dbus_watch_set_data(bus_watch, w, NULL);
163 static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
170 w = dbus_watch_get_data(bus_watch);
174 assert(w->type == WATCH_DBUS_WATCH);
175 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
178 close_nointr_nofail(w->fd);
183 static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
186 struct epoll_event ev;
191 w = dbus_watch_get_data(bus_watch);
195 assert(w->type == WATCH_DBUS_WATCH);
198 ev.events = bus_flags_to_events(bus_watch);
201 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
204 static int bus_timeout_arm(Manager *m, Watch *w) {
205 struct itimerspec its;
212 if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
213 timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
214 its.it_interval = its.it_value;
217 if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
223 void bus_timeout_event(Manager *m, Watch *w, int events) {
227 /* This is called by the event loop whenever there is
228 * something happening on D-Bus' file handles. */
230 if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
233 dbus_timeout_handle(w->data.bus_timeout);
236 static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
239 struct epoll_event ev;
244 if (!(w = new0(Watch, 1)))
247 if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
250 w->type = WATCH_DBUS_TIMEOUT;
251 w->data.bus_timeout = timeout;
253 if (bus_timeout_arm(m, w) < 0)
260 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
263 dbus_timeout_set_data(timeout, w, NULL);
269 close_nointr_nofail(w->fd);
275 static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
282 w = dbus_timeout_get_data(timeout);
286 assert(w->type == WATCH_DBUS_TIMEOUT);
288 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
289 close_nointr_nofail(w->fd);
293 static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
301 w = dbus_timeout_get_data(timeout);
305 assert(w->type == WATCH_DBUS_TIMEOUT);
307 if ((r = bus_timeout_arm(m, w)) < 0)
308 log_error("Failed to rearm timer: %s", strerror(-r));
311 static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
314 DBusMessage *reply = NULL;
320 dbus_error_init(&error);
322 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
323 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
324 log_debug("Got D-Bus request: %s.%s() on %s",
325 dbus_message_get_interface(message),
326 dbus_message_get_member(message),
327 dbus_message_get_path(message));
329 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
330 log_debug("API D-Bus connection terminated.");
333 } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
334 const char *name, *old_owner, *new_owner;
336 if (!dbus_message_get_args(message, &error,
337 DBUS_TYPE_STRING, &name,
338 DBUS_TYPE_STRING, &old_owner,
339 DBUS_TYPE_STRING, &new_owner,
341 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
343 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
344 log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
346 if (old_owner[0] == 0)
349 if (new_owner[0] == 0)
352 manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
354 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
357 if (!dbus_message_get_args(message, &error,
358 DBUS_TYPE_STRING, &name,
360 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
365 log_debug("Got D-Bus activation request for %s", name);
367 if (manager_unit_pending_inactive(m, SPECIAL_DBUS_SERVICE) ||
368 manager_unit_pending_inactive(m, SPECIAL_DBUS_SOCKET)) {
370 dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
372 r = manager_load_unit(m, name, NULL, &error, &u);
374 if (r >= 0 && u->refuse_manual_start)
378 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
382 const char *id, *text;
384 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
386 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
389 id = error.name ? error.name : bus_errno_to_dbus(r);
390 text = bus_error(&error, r);
392 if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
393 !dbus_message_append_args(reply,
394 DBUS_TYPE_STRING, &name,
395 DBUS_TYPE_STRING, &id,
396 DBUS_TYPE_STRING, &text,
401 /* On success we don't do anything, the service will be spawned now */
405 dbus_error_free(&error);
408 if (!dbus_connection_send(connection, reply, NULL))
411 dbus_message_unref(reply);
414 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
418 dbus_message_unref(reply);
420 dbus_error_free(&error);
422 return DBUS_HANDLER_RESULT_NEED_MEMORY;
425 static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
433 dbus_error_init(&error);
435 if (m->api_bus != m->system_bus &&
436 (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
437 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
438 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
439 dbus_message_get_interface(message),
440 dbus_message_get_member(message),
441 dbus_message_get_path(message));
443 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
444 log_debug("System D-Bus connection terminated.");
447 } else if (m->running_as != MANAGER_SYSTEM &&
448 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
452 if (!dbus_message_get_args(message, &error,
453 DBUS_TYPE_STRING, &cgroup,
455 log_error("Failed to parse Released message: %s", bus_error_message(&error));
457 cgroup_notify_empty(m, cgroup);
460 dbus_error_free(&error);
461 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
464 static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
472 dbus_error_init(&error);
474 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
475 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
476 log_debug("Got D-Bus request: %s.%s() on %s",
477 dbus_message_get_interface(message),
478 dbus_message_get_member(message),
479 dbus_message_get_path(message));
481 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
482 shutdown_connection(m, connection);
483 else if (m->running_as == MANAGER_SYSTEM &&
484 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
488 if (!dbus_message_get_args(message, &error,
489 DBUS_TYPE_STRING, &cgroup,
491 log_error("Failed to parse Released message: %s", bus_error_message(&error));
493 cgroup_notify_empty(m, cgroup);
495 /* Forward the message to the system bus, so that user
496 * instances are notified as well */
499 dbus_connection_send(m->system_bus, message, NULL);
502 dbus_error_free(&error);
504 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
507 unsigned bus_dispatch(Manager *m) {
512 if (m->queued_message) {
513 /* If we cannot get rid of this message we won't
514 * dispatch any D-Bus messages, so that we won't end
515 * up wanting to queue another message. */
517 if (m->queued_message_connection)
518 if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
521 dbus_message_unref(m->queued_message);
522 m->queued_message = NULL;
523 m->queued_message_connection = NULL;
526 if ((c = set_first(m->bus_connections_for_dispatch))) {
527 if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
528 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
536 static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
540 dbus_error_init(&error);
542 assert_se(reply = dbus_pending_call_steal_reply(pending));
544 switch (dbus_message_get_type(reply)) {
546 case DBUS_MESSAGE_TYPE_ERROR:
548 assert_se(dbus_set_error_from_message(&error, reply));
549 log_warning("RequestName() failed: %s", bus_error_message(&error));
552 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
555 if (!dbus_message_get_args(reply,
557 DBUS_TYPE_UINT32, &r,
558 DBUS_TYPE_INVALID)) {
559 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
564 log_debug("Successfully acquired name.");
566 log_error("Name already owned.");
572 assert_not_reached("Invalid reply message");
575 dbus_message_unref(reply);
576 dbus_error_free(&error);
579 static int request_name(Manager *m) {
580 const char *name = "org.freedesktop.systemd1";
581 /* Allow replacing of our name, to ease implementation of
582 * reexecution, where we keep the old connection open until
583 * after the new connection is set up and the name installed
584 * to allow clients to synchronously wait for reexecution to
586 uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
587 DBusMessage *message = NULL;
588 DBusPendingCall *pending = NULL;
590 if (!(message = dbus_message_new_method_call(
597 if (!dbus_message_append_args(
599 DBUS_TYPE_STRING, &name,
600 DBUS_TYPE_UINT32, &flags,
604 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
607 if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
610 dbus_message_unref(message);
611 dbus_pending_call_unref(pending);
613 /* We simple ask for the name and don't wait for it. Sooner or
614 * later we'll have it. */
620 dbus_pending_call_cancel(pending);
621 dbus_pending_call_unref(pending);
625 dbus_message_unref(message);
630 static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
633 Manager *m = userdata;
637 dbus_error_init(&error);
639 assert_se(reply = dbus_pending_call_steal_reply(pending));
641 switch (dbus_message_get_type(reply)) {
643 case DBUS_MESSAGE_TYPE_ERROR:
645 assert_se(dbus_set_error_from_message(&error, reply));
646 log_warning("ListNames() failed: %s", bus_error_message(&error));
649 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
653 if ((r = bus_parse_strv(reply, &l)) < 0)
654 log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
659 /* This is a bit hacky, we say the
660 * owner of the name is the name
661 * itself, because we don't want the
662 * extra traffic to figure out the
664 manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
673 assert_not_reached("Invalid reply message");
676 dbus_message_unref(reply);
677 dbus_error_free(&error);
680 static int query_name_list(Manager *m) {
681 DBusMessage *message = NULL;
682 DBusPendingCall *pending = NULL;
684 /* Asks for the currently installed bus names */
686 if (!(message = dbus_message_new_method_call(
693 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
696 if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
699 dbus_message_unref(message);
700 dbus_pending_call_unref(pending);
702 /* We simple ask for the list and don't wait for it. Sooner or
703 * later we'll get it. */
709 dbus_pending_call_cancel(pending);
710 dbus_pending_call_unref(pending);
714 dbus_message_unref(message);
719 static int bus_setup_loop(Manager *m, DBusConnection *bus) {
723 dbus_connection_set_exit_on_disconnect(bus, FALSE);
725 if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
726 !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
729 if (set_put(m->bus_connections_for_dispatch, bus) < 0)
732 dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
736 static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
737 return uid == 0 || uid == geteuid();
740 static void bus_new_connection(
742 DBusConnection *new_connection,
749 if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
750 log_error("Too many concurrent connections.");
754 dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
756 if (bus_setup_loop(m, new_connection) < 0)
759 if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
760 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
761 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
762 !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
767 log_debug("Accepted connection on private bus.");
769 dbus_connection_ref(new_connection);
772 static int init_registered_system_bus(Manager *m) {
775 if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
778 if (m->running_as != MANAGER_SYSTEM) {
781 dbus_error_init(&error);
783 dbus_bus_add_match(m->system_bus,
785 "interface='org.freedesktop.systemd1.Agent',"
787 "path='/org/freedesktop/systemd1/agent'",
790 if (dbus_error_is_set(&error)) {
791 log_error("Failed to register match: %s", bus_error_message(&error));
792 dbus_error_free(&error);
797 log_debug("Successfully connected to system D-Bus bus %s as %s",
798 strnull((id = dbus_connection_get_server_id(m->system_bus))),
799 strnull(dbus_bus_get_unique_name(m->system_bus)));
805 static int init_registered_api_bus(Manager *m) {
808 if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
809 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
810 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
811 !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
814 /* Get NameOwnerChange messages */
815 dbus_bus_add_match(m->api_bus,
817 "sender='"DBUS_SERVICE_DBUS"',"
818 "interface='"DBUS_INTERFACE_DBUS"',"
819 "member='NameOwnerChanged',"
820 "path='"DBUS_PATH_DBUS"'",
823 /* Get activation requests */
824 dbus_bus_add_match(m->api_bus,
826 "sender='"DBUS_SERVICE_DBUS"',"
827 "interface='org.freedesktop.systemd1.Activator',"
828 "member='ActivationRequest',"
829 "path='"DBUS_PATH_DBUS"'",
836 r = query_name_list(m);
840 if (m->running_as == MANAGER_USER) {
842 log_debug("Successfully connected to API D-Bus bus %s as %s",
843 strnull((id = dbus_connection_get_server_id(m->api_bus))),
844 strnull(dbus_bus_get_unique_name(m->api_bus)));
847 log_debug("Successfully initialized API on the system bus");
852 static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
853 Manager *m = userdata;
854 DBusConnection **conn;
860 dbus_error_init(&error);
862 conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
863 assert(conn == &m->system_bus || conn == &m->api_bus);
865 reply = dbus_pending_call_steal_reply(pending);
867 switch (dbus_message_get_type(reply)) {
868 case DBUS_MESSAGE_TYPE_ERROR:
869 assert_se(dbus_set_error_from_message(&error, reply));
870 log_warning("Failed to register to bus: %s", bus_error_message(&error));
873 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
874 if (!dbus_message_get_args(reply, &error,
875 DBUS_TYPE_STRING, &name,
876 DBUS_TYPE_INVALID)) {
877 log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
882 log_debug("Received name %s in reply to Hello", name);
883 if (!dbus_bus_set_unique_name(*conn, name)) {
884 log_error("Failed to set unique name");
889 if (conn == &m->system_bus) {
890 r = init_registered_system_bus(m);
891 if (r == 0 && m->running_as == MANAGER_SYSTEM)
892 r = init_registered_api_bus(m);
894 r = init_registered_api_bus(m);
898 assert_not_reached("Invalid reply message");
901 dbus_message_unref(reply);
902 dbus_error_free(&error);
905 if (conn == &m->system_bus) {
906 log_debug("Failed setting up the system bus");
909 log_debug("Failed setting up the API bus");
915 static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
916 DBusMessage *message = NULL;
917 DBusPendingCall *pending = NULL;
919 message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
926 if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
929 if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
932 if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
935 dbus_message_unref(message);
936 dbus_pending_call_unref(pending);
941 dbus_pending_call_cancel(pending);
942 dbus_pending_call_unref(pending);
946 dbus_message_unref(message);
951 static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
953 DBusConnection *connection;
957 case DBUS_BUS_SYSTEM:
958 address = __secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
959 if (!address || !address[0])
960 address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
962 case DBUS_BUS_SESSION:
963 address = __secure_getenv("DBUS_SESSION_BUS_ADDRESS");
964 if (!address || !address[0])
965 address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
968 assert_not_reached("Invalid bus type");
971 dbus_error_init(&error);
973 connection = dbus_connection_open_private(address, &error);
975 log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
982 dbus_connection_close(connection);
983 dbus_error_free(&error);
987 static int bus_init_system(Manager *m) {
993 m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
994 if (!m->system_bus) {
995 log_debug("Failed to connect to system D-Bus, retrying later");
1000 r = bus_setup_loop(m, m->system_bus);
1004 r = manager_bus_async_register(m, &m->system_bus);
1015 static int bus_init_api(Manager *m) {
1021 if (m->running_as == MANAGER_SYSTEM) {
1022 m->api_bus = m->system_bus;
1023 /* In this mode there is no distinct connection to the API bus,
1024 * the API is published on the system bus.
1025 * bus_register_cb() is aware of that and will init the API
1026 * when the system bus gets registered.
1027 * No need to setup anything here. */
1031 m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
1033 log_debug("Failed to connect to API D-Bus, retrying later");
1038 r = bus_setup_loop(m, m->api_bus);
1042 r = manager_bus_async_register(m, &m->api_bus);
1053 static int bus_init_private(Manager *m) {
1056 const char *const external_only[] = {
1063 dbus_error_init(&error);
1068 if (m->running_as == MANAGER_SYSTEM) {
1070 /* We want the private bus only when running as init */
1074 unlink("/run/systemd/private");
1075 m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
1080 e = __secure_getenv("XDG_RUNTIME_DIR");
1084 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) {
1089 mkdir_parents_label(p+10, 0755);
1091 m->private_bus = dbus_server_listen(p, &error);
1095 if (!m->private_bus) {
1096 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
1101 if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1102 !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1103 !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
1108 dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1110 log_debug("Successfully created private D-Bus server.");
1115 bus_done_private(m);
1116 dbus_error_free(&error);
1121 int bus_init(Manager *m, bool try_bus_connect) {
1124 if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1125 set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1128 if (m->name_data_slot < 0)
1129 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1132 if (m->conn_data_slot < 0)
1133 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1136 if (m->subscribed_data_slot < 0)
1137 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1140 if (try_bus_connect) {
1141 if ((r = bus_init_system(m)) < 0 ||
1142 (r = bus_init_api(m)) < 0)
1146 if ((r = bus_init_private(m)) < 0)
1154 static void shutdown_connection(Manager *m, DBusConnection *c) {
1159 HASHMAP_FOREACH(j, m->jobs, i) {
1160 JobBusClient *cl, *nextcl;
1161 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1163 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
1169 set_remove(m->bus_connections, c);
1170 set_remove(m->bus_connections_for_dispatch, c);
1172 if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
1175 while ((t = set_steal_first(s)))
1181 if (m->queued_message_connection == c) {
1182 m->queued_message_connection = NULL;
1184 if (m->queued_message) {
1185 dbus_message_unref(m->queued_message);
1186 m->queued_message = NULL;
1190 dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1191 /* system manager cannot afford to block on DBus */
1192 if (m->running_as != MANAGER_SYSTEM)
1193 dbus_connection_flush(c);
1194 dbus_connection_close(c);
1195 dbus_connection_unref(c);
1198 static void bus_done_api(Manager *m) {
1202 if (m->running_as == MANAGER_USER)
1203 shutdown_connection(m, m->api_bus);
1207 if (m->queued_message) {
1208 dbus_message_unref(m->queued_message);
1209 m->queued_message = NULL;
1213 static void bus_done_system(Manager *m) {
1217 if (m->running_as == MANAGER_SYSTEM)
1220 shutdown_connection(m, m->system_bus);
1221 m->system_bus = NULL;
1224 static void bus_done_private(Manager *m) {
1225 if (!m->private_bus)
1228 dbus_server_disconnect(m->private_bus);
1229 dbus_server_unref(m->private_bus);
1230 m->private_bus = NULL;
1233 void bus_done(Manager *m) {
1238 bus_done_private(m);
1240 while ((c = set_steal_first(m->bus_connections)))
1241 shutdown_connection(m, c);
1243 while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1244 shutdown_connection(m, c);
1246 set_free(m->bus_connections);
1247 set_free(m->bus_connections_for_dispatch);
1249 if (m->name_data_slot >= 0)
1250 dbus_pending_call_free_data_slot(&m->name_data_slot);
1252 if (m->conn_data_slot >= 0)
1253 dbus_pending_call_free_data_slot(&m->conn_data_slot);
1255 if (m->subscribed_data_slot >= 0)
1256 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1259 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1260 Manager *m = userdata;
1265 dbus_error_init(&error);
1267 assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1268 assert_se(reply = dbus_pending_call_steal_reply(pending));
1270 switch (dbus_message_get_type(reply)) {
1272 case DBUS_MESSAGE_TYPE_ERROR:
1274 assert_se(dbus_set_error_from_message(&error, reply));
1275 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1278 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1281 if (!dbus_message_get_args(reply,
1283 DBUS_TYPE_UINT32, &r,
1284 DBUS_TYPE_INVALID)) {
1285 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1289 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1294 assert_not_reached("Invalid reply message");
1297 dbus_message_unref(reply);
1298 dbus_error_free(&error);
1301 int bus_query_pid(Manager *m, const char *name) {
1302 DBusMessage *message = NULL;
1303 DBusPendingCall *pending = NULL;
1309 if (!(message = dbus_message_new_method_call(
1312 DBUS_INTERFACE_DBUS,
1313 "GetConnectionUnixProcessID")))
1316 if (!(dbus_message_append_args(
1318 DBUS_TYPE_STRING, &name,
1319 DBUS_TYPE_INVALID)))
1322 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1325 if (!(n = strdup(name)))
1328 if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1333 if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1336 dbus_message_unref(message);
1337 dbus_pending_call_unref(pending);
1345 dbus_pending_call_cancel(pending);
1346 dbus_pending_call_unref(pending);
1350 dbus_message_unref(message);
1355 int bus_broadcast(Manager *m, DBusMessage *message) {
1363 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1364 if (c != m->system_bus || m->running_as == MANAGER_SYSTEM)
1365 oom = !dbus_connection_send(c, message, NULL);
1367 SET_FOREACH(c, m->bus_connections, i)
1368 if (c != m->system_bus || m->running_as == MANAGER_SYSTEM)
1369 oom = !dbus_connection_send(c, message, NULL);
1371 return oom ? -ENOMEM : 0;
1374 bool bus_has_subscriber(Manager *m) {
1380 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1381 if (bus_connection_has_subscriber(m, c))
1384 SET_FOREACH(c, m->bus_connections, i)
1385 if (bus_connection_has_subscriber(m, c))
1391 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1395 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1398 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1405 /* When we are about to reexecute we add all D-Bus fds to the
1406 * set to pass over to the newly executed systemd. They won't
1407 * be used there however, except that they are closed at the
1408 * very end of deserialization, those making it possible for
1409 * clients to synchronously wait for systemd to reexec by
1410 * simply waiting for disconnection */
1412 SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1415 if (dbus_connection_get_unix_fd(c, &fd)) {
1416 fd = fdset_put_dup(fds, fd);
1423 SET_FOREACH(c, m->bus_connections, i) {
1426 if (dbus_connection_get_unix_fd(c, &fd)) {
1427 fd = fdset_put_dup(fds, fd);
1437 void bus_broadcast_finished(
1439 usec_t firmware_usec,
1443 usec_t userspace_usec,
1444 usec_t total_usec) {
1446 DBusMessage *message;
1450 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1456 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1457 if (!dbus_message_append_args(message,
1458 DBUS_TYPE_UINT64, &firmware_usec,
1459 DBUS_TYPE_UINT64, &loader_usec,
1460 DBUS_TYPE_UINT64, &kernel_usec,
1461 DBUS_TYPE_UINT64, &initrd_usec,
1462 DBUS_TYPE_UINT64, &userspace_usec,
1463 DBUS_TYPE_UINT64, &total_usec,
1464 DBUS_TYPE_INVALID)) {
1470 if (bus_broadcast(m, message) < 0) {
1477 dbus_message_unref(message);