1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
26 #include <dbus/dbus.h>
33 #include "dbus-unit.h"
35 #include "dbus-manager.h"
36 #include "dbus-service.h"
37 #include "dbus-socket.h"
38 #include "dbus-target.h"
39 #include "dbus-device.h"
40 #include "dbus-mount.h"
41 #include "dbus-automount.h"
42 #include "dbus-snapshot.h"
43 #include "dbus-swap.h"
44 #include "dbus-timer.h"
45 #include "dbus-path.h"
46 #include "bus-errors.h"
48 #include "dbus-common.h"
50 #define CONNECTIONS_MAX 52
52 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
53 #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
54 /* Only used as a fallback */
55 #define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
57 static const char bus_properties_interface
[] = BUS_PROPERTIES_INTERFACE
;
58 static const char bus_introspectable_interface
[] = BUS_INTROSPECTABLE_INTERFACE
;
60 const char *const bus_interface_table
[] = {
61 "org.freedesktop.DBus.Properties", bus_properties_interface
,
62 "org.freedesktop.DBus.Introspectable", bus_introspectable_interface
,
63 "org.freedesktop.systemd1.Manager", bus_manager_interface
,
64 "org.freedesktop.systemd1.Job", bus_job_interface
,
65 "org.freedesktop.systemd1.Unit", bus_unit_interface
,
66 "org.freedesktop.systemd1.Service", bus_service_interface
,
67 "org.freedesktop.systemd1.Socket", bus_socket_interface
,
68 "org.freedesktop.systemd1.Target", bus_target_interface
,
69 "org.freedesktop.systemd1.Device", bus_device_interface
,
70 "org.freedesktop.systemd1.Mount", bus_mount_interface
,
71 "org.freedesktop.systemd1.Automount", bus_automount_interface
,
72 "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface
,
73 "org.freedesktop.systemd1.Swap", bus_swap_interface
,
74 "org.freedesktop.systemd1.Timer", bus_timer_interface
,
75 "org.freedesktop.systemd1.Path", bus_path_interface
,
79 static void bus_done_api(Manager
*m
);
80 static void bus_done_system(Manager
*m
);
81 static void bus_done_private(Manager
*m
);
82 static void shutdown_connection(Manager
*m
, DBusConnection
*c
);
84 static void bus_dispatch_status(DBusConnection
*bus
, DBusDispatchStatus status
, void *data
) {
90 /* We maintain two sets, one for those connections where we
91 * requested a dispatch, and another where we didn't. And then,
92 * we move the connections between the two sets. */
94 if (status
== DBUS_DISPATCH_COMPLETE
)
95 set_move_one(m
->bus_connections
, m
->bus_connections_for_dispatch
, bus
);
97 set_move_one(m
->bus_connections_for_dispatch
, m
->bus_connections
, bus
);
100 void bus_watch_event(Manager
*m
, Watch
*w
, int events
) {
104 /* This is called by the event loop whenever there is
105 * something happening on D-Bus' file handles. */
107 if (!dbus_watch_get_enabled(w
->data
.bus_watch
))
110 dbus_watch_handle(w
->data
.bus_watch
, bus_events_to_flags(events
));
113 static dbus_bool_t
bus_add_watch(DBusWatch
*bus_watch
, void *data
) {
116 struct epoll_event ev
;
121 if (!(w
= new0(Watch
, 1)))
124 w
->fd
= dbus_watch_get_unix_fd(bus_watch
);
125 w
->type
= WATCH_DBUS_WATCH
;
126 w
->data
.bus_watch
= bus_watch
;
129 ev
.events
= bus_flags_to_events(bus_watch
);
132 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0) {
134 if (errno
!= EEXIST
) {
139 /* Hmm, bloody D-Bus creates multiple watches on the
140 * same fd. epoll() does not like that. As a dirty
141 * hack we simply dup() the fd and hence get a second
142 * one we can safely add to the epoll(). */
144 if ((w
->fd
= dup(w
->fd
)) < 0) {
149 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0) {
150 close_nointr_nofail(w
->fd
);
155 w
->fd_is_dupped
= true;
158 dbus_watch_set_data(bus_watch
, w
, NULL
);
163 static void bus_remove_watch(DBusWatch
*bus_watch
, void *data
) {
170 w
= dbus_watch_get_data(bus_watch
);
174 assert(w
->type
== WATCH_DBUS_WATCH
);
175 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_DEL
, w
->fd
, NULL
) >= 0);
178 close_nointr_nofail(w
->fd
);
183 static void bus_toggle_watch(DBusWatch
*bus_watch
, void *data
) {
186 struct epoll_event ev
;
191 w
= dbus_watch_get_data(bus_watch
);
195 assert(w
->type
== WATCH_DBUS_WATCH
);
198 ev
.events
= bus_flags_to_events(bus_watch
);
201 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_MOD
, w
->fd
, &ev
) == 0);
204 static int bus_timeout_arm(Manager
*m
, Watch
*w
) {
205 struct itimerspec its
;
212 if (dbus_timeout_get_enabled(w
->data
.bus_timeout
)) {
213 timespec_store(&its
.it_value
, dbus_timeout_get_interval(w
->data
.bus_timeout
) * USEC_PER_MSEC
);
214 its
.it_interval
= its
.it_value
;
217 if (timerfd_settime(w
->fd
, 0, &its
, NULL
) < 0)
223 void bus_timeout_event(Manager
*m
, Watch
*w
, int events
) {
227 /* This is called by the event loop whenever there is
228 * something happening on D-Bus' file handles. */
230 if (!(dbus_timeout_get_enabled(w
->data
.bus_timeout
)))
233 dbus_timeout_handle(w
->data
.bus_timeout
);
236 static dbus_bool_t
bus_add_timeout(DBusTimeout
*timeout
, void *data
) {
239 struct epoll_event ev
;
244 if (!(w
= new0(Watch
, 1)))
247 if ((w
->fd
= timerfd_create(CLOCK_MONOTONIC
, TFD_NONBLOCK
|TFD_CLOEXEC
)) < 0)
250 w
->type
= WATCH_DBUS_TIMEOUT
;
251 w
->data
.bus_timeout
= timeout
;
253 if (bus_timeout_arm(m
, w
) < 0)
260 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0)
263 dbus_timeout_set_data(timeout
, w
, NULL
);
269 close_nointr_nofail(w
->fd
);
275 static void bus_remove_timeout(DBusTimeout
*timeout
, void *data
) {
282 w
= dbus_timeout_get_data(timeout
);
286 assert(w
->type
== WATCH_DBUS_TIMEOUT
);
288 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_DEL
, w
->fd
, NULL
) >= 0);
289 close_nointr_nofail(w
->fd
);
293 static void bus_toggle_timeout(DBusTimeout
*timeout
, void *data
) {
301 w
= dbus_timeout_get_data(timeout
);
305 assert(w
->type
== WATCH_DBUS_TIMEOUT
);
307 if ((r
= bus_timeout_arm(m
, w
)) < 0)
308 log_error("Failed to rearm timer: %s", strerror(-r
));
311 static DBusHandlerResult
api_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
314 DBusMessage
*reply
= NULL
;
320 dbus_error_init(&error
);
322 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
323 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
)
324 log_debug("Got D-Bus request: %s.%s() on %s",
325 dbus_message_get_interface(message
),
326 dbus_message_get_member(message
),
327 dbus_message_get_path(message
));
329 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
330 log_debug("API D-Bus connection terminated.");
333 } else if (dbus_message_is_signal(message
, DBUS_INTERFACE_DBUS
, "NameOwnerChanged")) {
334 const char *name
, *old_owner
, *new_owner
;
336 if (!dbus_message_get_args(message
, &error
,
337 DBUS_TYPE_STRING
, &name
,
338 DBUS_TYPE_STRING
, &old_owner
,
339 DBUS_TYPE_STRING
, &new_owner
,
341 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error
));
343 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m
, connection
), (char*) name
))
344 log_debug("Subscription client vanished: %s (left: %u)", name
, set_size(BUS_CONNECTION_SUBSCRIBED(m
, connection
)));
346 if (old_owner
[0] == 0)
349 if (new_owner
[0] == 0)
352 manager_dispatch_bus_name_owner_changed(m
, name
, old_owner
, new_owner
);
354 } else if (dbus_message_is_signal(message
, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
357 if (!dbus_message_get_args(message
, &error
,
358 DBUS_TYPE_STRING
, &name
,
360 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error
));
365 log_debug("Got D-Bus activation request for %s", name
);
367 if (manager_unit_pending_inactive(m
, SPECIAL_DBUS_SERVICE
) ||
368 manager_unit_pending_inactive(m
, SPECIAL_DBUS_SOCKET
)) {
370 dbus_set_error(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
372 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
374 if (r
>= 0 && u
->refuse_manual_start
)
378 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, true, &error
, NULL
);
382 const char *id
, *text
;
384 log_debug("D-Bus activation failed for %s: %s", name
, strerror(-r
));
386 if (!(reply
= dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
389 id
= error
.name
? error
.name
: bus_errno_to_dbus(r
);
390 text
= bus_error(&error
, r
);
392 if (!dbus_message_set_destination(reply
, DBUS_SERVICE_DBUS
) ||
393 !dbus_message_append_args(reply
,
394 DBUS_TYPE_STRING
, &name
,
395 DBUS_TYPE_STRING
, &id
,
396 DBUS_TYPE_STRING
, &text
,
401 /* On success we don't do anything, the service will be spawned now */
405 dbus_error_free(&error
);
408 if (!dbus_connection_send(connection
, reply
, NULL
))
411 dbus_message_unref(reply
);
414 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
418 dbus_message_unref(reply
);
420 dbus_error_free(&error
);
422 return DBUS_HANDLER_RESULT_NEED_MEMORY
;
425 static DBusHandlerResult
system_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
433 dbus_error_init(&error
);
435 if (m
->api_bus
!= m
->system_bus
&&
436 (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
437 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
))
438 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
439 dbus_message_get_interface(message
),
440 dbus_message_get_member(message
),
441 dbus_message_get_path(message
));
443 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
444 log_debug("System D-Bus connection terminated.");
447 } else if (m
->running_as
!= MANAGER_SYSTEM
&&
448 dbus_message_is_signal(message
, "org.freedesktop.systemd1.Agent", "Released")) {
452 if (!dbus_message_get_args(message
, &error
,
453 DBUS_TYPE_STRING
, &cgroup
,
455 log_error("Failed to parse Released message: %s", bus_error_message(&error
));
457 cgroup_notify_empty(m
, cgroup
);
460 dbus_error_free(&error
);
461 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
464 static DBusHandlerResult
private_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
472 dbus_error_init(&error
);
474 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
475 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
)
476 log_debug("Got D-Bus request: %s.%s() on %s",
477 dbus_message_get_interface(message
),
478 dbus_message_get_member(message
),
479 dbus_message_get_path(message
));
481 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected"))
482 shutdown_connection(m
, connection
);
483 else if (m
->running_as
== MANAGER_SYSTEM
&&
484 dbus_message_is_signal(message
, "org.freedesktop.systemd1.Agent", "Released")) {
488 if (!dbus_message_get_args(message
, &error
,
489 DBUS_TYPE_STRING
, &cgroup
,
491 log_error("Failed to parse Released message: %s", bus_error_message(&error
));
493 cgroup_notify_empty(m
, cgroup
);
495 /* Forward the message to the system bus, so that user
496 * instances are notified as well */
499 dbus_connection_send(m
->system_bus
, message
, NULL
);
502 dbus_error_free(&error
);
504 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
507 unsigned bus_dispatch(Manager
*m
) {
512 if (m
->queued_message
) {
513 /* If we cannot get rid of this message we won't
514 * dispatch any D-Bus messages, so that we won't end
515 * up wanting to queue another message. */
517 if (m
->queued_message_connection
)
518 if (!dbus_connection_send(m
->queued_message_connection
, m
->queued_message
, NULL
))
521 dbus_message_unref(m
->queued_message
);
522 m
->queued_message
= NULL
;
523 m
->queued_message_connection
= NULL
;
526 if ((c
= set_first(m
->bus_connections_for_dispatch
))) {
527 if (dbus_connection_dispatch(c
) == DBUS_DISPATCH_COMPLETE
)
528 set_move_one(m
->bus_connections
, m
->bus_connections_for_dispatch
, c
);
536 static void request_name_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
540 dbus_error_init(&error
);
542 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
544 switch (dbus_message_get_type(reply
)) {
546 case DBUS_MESSAGE_TYPE_ERROR
:
548 assert_se(dbus_set_error_from_message(&error
, reply
));
549 log_warning("RequestName() failed: %s", bus_error_message(&error
));
552 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
555 if (!dbus_message_get_args(reply
,
557 DBUS_TYPE_UINT32
, &r
,
558 DBUS_TYPE_INVALID
)) {
559 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error
));
564 log_debug("Successfully acquired name.");
566 log_error("Name already owned.");
572 assert_not_reached("Invalid reply message");
575 dbus_message_unref(reply
);
576 dbus_error_free(&error
);
579 static int request_name(Manager
*m
) {
580 const char *name
= "org.freedesktop.systemd1";
581 /* Allow replacing of our name, to ease implementation of
582 * reexecution, where we keep the old connection open until
583 * after the new connection is set up and the name installed
584 * to allow clients to synchronously wait for reexecution to
586 uint32_t flags
= DBUS_NAME_FLAG_ALLOW_REPLACEMENT
|DBUS_NAME_FLAG_REPLACE_EXISTING
;
587 DBusMessage
*message
= NULL
;
588 DBusPendingCall
*pending
= NULL
;
590 if (!(message
= dbus_message_new_method_call(
597 if (!dbus_message_append_args(
599 DBUS_TYPE_STRING
, &name
,
600 DBUS_TYPE_UINT32
, &flags
,
604 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
607 if (!dbus_pending_call_set_notify(pending
, request_name_pending_cb
, m
, NULL
))
610 dbus_message_unref(message
);
611 dbus_pending_call_unref(pending
);
613 /* We simple ask for the name and don't wait for it. Sooner or
614 * later we'll have it. */
620 dbus_pending_call_cancel(pending
);
621 dbus_pending_call_unref(pending
);
625 dbus_message_unref(message
);
630 static void query_name_list_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
633 Manager
*m
= userdata
;
637 dbus_error_init(&error
);
639 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
641 switch (dbus_message_get_type(reply
)) {
643 case DBUS_MESSAGE_TYPE_ERROR
:
645 assert_se(dbus_set_error_from_message(&error
, reply
));
646 log_warning("ListNames() failed: %s", bus_error_message(&error
));
649 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
653 if ((r
= bus_parse_strv(reply
, &l
)) < 0)
654 log_warning("Failed to parse ListNames() reply: %s", strerror(-r
));
659 /* This is a bit hacky, we say the
660 * owner of the name is the name
661 * itself, because we don't want the
662 * extra traffic to figure out the
664 manager_dispatch_bus_name_owner_changed(m
, *t
, NULL
, *t
);
673 assert_not_reached("Invalid reply message");
676 dbus_message_unref(reply
);
677 dbus_error_free(&error
);
680 static int query_name_list(Manager
*m
) {
681 DBusMessage
*message
= NULL
;
682 DBusPendingCall
*pending
= NULL
;
684 /* Asks for the currently installed bus names */
686 if (!(message
= dbus_message_new_method_call(
693 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
696 if (!dbus_pending_call_set_notify(pending
, query_name_list_pending_cb
, m
, NULL
))
699 dbus_message_unref(message
);
700 dbus_pending_call_unref(pending
);
702 /* We simple ask for the list and don't wait for it. Sooner or
703 * later we'll get it. */
709 dbus_pending_call_cancel(pending
);
710 dbus_pending_call_unref(pending
);
714 dbus_message_unref(message
);
719 static int bus_setup_loop(Manager
*m
, DBusConnection
*bus
) {
723 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
725 if (!dbus_connection_set_watch_functions(bus
, bus_add_watch
, bus_remove_watch
, bus_toggle_watch
, m
, NULL
) ||
726 !dbus_connection_set_timeout_functions(bus
, bus_add_timeout
, bus_remove_timeout
, bus_toggle_timeout
, m
, NULL
)) {
727 log_error("Not enough memory");
731 if (set_put(m
->bus_connections_for_dispatch
, bus
) < 0) {
732 log_error("Not enough memory");
736 dbus_connection_set_dispatch_status_function(bus
, bus_dispatch_status
, m
, NULL
);
740 static dbus_bool_t
allow_only_same_user(DBusConnection
*connection
, unsigned long uid
, void *data
) {
741 return uid
== 0 || uid
== geteuid();
744 static void bus_new_connection(
746 DBusConnection
*new_connection
,
753 if (set_size(m
->bus_connections
) >= CONNECTIONS_MAX
) {
754 log_error("Too many concurrent connections.");
758 dbus_connection_set_unix_user_function(new_connection
, allow_only_same_user
, NULL
, NULL
);
760 if (bus_setup_loop(m
, new_connection
) < 0)
763 if (!dbus_connection_register_object_path(new_connection
, "/org/freedesktop/systemd1", &bus_manager_vtable
, m
) ||
764 !dbus_connection_register_fallback(new_connection
, "/org/freedesktop/systemd1/unit", &bus_unit_vtable
, m
) ||
765 !dbus_connection_register_fallback(new_connection
, "/org/freedesktop/systemd1/job", &bus_job_vtable
, m
) ||
766 !dbus_connection_add_filter(new_connection
, private_bus_message_filter
, m
, NULL
)) {
767 log_error("Not enough memory.");
771 log_debug("Accepted connection on private bus.");
773 dbus_connection_ref(new_connection
);
776 static int init_registered_system_bus(Manager
*m
) {
779 if (!dbus_connection_add_filter(m
->system_bus
, system_bus_message_filter
, m
, NULL
)) {
780 log_error("Not enough memory");
784 if (m
->running_as
!= MANAGER_SYSTEM
) {
787 dbus_error_init(&error
);
789 dbus_bus_add_match(m
->system_bus
,
791 "interface='org.freedesktop.systemd1.Agent',"
793 "path='/org/freedesktop/systemd1/agent'",
796 if (dbus_error_is_set(&error
)) {
797 log_error("Failed to register match: %s", bus_error_message(&error
));
798 dbus_error_free(&error
);
803 log_debug("Successfully connected to system D-Bus bus %s as %s",
804 strnull((id
= dbus_connection_get_server_id(m
->system_bus
))),
805 strnull(dbus_bus_get_unique_name(m
->system_bus
)));
811 static int init_registered_api_bus(Manager
*m
) {
814 if (!dbus_connection_register_object_path(m
->api_bus
, "/org/freedesktop/systemd1", &bus_manager_vtable
, m
) ||
815 !dbus_connection_register_fallback(m
->api_bus
, "/org/freedesktop/systemd1/unit", &bus_unit_vtable
, m
) ||
816 !dbus_connection_register_fallback(m
->api_bus
, "/org/freedesktop/systemd1/job", &bus_job_vtable
, m
) ||
817 !dbus_connection_add_filter(m
->api_bus
, api_bus_message_filter
, m
, NULL
)) {
818 log_error("Not enough memory");
822 /* Get NameOwnerChange messages */
823 dbus_bus_add_match(m
->api_bus
,
825 "sender='"DBUS_SERVICE_DBUS
"',"
826 "interface='"DBUS_INTERFACE_DBUS
"',"
827 "member='NameOwnerChanged',"
828 "path='"DBUS_PATH_DBUS
"'",
831 /* Get activation requests */
832 dbus_bus_add_match(m
->api_bus
,
834 "sender='"DBUS_SERVICE_DBUS
"',"
835 "interface='org.freedesktop.systemd1.Activator',"
836 "member='ActivationRequest',"
837 "path='"DBUS_PATH_DBUS
"'",
844 r
= query_name_list(m
);
848 if (m
->running_as
== MANAGER_USER
) {
850 log_debug("Successfully connected to API D-Bus bus %s as %s",
851 strnull((id
= dbus_connection_get_server_id(m
->api_bus
))),
852 strnull(dbus_bus_get_unique_name(m
->api_bus
)));
855 log_debug("Successfully initialized API on the system bus");
860 static void bus_register_cb(DBusPendingCall
*pending
, void *userdata
) {
861 Manager
*m
= userdata
;
862 DBusConnection
**conn
;
868 dbus_error_init(&error
);
870 conn
= dbus_pending_call_get_data(pending
, m
->conn_data_slot
);
871 assert(conn
== &m
->system_bus
|| conn
== &m
->api_bus
);
873 reply
= dbus_pending_call_steal_reply(pending
);
875 switch (dbus_message_get_type(reply
)) {
876 case DBUS_MESSAGE_TYPE_ERROR
:
877 assert_se(dbus_set_error_from_message(&error
, reply
));
878 log_warning("Failed to register to bus: %s", bus_error_message(&error
));
881 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
882 if (!dbus_message_get_args(reply
, &error
,
883 DBUS_TYPE_STRING
, &name
,
884 DBUS_TYPE_INVALID
)) {
885 log_error("Failed to parse Hello reply: %s", bus_error_message(&error
));
890 log_debug("Received name %s in reply to Hello", name
);
891 if (!dbus_bus_set_unique_name(*conn
, name
)) {
892 log_error("Failed to set unique name");
897 if (conn
== &m
->system_bus
) {
898 r
= init_registered_system_bus(m
);
899 if (r
== 0 && m
->running_as
== MANAGER_SYSTEM
)
900 r
= init_registered_api_bus(m
);
902 r
= init_registered_api_bus(m
);
906 assert_not_reached("Invalid reply message");
909 dbus_message_unref(reply
);
910 dbus_error_free(&error
);
913 if (conn
== &m
->system_bus
) {
914 log_debug("Failed setting up the system bus");
917 log_debug("Failed setting up the API bus");
923 static int manager_bus_async_register(Manager
*m
, DBusConnection
**conn
) {
924 DBusMessage
*message
= NULL
;
925 DBusPendingCall
*pending
= NULL
;
927 message
= dbus_message_new_method_call(DBUS_SERVICE_DBUS
,
934 if (!dbus_connection_send_with_reply(*conn
, message
, &pending
, -1))
937 if (!dbus_pending_call_set_data(pending
, m
->conn_data_slot
, conn
, NULL
))
940 if (!dbus_pending_call_set_notify(pending
, bus_register_cb
, m
, NULL
))
943 dbus_message_unref(message
);
944 dbus_pending_call_unref(pending
);
949 dbus_pending_call_cancel(pending
);
950 dbus_pending_call_unref(pending
);
954 dbus_message_unref(message
);
959 static DBusConnection
* manager_bus_connect_private(Manager
*m
, DBusBusType type
) {
961 DBusConnection
*connection
;
965 case DBUS_BUS_SYSTEM
:
966 address
= getenv("DBUS_SYSTEM_BUS_ADDRESS");
967 if (!address
|| !address
[0])
968 address
= DBUS_SYSTEM_BUS_DEFAULT_ADDRESS
;
970 case DBUS_BUS_SESSION
:
971 address
= getenv("DBUS_SESSION_BUS_ADDRESS");
972 if (!address
|| !address
[0])
973 address
= DBUS_SESSION_BUS_DEFAULT_ADDRESS
;
976 assert_not_reached("Invalid bus type");
979 dbus_error_init(&error
);
981 connection
= dbus_connection_open_private(address
, &error
);
983 log_warning("Failed to open private bus connection: %s", bus_error_message(&error
));
990 dbus_connection_close(connection
);
991 dbus_error_free(&error
);
995 static int bus_init_system(Manager
*m
) {
1001 m
->system_bus
= manager_bus_connect_private(m
, DBUS_BUS_SYSTEM
);
1002 if (!m
->system_bus
) {
1003 log_debug("Failed to connect to system D-Bus, retrying later");
1008 r
= bus_setup_loop(m
, m
->system_bus
);
1012 r
= manager_bus_async_register(m
, &m
->system_bus
);
1023 static int bus_init_api(Manager
*m
) {
1029 if (m
->running_as
== MANAGER_SYSTEM
) {
1030 m
->api_bus
= m
->system_bus
;
1031 /* In this mode there is no distinct connection to the API bus,
1032 * the API is published on the system bus.
1033 * bus_register_cb() is aware of that and will init the API
1034 * when the system bus gets registered.
1035 * No need to setup anything here. */
1039 m
->api_bus
= manager_bus_connect_private(m
, DBUS_BUS_SESSION
);
1041 log_debug("Failed to connect to API D-Bus, retrying later");
1046 r
= bus_setup_loop(m
, m
->api_bus
);
1050 r
= manager_bus_async_register(m
, &m
->api_bus
);
1061 static int bus_init_private(Manager
*m
) {
1064 const char *const external_only
[] = {
1071 dbus_error_init(&error
);
1076 if (m
->running_as
== MANAGER_SYSTEM
) {
1078 /* We want the private bus only when running as init */
1082 unlink("/run/systemd/private");
1083 m
->private_bus
= dbus_server_listen("unix:path=/run/systemd/private", &error
);
1088 e
= getenv("XDG_RUNTIME_DIR");
1092 if (asprintf(&p
, "unix:path=%s/systemd/private", e
) < 0) {
1093 log_error("Not enough memory");
1098 mkdir_parents_label(p
+10, 0755);
1100 m
->private_bus
= dbus_server_listen(p
, &error
);
1104 if (!m
->private_bus
) {
1105 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error
));
1110 if (!dbus_server_set_auth_mechanisms(m
->private_bus
, (const char**) external_only
) ||
1111 !dbus_server_set_watch_functions(m
->private_bus
, bus_add_watch
, bus_remove_watch
, bus_toggle_watch
, m
, NULL
) ||
1112 !dbus_server_set_timeout_functions(m
->private_bus
, bus_add_timeout
, bus_remove_timeout
, bus_toggle_timeout
, m
, NULL
)) {
1113 log_error("Not enough memory");
1118 dbus_server_set_new_connection_function(m
->private_bus
, bus_new_connection
, m
, NULL
);
1120 log_debug("Successfully created private D-Bus server.");
1125 bus_done_private(m
);
1126 dbus_error_free(&error
);
1131 int bus_init(Manager
*m
, bool try_bus_connect
) {
1134 if (set_ensure_allocated(&m
->bus_connections
, trivial_hash_func
, trivial_compare_func
) < 0 ||
1135 set_ensure_allocated(&m
->bus_connections_for_dispatch
, trivial_hash_func
, trivial_compare_func
) < 0)
1138 if (m
->name_data_slot
< 0)
1139 if (!dbus_pending_call_allocate_data_slot(&m
->name_data_slot
))
1142 if (m
->conn_data_slot
< 0)
1143 if (!dbus_pending_call_allocate_data_slot(&m
->conn_data_slot
))
1146 if (m
->subscribed_data_slot
< 0)
1147 if (!dbus_connection_allocate_data_slot(&m
->subscribed_data_slot
))
1150 if (try_bus_connect
) {
1151 if ((r
= bus_init_system(m
)) < 0 ||
1152 (r
= bus_init_api(m
)) < 0)
1156 if ((r
= bus_init_private(m
)) < 0)
1161 log_error("Not enough memory");
1165 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(JobBusClient
, client
, j
->bus_client_list
, cl
);
1180 set_remove(m
->bus_connections
, c
);
1181 set_remove(m
->bus_connections_for_dispatch
, c
);
1183 if ((s
= BUS_CONNECTION_SUBSCRIBED(m
, c
))) {
1186 while ((t
= set_steal_first(s
)))
1192 if (m
->queued_message_connection
== c
) {
1193 m
->queued_message_connection
= NULL
;
1195 if (m
->queued_message
) {
1196 dbus_message_unref(m
->queued_message
);
1197 m
->queued_message
= NULL
;
1201 dbus_connection_set_dispatch_status_function(c
, NULL
, NULL
, NULL
);
1202 /* system manager cannot afford to block on DBus */
1203 if (m
->running_as
!= MANAGER_SYSTEM
)
1204 dbus_connection_flush(c
);
1205 dbus_connection_close(c
);
1206 dbus_connection_unref(c
);
1209 static void bus_done_api(Manager
*m
) {
1213 if (m
->running_as
== MANAGER_USER
)
1214 shutdown_connection(m
, m
->api_bus
);
1218 if (m
->queued_message
) {
1219 dbus_message_unref(m
->queued_message
);
1220 m
->queued_message
= NULL
;
1224 static void bus_done_system(Manager
*m
) {
1228 if (m
->running_as
== MANAGER_SYSTEM
)
1231 shutdown_connection(m
, m
->system_bus
);
1232 m
->system_bus
= NULL
;
1235 static void bus_done_private(Manager
*m
) {
1236 if (!m
->private_bus
)
1239 dbus_server_disconnect(m
->private_bus
);
1240 dbus_server_unref(m
->private_bus
);
1241 m
->private_bus
= NULL
;
1244 void bus_done(Manager
*m
) {
1249 bus_done_private(m
);
1251 while ((c
= set_steal_first(m
->bus_connections
)))
1252 shutdown_connection(m
, c
);
1254 while ((c
= set_steal_first(m
->bus_connections_for_dispatch
)))
1255 shutdown_connection(m
, c
);
1257 set_free(m
->bus_connections
);
1258 set_free(m
->bus_connections_for_dispatch
);
1260 if (m
->name_data_slot
>= 0)
1261 dbus_pending_call_free_data_slot(&m
->name_data_slot
);
1263 if (m
->conn_data_slot
>= 0)
1264 dbus_pending_call_free_data_slot(&m
->conn_data_slot
);
1266 if (m
->subscribed_data_slot
>= 0)
1267 dbus_connection_free_data_slot(&m
->subscribed_data_slot
);
1270 static void query_pid_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
1271 Manager
*m
= userdata
;
1276 dbus_error_init(&error
);
1278 assert_se(name
= BUS_PENDING_CALL_NAME(m
, pending
));
1279 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
1281 switch (dbus_message_get_type(reply
)) {
1283 case DBUS_MESSAGE_TYPE_ERROR
:
1285 assert_se(dbus_set_error_from_message(&error
, reply
));
1286 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error
));
1289 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
1292 if (!dbus_message_get_args(reply
,
1294 DBUS_TYPE_UINT32
, &r
,
1295 DBUS_TYPE_INVALID
)) {
1296 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error
));
1300 manager_dispatch_bus_query_pid_done(m
, name
, (pid_t
) r
);
1305 assert_not_reached("Invalid reply message");
1308 dbus_message_unref(reply
);
1309 dbus_error_free(&error
);
1312 int bus_query_pid(Manager
*m
, const char *name
) {
1313 DBusMessage
*message
= NULL
;
1314 DBusPendingCall
*pending
= NULL
;
1320 if (!(message
= dbus_message_new_method_call(
1323 DBUS_INTERFACE_DBUS
,
1324 "GetConnectionUnixProcessID")))
1327 if (!(dbus_message_append_args(
1329 DBUS_TYPE_STRING
, &name
,
1330 DBUS_TYPE_INVALID
)))
1333 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
1336 if (!(n
= strdup(name
)))
1339 if (!dbus_pending_call_set_data(pending
, m
->name_data_slot
, n
, free
))
1344 if (!dbus_pending_call_set_notify(pending
, query_pid_pending_cb
, m
, NULL
))
1347 dbus_message_unref(message
);
1348 dbus_pending_call_unref(pending
);
1356 dbus_pending_call_cancel(pending
);
1357 dbus_pending_call_unref(pending
);
1361 dbus_message_unref(message
);
1366 int bus_broadcast(Manager
*m
, DBusMessage
*message
) {
1374 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
)
1375 if (c
!= m
->system_bus
|| m
->running_as
== MANAGER_SYSTEM
)
1376 oom
= !dbus_connection_send(c
, message
, NULL
);
1378 SET_FOREACH(c
, m
->bus_connections
, i
)
1379 if (c
!= m
->system_bus
|| m
->running_as
== MANAGER_SYSTEM
)
1380 oom
= !dbus_connection_send(c
, message
, NULL
);
1382 return oom
? -ENOMEM
: 0;
1385 bool bus_has_subscriber(Manager
*m
) {
1391 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
)
1392 if (bus_connection_has_subscriber(m
, c
))
1395 SET_FOREACH(c
, m
->bus_connections
, i
)
1396 if (bus_connection_has_subscriber(m
, c
))
1402 bool bus_connection_has_subscriber(Manager
*m
, DBusConnection
*c
) {
1406 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m
, c
));
1409 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1416 /* When we are about to reexecute we add all D-Bus fds to the
1417 * set to pass over to the newly executed systemd. They won't
1418 * be used there however, except that they are closed at the
1419 * very end of deserialization, those making it possible for
1420 * clients to synchronously wait for systemd to reexec by
1421 * simply waiting for disconnection */
1423 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
) {
1426 if (dbus_connection_get_unix_fd(c
, &fd
)) {
1427 fd
= fdset_put_dup(fds
, fd
);
1434 SET_FOREACH(c
, m
->bus_connections
, i
) {
1437 if (dbus_connection_get_unix_fd(c
, &fd
)) {
1438 fd
= fdset_put_dup(fds
, fd
);
1448 void bus_broadcast_finished(
1452 usec_t userspace_usec
,
1453 usec_t total_usec
) {
1455 DBusMessage
*message
;
1459 message
= dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1461 log_error("Out of memory.");
1465 assert_cc(sizeof(usec_t
) == sizeof(uint64_t));
1466 if (!dbus_message_append_args(message
,
1467 DBUS_TYPE_UINT64
, &kernel_usec
,
1468 DBUS_TYPE_UINT64
, &initrd_usec
,
1469 DBUS_TYPE_UINT64
, &userspace_usec
,
1470 DBUS_TYPE_UINT64
, &total_usec
,
1471 DBUS_TYPE_INVALID
)) {
1472 log_error("Out of memory.");
1477 if (bus_broadcast(m
, message
) < 0) {
1478 log_error("Out of memory.");
1484 dbus_message_unref(message
);