1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
26 #include <dbus/dbus.h>
34 #include "dbus-unit.h"
36 #include "dbus-manager.h"
37 #include "dbus-service.h"
38 #include "dbus-socket.h"
39 #include "dbus-target.h"
40 #include "dbus-device.h"
41 #include "dbus-mount.h"
42 #include "dbus-automount.h"
43 #include "dbus-snapshot.h"
44 #include "dbus-swap.h"
45 #include "dbus-timer.h"
46 #include "dbus-path.h"
47 #include "bus-errors.h"
49 #include "dbus-common.h"
51 #define CONNECTIONS_MAX 52
53 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
54 #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
55 /* Only used as a fallback */
56 #define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
58 static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
59 static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
61 const char *const bus_interface_table[] = {
62 "org.freedesktop.DBus.Properties", bus_properties_interface,
63 "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
64 "org.freedesktop.systemd1.Manager", bus_manager_interface,
65 "org.freedesktop.systemd1.Job", bus_job_interface,
66 "org.freedesktop.systemd1.Unit", bus_unit_interface,
67 "org.freedesktop.systemd1.Service", bus_service_interface,
68 "org.freedesktop.systemd1.Socket", bus_socket_interface,
69 "org.freedesktop.systemd1.Target", bus_target_interface,
70 "org.freedesktop.systemd1.Device", bus_device_interface,
71 "org.freedesktop.systemd1.Mount", bus_mount_interface,
72 "org.freedesktop.systemd1.Automount", bus_automount_interface,
73 "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface,
74 "org.freedesktop.systemd1.Swap", bus_swap_interface,
75 "org.freedesktop.systemd1.Timer", bus_timer_interface,
76 "org.freedesktop.systemd1.Path", bus_path_interface,
80 static void bus_done_api(Manager *m);
81 static void bus_done_system(Manager *m);
82 static void bus_done_private(Manager *m);
83 static void shutdown_connection(Manager *m, DBusConnection *c);
85 static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data) {
91 /* We maintain two sets, one for those connections where we
92 * requested a dispatch, and another where we didn't. And then,
93 * we move the connections between the two sets. */
95 if (status == DBUS_DISPATCH_COMPLETE)
96 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
98 set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
101 void bus_watch_event(Manager *m, Watch *w, int events) {
105 /* This is called by the event loop whenever there is
106 * something happening on D-Bus' file handles. */
108 if (!dbus_watch_get_enabled(w->data.bus_watch))
111 dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
114 static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
117 struct epoll_event ev;
122 if (!(w = new0(Watch, 1)))
125 w->fd = dbus_watch_get_unix_fd(bus_watch);
126 w->type = WATCH_DBUS_WATCH;
127 w->data.bus_watch = bus_watch;
130 ev.events = bus_flags_to_events(bus_watch);
133 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
135 if (errno != EEXIST) {
140 /* Hmm, bloody D-Bus creates multiple watches on the
141 * same fd. epoll() does not like that. As a dirty
142 * hack we simply dup() the fd and hence get a second
143 * one we can safely add to the epoll(). */
145 if ((w->fd = dup(w->fd)) < 0) {
150 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
151 close_nointr_nofail(w->fd);
156 w->fd_is_dupped = true;
159 dbus_watch_set_data(bus_watch, w, NULL);
164 static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
171 w = dbus_watch_get_data(bus_watch);
175 assert(w->type == WATCH_DBUS_WATCH);
176 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
179 close_nointr_nofail(w->fd);
184 static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
187 struct epoll_event ev;
192 w = dbus_watch_get_data(bus_watch);
196 assert(w->type == WATCH_DBUS_WATCH);
199 ev.events = bus_flags_to_events(bus_watch);
202 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
205 static int bus_timeout_arm(Manager *m, Watch *w) {
206 struct itimerspec its;
213 if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
214 timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
215 its.it_interval = its.it_value;
218 if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
224 void bus_timeout_event(Manager *m, Watch *w, int events) {
228 /* This is called by the event loop whenever there is
229 * something happening on D-Bus' file handles. */
231 if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
234 dbus_timeout_handle(w->data.bus_timeout);
237 static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
240 struct epoll_event ev;
245 if (!(w = new0(Watch, 1)))
248 if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
251 w->type = WATCH_DBUS_TIMEOUT;
252 w->data.bus_timeout = timeout;
254 if (bus_timeout_arm(m, w) < 0)
261 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
264 dbus_timeout_set_data(timeout, w, NULL);
270 close_nointr_nofail(w->fd);
276 static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
283 w = dbus_timeout_get_data(timeout);
287 assert(w->type == WATCH_DBUS_TIMEOUT);
289 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
290 close_nointr_nofail(w->fd);
294 static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
302 w = dbus_timeout_get_data(timeout);
306 assert(w->type == WATCH_DBUS_TIMEOUT);
308 if ((r = bus_timeout_arm(m, w)) < 0)
309 log_error("Failed to rearm timer: %s", strerror(-r));
312 static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
315 DBusMessage *reply = NULL;
321 dbus_error_init(&error);
323 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
324 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
325 log_debug("Got D-Bus request: %s.%s() on %s",
326 dbus_message_get_interface(message),
327 dbus_message_get_member(message),
328 dbus_message_get_path(message));
330 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
331 log_debug("API D-Bus connection terminated.");
334 } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
335 const char *name, *old_owner, *new_owner;
337 if (!dbus_message_get_args(message, &error,
338 DBUS_TYPE_STRING, &name,
339 DBUS_TYPE_STRING, &old_owner,
340 DBUS_TYPE_STRING, &new_owner,
342 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
344 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
345 log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
347 if (old_owner[0] == 0)
350 if (new_owner[0] == 0)
353 manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
355 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
358 if (!dbus_message_get_args(message, &error,
359 DBUS_TYPE_STRING, &name,
361 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
366 log_debug("Got D-Bus activation request for %s", name);
368 if (manager_unit_pending_inactive(m, SPECIAL_DBUS_SERVICE) ||
369 manager_unit_pending_inactive(m, SPECIAL_DBUS_SOCKET)) {
371 dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
373 r = manager_load_unit(m, name, NULL, &error, &u);
375 if (r >= 0 && u->refuse_manual_start)
379 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
383 const char *id, *text;
385 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
387 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
390 id = error.name ? error.name : bus_errno_to_dbus(r);
391 text = bus_error(&error, r);
393 if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
394 !dbus_message_append_args(reply,
395 DBUS_TYPE_STRING, &name,
396 DBUS_TYPE_STRING, &id,
397 DBUS_TYPE_STRING, &text,
402 /* On success we don't do anything, the service will be spawned now */
406 dbus_error_free(&error);
409 if (!bus_maybe_send_reply(connection, message, reply))
412 dbus_message_unref(reply);
415 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
419 dbus_message_unref(reply);
421 dbus_error_free(&error);
423 return DBUS_HANDLER_RESULT_NEED_MEMORY;
426 static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
434 dbus_error_init(&error);
436 if (m->api_bus != m->system_bus &&
437 (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
438 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
439 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
440 dbus_message_get_interface(message),
441 dbus_message_get_member(message),
442 dbus_message_get_path(message));
444 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
445 log_debug("System D-Bus connection terminated.");
448 } else if (m->running_as != SYSTEMD_SYSTEM &&
449 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
453 if (!dbus_message_get_args(message, &error,
454 DBUS_TYPE_STRING, &cgroup,
456 log_error("Failed to parse Released message: %s", bus_error_message(&error));
458 cgroup_notify_empty(m, cgroup);
461 dbus_error_free(&error);
462 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
465 static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
473 dbus_error_init(&error);
475 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
476 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
477 log_debug("Got D-Bus request: %s.%s() on %s",
478 dbus_message_get_interface(message),
479 dbus_message_get_member(message),
480 dbus_message_get_path(message));
482 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
483 shutdown_connection(m, connection);
484 else if (m->running_as == SYSTEMD_SYSTEM &&
485 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
489 if (!dbus_message_get_args(message, &error,
490 DBUS_TYPE_STRING, &cgroup,
492 log_error("Failed to parse Released message: %s", bus_error_message(&error));
494 cgroup_notify_empty(m, cgroup);
496 /* Forward the message to the system bus, so that user
497 * instances are notified as well */
500 dbus_connection_send(m->system_bus, message, NULL);
503 dbus_error_free(&error);
505 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
508 unsigned bus_dispatch(Manager *m) {
513 if (m->queued_message) {
514 /* If we cannot get rid of this message we won't
515 * dispatch any D-Bus messages, so that we won't end
516 * up wanting to queue another message. */
518 if (m->queued_message_connection)
519 if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
522 dbus_message_unref(m->queued_message);
523 m->queued_message = NULL;
524 m->queued_message_connection = NULL;
527 if ((c = set_first(m->bus_connections_for_dispatch))) {
528 if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
529 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
537 static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
541 dbus_error_init(&error);
543 assert_se(reply = dbus_pending_call_steal_reply(pending));
545 switch (dbus_message_get_type(reply)) {
547 case DBUS_MESSAGE_TYPE_ERROR:
549 assert_se(dbus_set_error_from_message(&error, reply));
550 log_warning("RequestName() failed: %s", bus_error_message(&error));
553 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
556 if (!dbus_message_get_args(reply,
558 DBUS_TYPE_UINT32, &r,
559 DBUS_TYPE_INVALID)) {
560 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
565 log_debug("Successfully acquired name.");
567 log_error("Name already owned.");
573 assert_not_reached("Invalid reply message");
576 dbus_message_unref(reply);
577 dbus_error_free(&error);
580 static int request_name(Manager *m) {
581 const char *name = "org.freedesktop.systemd1";
582 /* Allow replacing of our name, to ease implementation of
583 * reexecution, where we keep the old connection open until
584 * after the new connection is set up and the name installed
585 * to allow clients to synchronously wait for reexecution to
587 uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
588 DBusMessage *message = NULL;
589 DBusPendingCall *pending = NULL;
591 if (!(message = dbus_message_new_method_call(
598 if (!dbus_message_append_args(
600 DBUS_TYPE_STRING, &name,
601 DBUS_TYPE_UINT32, &flags,
605 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
608 if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
611 dbus_message_unref(message);
612 dbus_pending_call_unref(pending);
614 /* We simple ask for the name and don't wait for it. Sooner or
615 * later we'll have it. */
621 dbus_pending_call_cancel(pending);
622 dbus_pending_call_unref(pending);
626 dbus_message_unref(message);
631 static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
634 Manager *m = userdata;
638 dbus_error_init(&error);
640 assert_se(reply = dbus_pending_call_steal_reply(pending));
642 switch (dbus_message_get_type(reply)) {
644 case DBUS_MESSAGE_TYPE_ERROR:
646 assert_se(dbus_set_error_from_message(&error, reply));
647 log_warning("ListNames() failed: %s", bus_error_message(&error));
650 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
654 if ((r = bus_parse_strv(reply, &l)) < 0)
655 log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
660 /* This is a bit hacky, we say the
661 * owner of the name is the name
662 * itself, because we don't want the
663 * extra traffic to figure out the
665 manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
674 assert_not_reached("Invalid reply message");
677 dbus_message_unref(reply);
678 dbus_error_free(&error);
681 static int query_name_list(Manager *m) {
682 DBusMessage *message = NULL;
683 DBusPendingCall *pending = NULL;
685 /* Asks for the currently installed bus names */
687 if (!(message = dbus_message_new_method_call(
694 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
697 if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
700 dbus_message_unref(message);
701 dbus_pending_call_unref(pending);
703 /* We simple ask for the list and don't wait for it. Sooner or
704 * later we'll get it. */
710 dbus_pending_call_cancel(pending);
711 dbus_pending_call_unref(pending);
715 dbus_message_unref(message);
720 static int bus_setup_loop(Manager *m, DBusConnection *bus) {
724 dbus_connection_set_exit_on_disconnect(bus, FALSE);
726 if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
727 !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
730 if (set_put(m->bus_connections_for_dispatch, bus) < 0)
733 dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
737 static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
738 return uid == 0 || uid == geteuid();
741 static void bus_new_connection(
743 DBusConnection *new_connection,
750 if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
751 log_error("Too many concurrent connections.");
755 dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
757 if (bus_setup_loop(m, new_connection) < 0)
760 if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
761 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
762 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
763 !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
768 log_debug("Accepted connection on private bus.");
770 dbus_connection_ref(new_connection);
773 static int init_registered_system_bus(Manager *m) {
776 if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
779 if (m->running_as != SYSTEMD_SYSTEM) {
782 dbus_error_init(&error);
784 dbus_bus_add_match(m->system_bus,
786 "interface='org.freedesktop.systemd1.Agent',"
788 "path='/org/freedesktop/systemd1/agent'",
791 if (dbus_error_is_set(&error)) {
792 log_error("Failed to register match: %s", bus_error_message(&error));
793 dbus_error_free(&error);
798 log_debug("Successfully connected to system D-Bus bus %s as %s",
799 strnull((id = dbus_connection_get_server_id(m->system_bus))),
800 strnull(dbus_bus_get_unique_name(m->system_bus)));
806 static int init_registered_api_bus(Manager *m) {
809 if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
810 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
811 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
812 !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
815 /* Get NameOwnerChange messages */
816 dbus_bus_add_match(m->api_bus,
818 "sender='"DBUS_SERVICE_DBUS"',"
819 "interface='"DBUS_INTERFACE_DBUS"',"
820 "member='NameOwnerChanged',"
821 "path='"DBUS_PATH_DBUS"'",
824 /* Get activation requests */
825 dbus_bus_add_match(m->api_bus,
827 "sender='"DBUS_SERVICE_DBUS"',"
828 "interface='org.freedesktop.systemd1.Activator',"
829 "member='ActivationRequest',"
830 "path='"DBUS_PATH_DBUS"'",
837 r = query_name_list(m);
841 if (m->running_as == SYSTEMD_USER) {
843 log_debug("Successfully connected to API D-Bus bus %s as %s",
844 strnull((id = dbus_connection_get_server_id(m->api_bus))),
845 strnull(dbus_bus_get_unique_name(m->api_bus)));
848 log_debug("Successfully initialized API on the system bus");
853 static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
854 Manager *m = userdata;
855 DBusConnection **conn;
861 dbus_error_init(&error);
863 conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
864 assert(conn == &m->system_bus || conn == &m->api_bus);
866 reply = dbus_pending_call_steal_reply(pending);
868 switch (dbus_message_get_type(reply)) {
869 case DBUS_MESSAGE_TYPE_ERROR:
870 assert_se(dbus_set_error_from_message(&error, reply));
871 log_warning("Failed to register to bus: %s", bus_error_message(&error));
874 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
875 if (!dbus_message_get_args(reply, &error,
876 DBUS_TYPE_STRING, &name,
877 DBUS_TYPE_INVALID)) {
878 log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
883 log_debug("Received name %s in reply to Hello", name);
884 if (!dbus_bus_set_unique_name(*conn, name)) {
885 log_error("Failed to set unique name");
890 if (conn == &m->system_bus) {
891 r = init_registered_system_bus(m);
892 if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
893 r = init_registered_api_bus(m);
895 r = init_registered_api_bus(m);
899 assert_not_reached("Invalid reply message");
902 dbus_message_unref(reply);
903 dbus_error_free(&error);
906 if (conn == &m->system_bus) {
907 log_debug("Failed setting up the system bus");
910 log_debug("Failed setting up the API bus");
916 static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
917 DBusMessage *message = NULL;
918 DBusPendingCall *pending = NULL;
920 message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
927 if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
930 if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
933 if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
936 dbus_message_unref(message);
937 dbus_pending_call_unref(pending);
942 dbus_pending_call_cancel(pending);
943 dbus_pending_call_unref(pending);
947 dbus_message_unref(message);
952 static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
954 DBusConnection *connection;
958 case DBUS_BUS_SYSTEM:
959 address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
960 if (!address || !address[0])
961 address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
963 case DBUS_BUS_SESSION:
964 address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
965 if (!address || !address[0])
966 address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
969 assert_not_reached("Invalid bus type");
972 dbus_error_init(&error);
974 connection = dbus_connection_open_private(address, &error);
976 log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
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 == SYSTEMD_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 static const char *const external_only[] = {
1063 dbus_error_init(&error);
1068 if (m->running_as == SYSTEMD_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);
1081 e = secure_getenv("XDG_RUNTIME_DIR");
1085 if (asprintf(&p, "%s/systemd/private", e) < 0) {
1090 mkdir_parents_label(p, 0755);
1094 escaped = dbus_address_escape_value(e);
1099 if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) {
1106 m->private_bus = dbus_server_listen(p, &error);
1110 if (!m->private_bus) {
1111 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
1116 if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1117 !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1118 !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
1123 dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1125 log_debug("Successfully created private D-Bus server.");
1130 bus_done_private(m);
1131 dbus_error_free(&error);
1136 int bus_init(Manager *m, bool try_bus_connect) {
1139 if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1140 set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1143 if (m->name_data_slot < 0)
1144 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1147 if (m->conn_data_slot < 0)
1148 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1151 if (m->subscribed_data_slot < 0)
1152 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1155 if (try_bus_connect) {
1156 if ((r = bus_init_system(m)) < 0 ||
1157 (r = bus_init_api(m)) < 0)
1161 if ((r = bus_init_private(m)) < 0)
1169 static void shutdown_connection(Manager *m, DBusConnection *c) {
1174 HASHMAP_FOREACH(j, m->jobs, i) {
1175 JobBusClient *cl, *nextcl;
1176 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1178 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
1184 set_remove(m->bus_connections, c);
1185 set_remove(m->bus_connections_for_dispatch, c);
1187 if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
1190 while ((t = set_steal_first(s)))
1196 if (m->queued_message_connection == c) {
1197 m->queued_message_connection = NULL;
1199 if (m->queued_message) {
1200 dbus_message_unref(m->queued_message);
1201 m->queued_message = NULL;
1205 dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1206 /* system manager cannot afford to block on DBus */
1207 if (m->running_as != SYSTEMD_SYSTEM)
1208 dbus_connection_flush(c);
1209 dbus_connection_close(c);
1210 dbus_connection_unref(c);
1213 static void bus_done_api(Manager *m) {
1217 if (m->running_as == SYSTEMD_USER)
1218 shutdown_connection(m, m->api_bus);
1222 if (m->queued_message) {
1223 dbus_message_unref(m->queued_message);
1224 m->queued_message = NULL;
1228 static void bus_done_system(Manager *m) {
1232 if (m->running_as == SYSTEMD_SYSTEM)
1235 shutdown_connection(m, m->system_bus);
1236 m->system_bus = NULL;
1239 static void bus_done_private(Manager *m) {
1240 if (!m->private_bus)
1243 dbus_server_disconnect(m->private_bus);
1244 dbus_server_unref(m->private_bus);
1245 m->private_bus = NULL;
1248 void bus_done(Manager *m) {
1253 bus_done_private(m);
1255 while ((c = set_steal_first(m->bus_connections)))
1256 shutdown_connection(m, c);
1258 while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1259 shutdown_connection(m, c);
1261 set_free(m->bus_connections);
1262 set_free(m->bus_connections_for_dispatch);
1264 if (m->name_data_slot >= 0)
1265 dbus_pending_call_free_data_slot(&m->name_data_slot);
1267 if (m->conn_data_slot >= 0)
1268 dbus_pending_call_free_data_slot(&m->conn_data_slot);
1270 if (m->subscribed_data_slot >= 0)
1271 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1274 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1275 Manager *m = userdata;
1280 dbus_error_init(&error);
1282 assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1283 assert_se(reply = dbus_pending_call_steal_reply(pending));
1285 switch (dbus_message_get_type(reply)) {
1287 case DBUS_MESSAGE_TYPE_ERROR:
1289 assert_se(dbus_set_error_from_message(&error, reply));
1290 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1293 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1296 if (!dbus_message_get_args(reply,
1298 DBUS_TYPE_UINT32, &r,
1299 DBUS_TYPE_INVALID)) {
1300 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1304 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1309 assert_not_reached("Invalid reply message");
1312 dbus_message_unref(reply);
1313 dbus_error_free(&error);
1316 int bus_query_pid(Manager *m, const char *name) {
1317 DBusMessage *message = NULL;
1318 DBusPendingCall *pending = NULL;
1324 if (!(message = dbus_message_new_method_call(
1327 DBUS_INTERFACE_DBUS,
1328 "GetConnectionUnixProcessID")))
1331 if (!(dbus_message_append_args(
1333 DBUS_TYPE_STRING, &name,
1334 DBUS_TYPE_INVALID)))
1337 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1340 if (!(n = strdup(name)))
1343 if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1348 if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1351 dbus_message_unref(message);
1352 dbus_pending_call_unref(pending);
1360 dbus_pending_call_cancel(pending);
1361 dbus_pending_call_unref(pending);
1365 dbus_message_unref(message);
1370 int bus_broadcast(Manager *m, DBusMessage *message) {
1378 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1379 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1380 oom = !dbus_connection_send(c, message, NULL);
1382 SET_FOREACH(c, m->bus_connections, i)
1383 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1384 oom = !dbus_connection_send(c, message, NULL);
1386 return oom ? -ENOMEM : 0;
1389 bool bus_has_subscriber(Manager *m) {
1395 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1396 if (bus_connection_has_subscriber(m, c))
1399 SET_FOREACH(c, m->bus_connections, i)
1400 if (bus_connection_has_subscriber(m, c))
1406 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1410 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1413 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1420 /* When we are about to reexecute we add all D-Bus fds to the
1421 * set to pass over to the newly executed systemd. They won't
1422 * be used there however, except that they are closed at the
1423 * very end of deserialization, those making it possible for
1424 * clients to synchronously wait for systemd to reexec by
1425 * simply waiting for disconnection */
1427 SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1430 if (dbus_connection_get_unix_fd(c, &fd)) {
1431 fd = fdset_put_dup(fds, fd);
1438 SET_FOREACH(c, m->bus_connections, i) {
1441 if (dbus_connection_get_unix_fd(c, &fd)) {
1442 fd = fdset_put_dup(fds, fd);
1452 void bus_broadcast_finished(
1454 usec_t firmware_usec,
1458 usec_t userspace_usec,
1459 usec_t total_usec) {
1461 DBusMessage *message;
1465 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1471 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1472 if (!dbus_message_append_args(message,
1473 DBUS_TYPE_UINT64, &firmware_usec,
1474 DBUS_TYPE_UINT64, &loader_usec,
1475 DBUS_TYPE_UINT64, &kernel_usec,
1476 DBUS_TYPE_UINT64, &initrd_usec,
1477 DBUS_TYPE_UINT64, &userspace_usec,
1478 DBUS_TYPE_UINT64, &total_usec,
1479 DBUS_TYPE_INVALID)) {
1485 if (bus_broadcast(m, message) < 0) {
1492 dbus_message_unref(message);