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) {
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 r = bus_init_private(m);
1166 static void shutdown_connection(Manager *m, DBusConnection *c) {
1170 HASHMAP_FOREACH(j, m->jobs, i) {
1171 JobBusClient *cl, *nextcl;
1172 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1174 LIST_REMOVE(client, j->bus_client_list, cl);
1180 set_remove(m->bus_connections, c);
1181 set_remove(m->bus_connections_for_dispatch, c);
1182 set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c));
1184 if (m->queued_message_connection == c) {
1185 m->queued_message_connection = NULL;
1187 if (m->queued_message) {
1188 dbus_message_unref(m->queued_message);
1189 m->queued_message = NULL;
1193 dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1194 /* system manager cannot afford to block on DBus */
1195 if (m->running_as != SYSTEMD_SYSTEM)
1196 dbus_connection_flush(c);
1197 dbus_connection_close(c);
1198 dbus_connection_unref(c);
1201 static void bus_done_api(Manager *m) {
1205 if (m->running_as == SYSTEMD_USER)
1206 shutdown_connection(m, m->api_bus);
1210 if (m->queued_message) {
1211 dbus_message_unref(m->queued_message);
1212 m->queued_message = NULL;
1216 static void bus_done_system(Manager *m) {
1220 if (m->running_as == SYSTEMD_SYSTEM)
1223 shutdown_connection(m, m->system_bus);
1224 m->system_bus = NULL;
1227 static void bus_done_private(Manager *m) {
1228 if (!m->private_bus)
1231 dbus_server_disconnect(m->private_bus);
1232 dbus_server_unref(m->private_bus);
1233 m->private_bus = NULL;
1236 void bus_done(Manager *m) {
1241 bus_done_private(m);
1243 while ((c = set_steal_first(m->bus_connections)))
1244 shutdown_connection(m, c);
1246 while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1247 shutdown_connection(m, c);
1249 set_free(m->bus_connections);
1250 set_free(m->bus_connections_for_dispatch);
1252 if (m->name_data_slot >= 0)
1253 dbus_pending_call_free_data_slot(&m->name_data_slot);
1255 if (m->conn_data_slot >= 0)
1256 dbus_pending_call_free_data_slot(&m->conn_data_slot);
1258 if (m->subscribed_data_slot >= 0)
1259 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1262 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1263 Manager *m = userdata;
1268 dbus_error_init(&error);
1270 assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1271 assert_se(reply = dbus_pending_call_steal_reply(pending));
1273 switch (dbus_message_get_type(reply)) {
1275 case DBUS_MESSAGE_TYPE_ERROR:
1277 assert_se(dbus_set_error_from_message(&error, reply));
1278 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1281 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1284 if (!dbus_message_get_args(reply,
1286 DBUS_TYPE_UINT32, &r,
1287 DBUS_TYPE_INVALID)) {
1288 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1292 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1297 assert_not_reached("Invalid reply message");
1300 dbus_message_unref(reply);
1301 dbus_error_free(&error);
1304 int bus_query_pid(Manager *m, const char *name) {
1305 DBusMessage *message = NULL;
1306 DBusPendingCall *pending = NULL;
1312 if (!(message = dbus_message_new_method_call(
1315 DBUS_INTERFACE_DBUS,
1316 "GetConnectionUnixProcessID")))
1319 if (!(dbus_message_append_args(
1321 DBUS_TYPE_STRING, &name,
1322 DBUS_TYPE_INVALID)))
1325 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1328 if (!(n = strdup(name)))
1331 if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1336 if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1339 dbus_message_unref(message);
1340 dbus_pending_call_unref(pending);
1348 dbus_pending_call_cancel(pending);
1349 dbus_pending_call_unref(pending);
1353 dbus_message_unref(message);
1358 int bus_broadcast(Manager *m, DBusMessage *message) {
1366 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1367 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1368 oom = !dbus_connection_send(c, message, NULL);
1370 SET_FOREACH(c, m->bus_connections, i)
1371 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1372 oom = !dbus_connection_send(c, message, NULL);
1374 return oom ? -ENOMEM : 0;
1377 bool bus_has_subscriber(Manager *m) {
1383 /* If we are reloading then we might not have deserialized the
1384 subscribers yet, hence let's assume that there are some */
1386 if (m->n_reloading > 0)
1389 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1390 if (bus_connection_has_subscriber(m, c))
1393 SET_FOREACH(c, m->bus_connections, i)
1394 if (bus_connection_has_subscriber(m, c))
1400 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1404 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1407 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1414 /* When we are about to reexecute we add all D-Bus fds to the
1415 * set to pass over to the newly executed systemd. They won't
1416 * be used there however, except that they are closed at the
1417 * very end of deserialization, those making it possible for
1418 * clients to synchronously wait for systemd to reexec by
1419 * simply waiting for disconnection */
1421 SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1424 if (dbus_connection_get_unix_fd(c, &fd)) {
1425 fd = fdset_put_dup(fds, fd);
1432 SET_FOREACH(c, m->bus_connections, i) {
1435 if (dbus_connection_get_unix_fd(c, &fd)) {
1436 fd = fdset_put_dup(fds, fd);
1446 void bus_broadcast_finished(
1448 usec_t firmware_usec,
1452 usec_t userspace_usec,
1453 usec_t total_usec) {
1455 _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
1459 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1465 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1466 if (!dbus_message_append_args(message,
1467 DBUS_TYPE_UINT64, &firmware_usec,
1468 DBUS_TYPE_UINT64, &loader_usec,
1469 DBUS_TYPE_UINT64, &kernel_usec,
1470 DBUS_TYPE_UINT64, &initrd_usec,
1471 DBUS_TYPE_UINT64, &userspace_usec,
1472 DBUS_TYPE_UINT64, &total_usec,
1473 DBUS_TYPE_INVALID)) {
1479 if (bus_broadcast(m, message) < 0) {
1485 void bus_broadcast_reloading(Manager *m, bool active) {
1487 _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
1488 dbus_bool_t b = active;
1492 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
1498 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1499 if (!dbus_message_append_args(message,
1500 DBUS_TYPE_BOOLEAN, &b,
1501 DBUS_TYPE_INVALID)) {
1507 if (bus_broadcast(m, message) < 0) {
1513 Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) {
1519 s = BUS_CONNECTION_SUBSCRIBED(m, c);
1523 s = set_new(string_hash_func, string_compare_func);
1527 if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
1535 void bus_serialize(Manager *m, FILE *f) {
1546 s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus);
1547 SET_FOREACH(client, s, i)
1548 fprintf(f, "subscribed=%s\n", client);
1551 int bus_deserialize_item(Manager *m, const char *line) {
1562 e = startswith(line, "subscribed=");
1566 s = bus_acquire_subscribed(m, m->api_bus);