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 512
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 = {};
210 if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
211 timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
212 its.it_interval = its.it_value;
215 if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
221 void bus_timeout_event(Manager *m, Watch *w, int events) {
225 /* This is called by the event loop whenever there is
226 * something happening on D-Bus' file handles. */
228 if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
231 dbus_timeout_handle(w->data.bus_timeout);
234 static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
237 struct epoll_event ev;
242 if (!(w = new0(Watch, 1)))
245 if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
248 w->type = WATCH_DBUS_TIMEOUT;
249 w->data.bus_timeout = timeout;
251 if (bus_timeout_arm(m, w) < 0)
258 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
261 dbus_timeout_set_data(timeout, w, NULL);
267 close_nointr_nofail(w->fd);
273 static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
280 w = dbus_timeout_get_data(timeout);
284 assert(w->type == WATCH_DBUS_TIMEOUT);
286 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
287 close_nointr_nofail(w->fd);
291 static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
299 w = dbus_timeout_get_data(timeout);
303 assert(w->type == WATCH_DBUS_TIMEOUT);
305 if ((r = bus_timeout_arm(m, w)) < 0)
306 log_error("Failed to rearm timer: %s", strerror(-r));
309 static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
312 DBusMessage *reply = NULL;
318 dbus_error_init(&error);
320 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
321 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
322 log_debug("Got D-Bus request: %s.%s() on %s",
323 dbus_message_get_interface(message),
324 dbus_message_get_member(message),
325 dbus_message_get_path(message));
327 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
328 log_debug("API D-Bus connection terminated.");
331 } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
332 const char *name, *old_owner, *new_owner;
334 if (!dbus_message_get_args(message, &error,
335 DBUS_TYPE_STRING, &name,
336 DBUS_TYPE_STRING, &old_owner,
337 DBUS_TYPE_STRING, &new_owner,
339 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
341 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
342 log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
344 if (old_owner[0] == 0)
347 if (new_owner[0] == 0)
350 manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
352 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
355 if (!dbus_message_get_args(message, &error,
356 DBUS_TYPE_STRING, &name,
358 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
363 log_debug("Got D-Bus activation request for %s", name);
365 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
366 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
368 dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
370 r = manager_load_unit(m, name, NULL, &error, &u);
372 if (r >= 0 && u->refuse_manual_start)
376 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
380 const char *id, *text;
382 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
384 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
387 id = error.name ? error.name : bus_errno_to_dbus(r);
388 text = bus_error(&error, r);
390 if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
391 !dbus_message_append_args(reply,
392 DBUS_TYPE_STRING, &name,
393 DBUS_TYPE_STRING, &id,
394 DBUS_TYPE_STRING, &text,
399 /* On success we don't do anything, the service will be spawned now */
403 dbus_error_free(&error);
406 if (!bus_maybe_send_reply(connection, message, reply))
409 dbus_message_unref(reply);
412 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
416 dbus_message_unref(reply);
418 dbus_error_free(&error);
420 return DBUS_HANDLER_RESULT_NEED_MEMORY;
423 static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
431 dbus_error_init(&error);
433 if (m->api_bus != m->system_bus &&
434 (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
435 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
436 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
437 dbus_message_get_interface(message),
438 dbus_message_get_member(message),
439 dbus_message_get_path(message));
441 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
442 log_debug("System D-Bus connection terminated.");
445 } else if (m->running_as != SYSTEMD_SYSTEM &&
446 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
450 if (!dbus_message_get_args(message, &error,
451 DBUS_TYPE_STRING, &cgroup,
453 log_error("Failed to parse Released message: %s", bus_error_message(&error));
455 manager_notify_cgroup_empty(m, cgroup);
458 dbus_error_free(&error);
459 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
462 static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
470 dbus_error_init(&error);
472 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
473 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
474 log_debug("Got D-Bus request: %s.%s() on %s",
475 dbus_message_get_interface(message),
476 dbus_message_get_member(message),
477 dbus_message_get_path(message));
479 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
480 shutdown_connection(m, connection);
481 else if (m->running_as == SYSTEMD_SYSTEM &&
482 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
486 if (!dbus_message_get_args(message, &error,
487 DBUS_TYPE_STRING, &cgroup,
489 log_error("Failed to parse Released message: %s", bus_error_message(&error));
491 manager_notify_cgroup_empty(m, cgroup);
493 /* Forward the message to the system bus, so that user
494 * instances are notified as well */
497 dbus_connection_send(m->system_bus, message, NULL);
500 dbus_error_free(&error);
502 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
505 unsigned bus_dispatch(Manager *m) {
510 if (m->queued_message) {
511 /* If we cannot get rid of this message we won't
512 * dispatch any D-Bus messages, so that we won't end
513 * up wanting to queue another message. */
515 if (m->queued_message_connection)
516 if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
519 dbus_message_unref(m->queued_message);
520 m->queued_message = NULL;
521 m->queued_message_connection = NULL;
524 if ((c = set_first(m->bus_connections_for_dispatch))) {
525 if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
526 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
534 static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
538 dbus_error_init(&error);
540 assert_se(reply = dbus_pending_call_steal_reply(pending));
542 switch (dbus_message_get_type(reply)) {
544 case DBUS_MESSAGE_TYPE_ERROR:
546 assert_se(dbus_set_error_from_message(&error, reply));
547 log_warning("RequestName() failed: %s", bus_error_message(&error));
550 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
553 if (!dbus_message_get_args(reply,
555 DBUS_TYPE_UINT32, &r,
556 DBUS_TYPE_INVALID)) {
557 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
562 log_debug("Successfully acquired name.");
564 log_error("Name already owned.");
570 assert_not_reached("Invalid reply message");
573 dbus_message_unref(reply);
574 dbus_error_free(&error);
577 static int request_name(Manager *m) {
578 const char *name = "org.freedesktop.systemd1";
579 /* Allow replacing of our name, to ease implementation of
580 * reexecution, where we keep the old connection open until
581 * after the new connection is set up and the name installed
582 * to allow clients to synchronously wait for reexecution to
584 uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
585 DBusMessage *message = NULL;
586 DBusPendingCall *pending = NULL;
588 if (!(message = dbus_message_new_method_call(
595 if (!dbus_message_append_args(
597 DBUS_TYPE_STRING, &name,
598 DBUS_TYPE_UINT32, &flags,
602 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
605 if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
608 dbus_message_unref(message);
609 dbus_pending_call_unref(pending);
611 /* We simple ask for the name and don't wait for it. Sooner or
612 * later we'll have it. */
618 dbus_pending_call_cancel(pending);
619 dbus_pending_call_unref(pending);
623 dbus_message_unref(message);
628 static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
631 Manager *m = userdata;
635 dbus_error_init(&error);
637 assert_se(reply = dbus_pending_call_steal_reply(pending));
639 switch (dbus_message_get_type(reply)) {
641 case DBUS_MESSAGE_TYPE_ERROR:
643 assert_se(dbus_set_error_from_message(&error, reply));
644 log_warning("ListNames() failed: %s", bus_error_message(&error));
647 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
651 if ((r = bus_parse_strv(reply, &l)) < 0)
652 log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
657 /* This is a bit hacky, we say the
658 * owner of the name is the name
659 * itself, because we don't want the
660 * extra traffic to figure out the
662 manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
671 assert_not_reached("Invalid reply message");
674 dbus_message_unref(reply);
675 dbus_error_free(&error);
678 static int query_name_list(Manager *m) {
679 DBusMessage *message = NULL;
680 DBusPendingCall *pending = NULL;
682 /* Asks for the currently installed bus names */
684 if (!(message = dbus_message_new_method_call(
691 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
694 if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
697 dbus_message_unref(message);
698 dbus_pending_call_unref(pending);
700 /* We simple ask for the list and don't wait for it. Sooner or
701 * later we'll get it. */
707 dbus_pending_call_cancel(pending);
708 dbus_pending_call_unref(pending);
712 dbus_message_unref(message);
717 static int bus_setup_loop(Manager *m, DBusConnection *bus) {
721 dbus_connection_set_exit_on_disconnect(bus, FALSE);
723 if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
724 !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
727 if (set_put(m->bus_connections_for_dispatch, bus) < 0)
730 dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
734 static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
735 return uid == 0 || uid == geteuid();
738 static void bus_new_connection(
740 DBusConnection *new_connection,
747 if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
748 log_error("Too many concurrent connections.");
752 dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
754 if (bus_setup_loop(m, new_connection) < 0)
757 if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
758 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
759 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
760 !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
765 log_debug("Accepted connection on private bus.");
767 dbus_connection_ref(new_connection);
770 static int init_registered_system_bus(Manager *m) {
773 if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
776 if (m->running_as != SYSTEMD_SYSTEM) {
779 dbus_error_init(&error);
781 dbus_bus_add_match(m->system_bus,
783 "interface='org.freedesktop.systemd1.Agent',"
785 "path='/org/freedesktop/systemd1/agent'",
788 if (dbus_error_is_set(&error)) {
789 log_error("Failed to register match: %s", bus_error_message(&error));
790 dbus_error_free(&error);
795 log_debug("Successfully connected to system D-Bus bus %s as %s",
796 strnull((id = dbus_connection_get_server_id(m->system_bus))),
797 strnull(dbus_bus_get_unique_name(m->system_bus)));
803 static int init_registered_api_bus(Manager *m) {
806 if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
807 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
808 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
809 !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
812 /* Get NameOwnerChange messages */
813 dbus_bus_add_match(m->api_bus,
815 "sender='"DBUS_SERVICE_DBUS"',"
816 "interface='"DBUS_INTERFACE_DBUS"',"
817 "member='NameOwnerChanged',"
818 "path='"DBUS_PATH_DBUS"'",
821 /* Get activation requests */
822 dbus_bus_add_match(m->api_bus,
824 "sender='"DBUS_SERVICE_DBUS"',"
825 "interface='org.freedesktop.systemd1.Activator',"
826 "member='ActivationRequest',"
827 "path='"DBUS_PATH_DBUS"'",
834 r = query_name_list(m);
838 if (m->running_as == SYSTEMD_USER) {
840 log_debug("Successfully connected to API D-Bus bus %s as %s",
841 strnull((id = dbus_connection_get_server_id(m->api_bus))),
842 strnull(dbus_bus_get_unique_name(m->api_bus)));
845 log_debug("Successfully initialized API on the system bus");
850 static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
851 Manager *m = userdata;
852 DBusConnection **conn;
858 dbus_error_init(&error);
860 conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
861 assert(conn == &m->system_bus || conn == &m->api_bus);
863 reply = dbus_pending_call_steal_reply(pending);
865 switch (dbus_message_get_type(reply)) {
866 case DBUS_MESSAGE_TYPE_ERROR:
867 assert_se(dbus_set_error_from_message(&error, reply));
868 log_warning("Failed to register to bus: %s", bus_error_message(&error));
871 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
872 if (!dbus_message_get_args(reply, &error,
873 DBUS_TYPE_STRING, &name,
874 DBUS_TYPE_INVALID)) {
875 log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
880 log_debug("Received name %s in reply to Hello", name);
881 if (!dbus_bus_set_unique_name(*conn, name)) {
882 log_error("Failed to set unique name");
887 if (conn == &m->system_bus) {
888 r = init_registered_system_bus(m);
889 if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
890 r = init_registered_api_bus(m);
892 r = init_registered_api_bus(m);
896 assert_not_reached("Invalid reply message");
899 dbus_message_unref(reply);
900 dbus_error_free(&error);
903 if (conn == &m->system_bus) {
904 log_debug("Failed setting up the system bus");
907 log_debug("Failed setting up the API bus");
913 static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
914 DBusMessage *message = NULL;
915 DBusPendingCall *pending = NULL;
917 message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
924 if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
927 if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
930 if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
933 dbus_message_unref(message);
934 dbus_pending_call_unref(pending);
939 dbus_pending_call_cancel(pending);
940 dbus_pending_call_unref(pending);
944 dbus_message_unref(message);
949 static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
951 DBusConnection *connection;
955 case DBUS_BUS_SYSTEM:
956 address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
957 if (!address || !address[0])
958 address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
960 case DBUS_BUS_SESSION:
961 address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
962 if (!address || !address[0])
963 address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
966 assert_not_reached("Invalid bus type");
969 dbus_error_init(&error);
971 connection = dbus_connection_open_private(address, &error);
973 log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
980 dbus_error_free(&error);
984 static int bus_init_system(Manager *m) {
990 m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
991 if (!m->system_bus) {
992 log_debug("Failed to connect to system D-Bus, retrying later");
997 r = bus_setup_loop(m, m->system_bus);
1001 r = manager_bus_async_register(m, &m->system_bus);
1012 static int bus_init_api(Manager *m) {
1018 if (m->running_as == SYSTEMD_SYSTEM) {
1019 m->api_bus = m->system_bus;
1020 /* In this mode there is no distinct connection to the API bus,
1021 * the API is published on the system bus.
1022 * bus_register_cb() is aware of that and will init the API
1023 * when the system bus gets registered.
1024 * No need to setup anything here. */
1028 m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
1030 log_debug("Failed to connect to API D-Bus, retrying later");
1035 r = bus_setup_loop(m, m->api_bus);
1039 r = manager_bus_async_register(m, &m->api_bus);
1050 static int bus_init_private(Manager *m) {
1053 static const char *const external_only[] = {
1060 dbus_error_init(&error);
1065 if (m->running_as == SYSTEMD_SYSTEM) {
1067 /* We want the private bus only when running as init */
1071 unlink("/run/systemd/private");
1072 m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
1078 e = secure_getenv("XDG_RUNTIME_DIR");
1082 if (asprintf(&p, "%s/systemd/private", e) < 0) {
1087 mkdir_parents_label(p, 0755);
1091 escaped = dbus_address_escape_value(e);
1096 if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) {
1103 m->private_bus = dbus_server_listen(p, &error);
1107 if (!m->private_bus) {
1108 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
1113 if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1114 !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1115 !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
1120 dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1122 log_debug("Successfully created private D-Bus server.");
1127 bus_done_private(m);
1128 dbus_error_free(&error);
1133 int bus_init(Manager *m, bool try_bus_connect) {
1136 if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1137 set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1140 if (m->name_data_slot < 0)
1141 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1144 if (m->conn_data_slot < 0)
1145 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1148 if (m->subscribed_data_slot < 0)
1149 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1152 if (try_bus_connect) {
1153 if ((r = bus_init_system(m)) < 0 ||
1154 (r = bus_init_api(m)) < 0)
1158 r = bus_init_private(m);
1165 static void shutdown_connection(Manager *m, DBusConnection *c) {
1169 HASHMAP_FOREACH(j, m->jobs, i) {
1170 JobBusClient *cl, *nextcl;
1171 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1173 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
1179 set_remove(m->bus_connections, c);
1180 set_remove(m->bus_connections_for_dispatch, c);
1181 set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c));
1183 if (m->queued_message_connection == c) {
1184 m->queued_message_connection = NULL;
1186 if (m->queued_message) {
1187 dbus_message_unref(m->queued_message);
1188 m->queued_message = NULL;
1192 dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1193 /* system manager cannot afford to block on DBus */
1194 if (m->running_as != SYSTEMD_SYSTEM)
1195 dbus_connection_flush(c);
1196 dbus_connection_close(c);
1197 dbus_connection_unref(c);
1200 static void bus_done_api(Manager *m) {
1204 if (m->running_as == SYSTEMD_USER)
1205 shutdown_connection(m, m->api_bus);
1209 if (m->queued_message) {
1210 dbus_message_unref(m->queued_message);
1211 m->queued_message = NULL;
1215 static void bus_done_system(Manager *m) {
1219 if (m->running_as == SYSTEMD_SYSTEM)
1222 shutdown_connection(m, m->system_bus);
1223 m->system_bus = NULL;
1226 static void bus_done_private(Manager *m) {
1227 if (!m->private_bus)
1230 dbus_server_disconnect(m->private_bus);
1231 dbus_server_unref(m->private_bus);
1232 m->private_bus = NULL;
1235 void bus_done(Manager *m) {
1240 bus_done_private(m);
1242 while ((c = set_steal_first(m->bus_connections)))
1243 shutdown_connection(m, c);
1245 while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1246 shutdown_connection(m, c);
1248 set_free(m->bus_connections);
1249 set_free(m->bus_connections_for_dispatch);
1251 if (m->name_data_slot >= 0)
1252 dbus_pending_call_free_data_slot(&m->name_data_slot);
1254 if (m->conn_data_slot >= 0)
1255 dbus_pending_call_free_data_slot(&m->conn_data_slot);
1257 if (m->subscribed_data_slot >= 0)
1258 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1261 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1262 Manager *m = userdata;
1267 dbus_error_init(&error);
1269 assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1270 assert_se(reply = dbus_pending_call_steal_reply(pending));
1272 switch (dbus_message_get_type(reply)) {
1274 case DBUS_MESSAGE_TYPE_ERROR:
1276 assert_se(dbus_set_error_from_message(&error, reply));
1277 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1280 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1283 if (!dbus_message_get_args(reply,
1285 DBUS_TYPE_UINT32, &r,
1286 DBUS_TYPE_INVALID)) {
1287 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1291 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1296 assert_not_reached("Invalid reply message");
1299 dbus_message_unref(reply);
1300 dbus_error_free(&error);
1303 int bus_query_pid(Manager *m, const char *name) {
1304 DBusMessage *message = NULL;
1305 DBusPendingCall *pending = NULL;
1311 if (!(message = dbus_message_new_method_call(
1314 DBUS_INTERFACE_DBUS,
1315 "GetConnectionUnixProcessID")))
1318 if (!(dbus_message_append_args(
1320 DBUS_TYPE_STRING, &name,
1321 DBUS_TYPE_INVALID)))
1324 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1327 if (!(n = strdup(name)))
1330 if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1335 if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1338 dbus_message_unref(message);
1339 dbus_pending_call_unref(pending);
1347 dbus_pending_call_cancel(pending);
1348 dbus_pending_call_unref(pending);
1352 dbus_message_unref(message);
1357 int bus_broadcast(Manager *m, DBusMessage *message) {
1365 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1366 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1367 oom = !dbus_connection_send(c, message, NULL);
1369 SET_FOREACH(c, m->bus_connections, i)
1370 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1371 oom = !dbus_connection_send(c, message, NULL);
1373 return oom ? -ENOMEM : 0;
1376 bool bus_has_subscriber(Manager *m) {
1382 /* If we are reloading then we might not have deserialized the
1383 subscribers yet, hence let's assume that there are some */
1385 if (m->n_reloading > 0)
1388 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1389 if (bus_connection_has_subscriber(m, c))
1392 SET_FOREACH(c, m->bus_connections, i)
1393 if (bus_connection_has_subscriber(m, c))
1399 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1403 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1406 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1413 /* When we are about to reexecute we add all D-Bus fds to the
1414 * set to pass over to the newly executed systemd. They won't
1415 * be used there however, except that they are closed at the
1416 * very end of deserialization, those making it possible for
1417 * clients to synchronously wait for systemd to reexec by
1418 * simply waiting for disconnection */
1420 SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1423 if (dbus_connection_get_unix_fd(c, &fd)) {
1424 fd = fdset_put_dup(fds, fd);
1431 SET_FOREACH(c, m->bus_connections, i) {
1434 if (dbus_connection_get_unix_fd(c, &fd)) {
1435 fd = fdset_put_dup(fds, fd);
1445 void bus_broadcast_finished(
1447 usec_t firmware_usec,
1451 usec_t userspace_usec,
1452 usec_t total_usec) {
1454 _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
1458 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1464 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1465 if (!dbus_message_append_args(message,
1466 DBUS_TYPE_UINT64, &firmware_usec,
1467 DBUS_TYPE_UINT64, &loader_usec,
1468 DBUS_TYPE_UINT64, &kernel_usec,
1469 DBUS_TYPE_UINT64, &initrd_usec,
1470 DBUS_TYPE_UINT64, &userspace_usec,
1471 DBUS_TYPE_UINT64, &total_usec,
1472 DBUS_TYPE_INVALID)) {
1478 if (bus_broadcast(m, message) < 0) {
1484 void bus_broadcast_reloading(Manager *m, bool active) {
1486 _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
1487 dbus_bool_t b = active;
1491 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
1497 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1498 if (!dbus_message_append_args(message,
1499 DBUS_TYPE_BOOLEAN, &b,
1500 DBUS_TYPE_INVALID)) {
1506 if (bus_broadcast(m, message) < 0) {
1512 Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) {
1518 s = BUS_CONNECTION_SUBSCRIBED(m, c);
1522 s = set_new(string_hash_func, string_compare_func);
1526 if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
1534 void bus_serialize(Manager *m, FILE *f) {
1545 s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus);
1546 SET_FOREACH(client, s, i)
1547 fprintf(f, "subscribed=%s\n", client);
1550 int bus_deserialize_item(Manager *m, const char *line) {
1561 e = startswith(line, "subscribed=");
1565 s = bus_acquire_subscribed(m, m->api_bus);