1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
26 #include <dbus/dbus.h>
33 #include "dbus-unit.h"
35 #include "dbus-manager.h"
36 #include "dbus-service.h"
37 #include "dbus-socket.h"
38 #include "dbus-target.h"
39 #include "dbus-device.h"
40 #include "dbus-mount.h"
41 #include "dbus-automount.h"
42 #include "dbus-snapshot.h"
43 #include "dbus-swap.h"
44 #include "dbus-timer.h"
45 #include "dbus-path.h"
46 #include "bus-errors.h"
48 #include "dbus-common.h"
50 #define CONNECTIONS_MAX 512
52 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
53 #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
54 /* Only used as a fallback */
55 #define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
57 static const char bus_properties_interface
[] = BUS_PROPERTIES_INTERFACE
;
58 static const char bus_introspectable_interface
[] = BUS_INTROSPECTABLE_INTERFACE
;
60 const char *const bus_interface_table
[] = {
61 "org.freedesktop.DBus.Properties", bus_properties_interface
,
62 "org.freedesktop.DBus.Introspectable", bus_introspectable_interface
,
63 "org.freedesktop.systemd1.Manager", bus_manager_interface
,
64 "org.freedesktop.systemd1.Job", bus_job_interface
,
65 "org.freedesktop.systemd1.Unit", bus_unit_interface
,
66 "org.freedesktop.systemd1.Service", bus_service_interface
,
67 "org.freedesktop.systemd1.Socket", bus_socket_interface
,
68 "org.freedesktop.systemd1.Target", bus_target_interface
,
69 "org.freedesktop.systemd1.Device", bus_device_interface
,
70 "org.freedesktop.systemd1.Mount", bus_mount_interface
,
71 "org.freedesktop.systemd1.Automount", bus_automount_interface
,
72 "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface
,
73 "org.freedesktop.systemd1.Swap", bus_swap_interface
,
74 "org.freedesktop.systemd1.Timer", bus_timer_interface
,
75 "org.freedesktop.systemd1.Path", bus_path_interface
,
79 static void bus_done_api(Manager
*m
);
80 static void bus_done_system(Manager
*m
);
81 static void bus_done_private(Manager
*m
);
82 static void shutdown_connection(Manager
*m
, DBusConnection
*c
);
84 static void bus_dispatch_status(DBusConnection
*bus
, DBusDispatchStatus status
, void *data
) {
90 /* We maintain two sets, one for those connections where we
91 * requested a dispatch, and another where we didn't. And then,
92 * we move the connections between the two sets. */
94 if (status
== DBUS_DISPATCH_COMPLETE
)
95 set_move_one(m
->bus_connections
, m
->bus_connections_for_dispatch
, bus
);
97 set_move_one(m
->bus_connections_for_dispatch
, m
->bus_connections
, bus
);
100 void bus_watch_event(Manager
*m
, Watch
*w
, int events
) {
104 /* This is called by the event loop whenever there is
105 * something happening on D-Bus' file handles. */
107 if (!dbus_watch_get_enabled(w
->data
.bus_watch
))
110 dbus_watch_handle(w
->data
.bus_watch
, bus_events_to_flags(events
));
113 static dbus_bool_t
bus_add_watch(DBusWatch
*bus_watch
, void *data
) {
116 struct epoll_event ev
;
121 if (!(w
= new0(Watch
, 1)))
124 w
->fd
= dbus_watch_get_unix_fd(bus_watch
);
125 w
->type
= WATCH_DBUS_WATCH
;
126 w
->data
.bus_watch
= bus_watch
;
129 ev
.events
= bus_flags_to_events(bus_watch
);
132 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0) {
134 if (errno
!= EEXIST
) {
139 /* Hmm, bloody D-Bus creates multiple watches on the
140 * same fd. epoll() does not like that. As a dirty
141 * hack we simply dup() the fd and hence get a second
142 * one we can safely add to the epoll(). */
144 if ((w
->fd
= dup(w
->fd
)) < 0) {
149 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0) {
150 close_nointr_nofail(w
->fd
);
155 w
->fd_is_dupped
= true;
158 dbus_watch_set_data(bus_watch
, w
, NULL
);
163 static void bus_remove_watch(DBusWatch
*bus_watch
, void *data
) {
170 w
= dbus_watch_get_data(bus_watch
);
174 assert(w
->type
== WATCH_DBUS_WATCH
);
175 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_DEL
, w
->fd
, NULL
) >= 0);
178 close_nointr_nofail(w
->fd
);
183 static void bus_toggle_watch(DBusWatch
*bus_watch
, void *data
) {
186 struct epoll_event ev
;
191 w
= dbus_watch_get_data(bus_watch
);
195 assert(w
->type
== WATCH_DBUS_WATCH
);
198 ev
.events
= bus_flags_to_events(bus_watch
);
201 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_MOD
, w
->fd
, &ev
) == 0);
204 static int bus_timeout_arm(Manager
*m
, Watch
*w
) {
205 struct itimerspec its
= {};
210 if (dbus_timeout_get_enabled(w
->data
.bus_timeout
)) {
211 timespec_store(&its
.it_value
, dbus_timeout_get_interval(w
->data
.bus_timeout
) * USEC_PER_MSEC
);
212 its
.it_interval
= its
.it_value
;
215 if (timerfd_settime(w
->fd
, 0, &its
, NULL
) < 0)
221 void bus_timeout_event(Manager
*m
, Watch
*w
, int events
) {
225 /* This is called by the event loop whenever there is
226 * something happening on D-Bus' file handles. */
228 if (!(dbus_timeout_get_enabled(w
->data
.bus_timeout
)))
231 dbus_timeout_handle(w
->data
.bus_timeout
);
234 static dbus_bool_t
bus_add_timeout(DBusTimeout
*timeout
, void *data
) {
237 struct epoll_event ev
;
242 if (!(w
= new0(Watch
, 1)))
245 if ((w
->fd
= timerfd_create(CLOCK_MONOTONIC
, TFD_NONBLOCK
|TFD_CLOEXEC
)) < 0)
248 w
->type
= WATCH_DBUS_TIMEOUT
;
249 w
->data
.bus_timeout
= timeout
;
251 if (bus_timeout_arm(m
, w
) < 0)
258 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0)
261 dbus_timeout_set_data(timeout
, w
, NULL
);
267 close_nointr_nofail(w
->fd
);
273 static void bus_remove_timeout(DBusTimeout
*timeout
, void *data
) {
280 w
= dbus_timeout_get_data(timeout
);
284 assert(w
->type
== WATCH_DBUS_TIMEOUT
);
286 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_DEL
, w
->fd
, NULL
) >= 0);
287 close_nointr_nofail(w
->fd
);
291 static void bus_toggle_timeout(DBusTimeout
*timeout
, void *data
) {
299 w
= dbus_timeout_get_data(timeout
);
303 assert(w
->type
== WATCH_DBUS_TIMEOUT
);
305 if ((r
= bus_timeout_arm(m
, w
)) < 0)
306 log_error("Failed to rearm timer: %s", strerror(-r
));
309 static DBusHandlerResult
api_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
312 DBusMessage
*reply
= NULL
;
318 dbus_error_init(&error
);
320 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
321 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
)
322 log_debug("Got D-Bus request: %s.%s() on %s",
323 dbus_message_get_interface(message
),
324 dbus_message_get_member(message
),
325 dbus_message_get_path(message
));
327 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
328 log_debug("API D-Bus connection terminated.");
331 } else if (dbus_message_is_signal(message
, DBUS_INTERFACE_DBUS
, "NameOwnerChanged")) {
332 const char *name
, *old_owner
, *new_owner
;
334 if (!dbus_message_get_args(message
, &error
,
335 DBUS_TYPE_STRING
, &name
,
336 DBUS_TYPE_STRING
, &old_owner
,
337 DBUS_TYPE_STRING
, &new_owner
,
339 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error
));
341 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m
, connection
), (char*) name
))
342 log_debug("Subscription client vanished: %s (left: %u)", name
, set_size(BUS_CONNECTION_SUBSCRIBED(m
, connection
)));
344 if (old_owner
[0] == 0)
347 if (new_owner
[0] == 0)
350 manager_dispatch_bus_name_owner_changed(m
, name
, old_owner
, new_owner
);
352 } else if (dbus_message_is_signal(message
, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
355 if (!dbus_message_get_args(message
, &error
,
356 DBUS_TYPE_STRING
, &name
,
358 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error
));
363 log_debug("Got D-Bus activation request for %s", name
);
365 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
366 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
368 dbus_set_error(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
370 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
372 if (r
>= 0 && u
->refuse_manual_start
)
376 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, true, &error
, NULL
);
380 const char *id
, *text
;
382 log_debug("D-Bus activation failed for %s: %s", name
, strerror(-r
));
384 if (!(reply
= dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
387 id
= error
.name
? error
.name
: bus_errno_to_dbus(r
);
388 text
= bus_error(&error
, r
);
390 if (!dbus_message_set_destination(reply
, DBUS_SERVICE_DBUS
) ||
391 !dbus_message_append_args(reply
,
392 DBUS_TYPE_STRING
, &name
,
393 DBUS_TYPE_STRING
, &id
,
394 DBUS_TYPE_STRING
, &text
,
399 /* On success we don't do anything, the service will be spawned now */
403 dbus_error_free(&error
);
406 if (!bus_maybe_send_reply(connection
, message
, reply
))
409 dbus_message_unref(reply
);
412 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
416 dbus_message_unref(reply
);
418 dbus_error_free(&error
);
420 return DBUS_HANDLER_RESULT_NEED_MEMORY
;
423 static DBusHandlerResult
system_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
431 dbus_error_init(&error
);
433 if (m
->api_bus
!= m
->system_bus
&&
434 (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
435 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
))
436 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
437 dbus_message_get_interface(message
),
438 dbus_message_get_member(message
),
439 dbus_message_get_path(message
));
441 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
442 log_debug("System D-Bus connection terminated.");
445 } else if (m
->running_as
!= SYSTEMD_SYSTEM
&&
446 dbus_message_is_signal(message
, "org.freedesktop.systemd1.Agent", "Released")) {
450 if (!dbus_message_get_args(message
, &error
,
451 DBUS_TYPE_STRING
, &cgroup
,
453 log_error("Failed to parse Released message: %s", bus_error_message(&error
));
455 manager_notify_cgroup_empty(m
, cgroup
);
458 dbus_error_free(&error
);
459 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
462 static DBusHandlerResult
private_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
470 dbus_error_init(&error
);
472 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
473 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
)
474 log_debug("Got D-Bus request: %s.%s() on %s",
475 dbus_message_get_interface(message
),
476 dbus_message_get_member(message
),
477 dbus_message_get_path(message
));
479 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected"))
480 shutdown_connection(m
, connection
);
481 else if (m
->running_as
== SYSTEMD_SYSTEM
&&
482 dbus_message_is_signal(message
, "org.freedesktop.systemd1.Agent", "Released")) {
486 if (!dbus_message_get_args(message
, &error
,
487 DBUS_TYPE_STRING
, &cgroup
,
489 log_error("Failed to parse Released message: %s", bus_error_message(&error
));
491 manager_notify_cgroup_empty(m
, cgroup
);
493 /* Forward the message to the system bus, so that user
494 * instances are notified as well */
497 dbus_connection_send(m
->system_bus
, message
, NULL
);
500 dbus_error_free(&error
);
502 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
505 unsigned bus_dispatch(Manager
*m
) {
510 if (m
->queued_message
) {
511 /* If we cannot get rid of this message we won't
512 * dispatch any D-Bus messages, so that we won't end
513 * up wanting to queue another message. */
515 if (m
->queued_message_connection
)
516 if (!dbus_connection_send(m
->queued_message_connection
, m
->queued_message
, NULL
))
519 dbus_message_unref(m
->queued_message
);
520 m
->queued_message
= NULL
;
521 m
->queued_message_connection
= NULL
;
524 if ((c
= set_first(m
->bus_connections_for_dispatch
))) {
525 if (dbus_connection_dispatch(c
) == DBUS_DISPATCH_COMPLETE
)
526 set_move_one(m
->bus_connections
, m
->bus_connections_for_dispatch
, c
);
534 static void request_name_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
538 dbus_error_init(&error
);
540 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
542 switch (dbus_message_get_type(reply
)) {
544 case DBUS_MESSAGE_TYPE_ERROR
:
546 assert_se(dbus_set_error_from_message(&error
, reply
));
547 log_warning("RequestName() failed: %s", bus_error_message(&error
));
550 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
553 if (!dbus_message_get_args(reply
,
555 DBUS_TYPE_UINT32
, &r
,
556 DBUS_TYPE_INVALID
)) {
557 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error
));
562 log_debug("Successfully acquired name.");
564 log_error("Name already owned.");
570 assert_not_reached("Invalid reply message");
573 dbus_message_unref(reply
);
574 dbus_error_free(&error
);
577 static int request_name(Manager
*m
) {
578 const char *name
= "org.freedesktop.systemd1";
579 /* Allow replacing of our name, to ease implementation of
580 * reexecution, where we keep the old connection open until
581 * after the new connection is set up and the name installed
582 * to allow clients to synchronously wait for reexecution to
584 uint32_t flags
= DBUS_NAME_FLAG_ALLOW_REPLACEMENT
|DBUS_NAME_FLAG_REPLACE_EXISTING
;
585 DBusMessage
*message
= NULL
;
586 DBusPendingCall
*pending
= NULL
;
588 if (!(message
= dbus_message_new_method_call(
595 if (!dbus_message_append_args(
597 DBUS_TYPE_STRING
, &name
,
598 DBUS_TYPE_UINT32
, &flags
,
602 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
605 if (!dbus_pending_call_set_notify(pending
, request_name_pending_cb
, m
, NULL
))
608 dbus_message_unref(message
);
609 dbus_pending_call_unref(pending
);
611 /* We simple ask for the name and don't wait for it. Sooner or
612 * later we'll have it. */
618 dbus_pending_call_cancel(pending
);
619 dbus_pending_call_unref(pending
);
623 dbus_message_unref(message
);
628 static void query_name_list_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
631 Manager
*m
= userdata
;
635 dbus_error_init(&error
);
637 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
639 switch (dbus_message_get_type(reply
)) {
641 case DBUS_MESSAGE_TYPE_ERROR
:
643 assert_se(dbus_set_error_from_message(&error
, reply
));
644 log_warning("ListNames() failed: %s", bus_error_message(&error
));
647 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
651 if ((r
= bus_parse_strv(reply
, &l
)) < 0)
652 log_warning("Failed to parse ListNames() reply: %s", strerror(-r
));
657 /* This is a bit hacky, we say the
658 * owner of the name is the name
659 * itself, because we don't want the
660 * extra traffic to figure out the
662 manager_dispatch_bus_name_owner_changed(m
, *t
, NULL
, *t
);
671 assert_not_reached("Invalid reply message");
674 dbus_message_unref(reply
);
675 dbus_error_free(&error
);
678 static int query_name_list(Manager
*m
) {
679 DBusMessage
*message
= NULL
;
680 DBusPendingCall
*pending
= NULL
;
682 /* Asks for the currently installed bus names */
684 if (!(message
= dbus_message_new_method_call(
691 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
694 if (!dbus_pending_call_set_notify(pending
, query_name_list_pending_cb
, m
, NULL
))
697 dbus_message_unref(message
);
698 dbus_pending_call_unref(pending
);
700 /* We simple ask for the list and don't wait for it. Sooner or
701 * later we'll get it. */
707 dbus_pending_call_cancel(pending
);
708 dbus_pending_call_unref(pending
);
712 dbus_message_unref(message
);
717 static int bus_setup_loop(Manager
*m
, DBusConnection
*bus
) {
721 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
723 if (!dbus_connection_set_watch_functions(bus
, bus_add_watch
, bus_remove_watch
, bus_toggle_watch
, m
, NULL
) ||
724 !dbus_connection_set_timeout_functions(bus
, bus_add_timeout
, bus_remove_timeout
, bus_toggle_timeout
, m
, NULL
))
727 if (set_put(m
->bus_connections_for_dispatch
, bus
) < 0)
730 dbus_connection_set_dispatch_status_function(bus
, bus_dispatch_status
, m
, NULL
);
734 static dbus_bool_t
allow_only_same_user(DBusConnection
*connection
, unsigned long uid
, void *data
) {
735 return uid
== 0 || uid
== geteuid();
738 static void bus_new_connection(
740 DBusConnection
*new_connection
,
747 if (set_size(m
->bus_connections
) >= CONNECTIONS_MAX
) {
748 log_error("Too many concurrent connections.");
752 dbus_connection_set_unix_user_function(new_connection
, allow_only_same_user
, NULL
, NULL
);
754 if (bus_setup_loop(m
, new_connection
) < 0)
757 if (!dbus_connection_register_object_path(new_connection
, "/org/freedesktop/systemd1", &bus_manager_vtable
, m
) ||
758 !dbus_connection_register_fallback(new_connection
, "/org/freedesktop/systemd1/unit", &bus_unit_vtable
, m
) ||
759 !dbus_connection_register_fallback(new_connection
, "/org/freedesktop/systemd1/job", &bus_job_vtable
, m
) ||
760 !dbus_connection_add_filter(new_connection
, private_bus_message_filter
, m
, NULL
)) {
765 log_debug("Accepted connection on private bus.");
767 dbus_connection_ref(new_connection
);
770 static int init_registered_system_bus(Manager
*m
) {
773 if (!dbus_connection_add_filter(m
->system_bus
, system_bus_message_filter
, m
, NULL
))
776 if (m
->running_as
!= SYSTEMD_SYSTEM
) {
779 dbus_error_init(&error
);
781 dbus_bus_add_match(m
->system_bus
,
783 "interface='org.freedesktop.systemd1.Agent',"
785 "path='/org/freedesktop/systemd1/agent'",
788 if (dbus_error_is_set(&error
)) {
789 log_error("Failed to register match: %s", bus_error_message(&error
));
790 dbus_error_free(&error
);
795 log_debug("Successfully connected to system D-Bus bus %s as %s",
796 strnull((id
= dbus_connection_get_server_id(m
->system_bus
))),
797 strnull(dbus_bus_get_unique_name(m
->system_bus
)));
803 static int init_registered_api_bus(Manager
*m
) {
806 if (!dbus_connection_register_object_path(m
->api_bus
, "/org/freedesktop/systemd1", &bus_manager_vtable
, m
) ||
807 !dbus_connection_register_fallback(m
->api_bus
, "/org/freedesktop/systemd1/unit", &bus_unit_vtable
, m
) ||
808 !dbus_connection_register_fallback(m
->api_bus
, "/org/freedesktop/systemd1/job", &bus_job_vtable
, m
) ||
809 !dbus_connection_add_filter(m
->api_bus
, api_bus_message_filter
, m
, NULL
))
812 /* Get NameOwnerChange messages */
813 dbus_bus_add_match(m
->api_bus
,
815 "sender='"DBUS_SERVICE_DBUS
"',"
816 "interface='"DBUS_INTERFACE_DBUS
"',"
817 "member='NameOwnerChanged',"
818 "path='"DBUS_PATH_DBUS
"'",
821 /* Get activation requests */
822 dbus_bus_add_match(m
->api_bus
,
824 "sender='"DBUS_SERVICE_DBUS
"',"
825 "interface='org.freedesktop.systemd1.Activator',"
826 "member='ActivationRequest',"
827 "path='"DBUS_PATH_DBUS
"'",
834 r
= query_name_list(m
);
838 if (m
->running_as
== SYSTEMD_USER
) {
840 log_debug("Successfully connected to API D-Bus bus %s as %s",
841 strnull((id
= dbus_connection_get_server_id(m
->api_bus
))),
842 strnull(dbus_bus_get_unique_name(m
->api_bus
)));
845 log_debug("Successfully initialized API on the system bus");
850 static void bus_register_cb(DBusPendingCall
*pending
, void *userdata
) {
851 Manager
*m
= userdata
;
852 DBusConnection
**conn
;
858 dbus_error_init(&error
);
860 conn
= dbus_pending_call_get_data(pending
, m
->conn_data_slot
);
861 assert(conn
== &m
->system_bus
|| conn
== &m
->api_bus
);
863 reply
= dbus_pending_call_steal_reply(pending
);
865 switch (dbus_message_get_type(reply
)) {
866 case DBUS_MESSAGE_TYPE_ERROR
:
867 assert_se(dbus_set_error_from_message(&error
, reply
));
868 log_warning("Failed to register to bus: %s", bus_error_message(&error
));
871 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
872 if (!dbus_message_get_args(reply
, &error
,
873 DBUS_TYPE_STRING
, &name
,
874 DBUS_TYPE_INVALID
)) {
875 log_error("Failed to parse Hello reply: %s", bus_error_message(&error
));
880 log_debug("Received name %s in reply to Hello", name
);
881 if (!dbus_bus_set_unique_name(*conn
, name
)) {
882 log_error("Failed to set unique name");
887 if (conn
== &m
->system_bus
) {
888 r
= init_registered_system_bus(m
);
889 if (r
== 0 && m
->running_as
== SYSTEMD_SYSTEM
)
890 r
= init_registered_api_bus(m
);
892 r
= init_registered_api_bus(m
);
896 assert_not_reached("Invalid reply message");
899 dbus_message_unref(reply
);
900 dbus_error_free(&error
);
903 if (conn
== &m
->system_bus
) {
904 log_debug("Failed setting up the system bus");
907 log_debug("Failed setting up the API bus");
913 static int manager_bus_async_register(Manager
*m
, DBusConnection
**conn
) {
914 DBusMessage
*message
= NULL
;
915 DBusPendingCall
*pending
= NULL
;
917 message
= dbus_message_new_method_call(DBUS_SERVICE_DBUS
,
924 if (!dbus_connection_send_with_reply(*conn
, message
, &pending
, -1))
927 if (!dbus_pending_call_set_data(pending
, m
->conn_data_slot
, conn
, NULL
))
930 if (!dbus_pending_call_set_notify(pending
, bus_register_cb
, m
, NULL
))
933 dbus_message_unref(message
);
934 dbus_pending_call_unref(pending
);
939 dbus_pending_call_cancel(pending
);
940 dbus_pending_call_unref(pending
);
944 dbus_message_unref(message
);
949 static DBusConnection
* manager_bus_connect_private(Manager
*m
, DBusBusType type
) {
951 DBusConnection
*connection
;
955 case DBUS_BUS_SYSTEM
:
956 address
= secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
957 if (!address
|| !address
[0])
958 address
= DBUS_SYSTEM_BUS_DEFAULT_ADDRESS
;
960 case DBUS_BUS_SESSION
:
961 address
= secure_getenv("DBUS_SESSION_BUS_ADDRESS");
962 if (!address
|| !address
[0])
963 address
= DBUS_SESSION_BUS_DEFAULT_ADDRESS
;
966 assert_not_reached("Invalid bus type");
969 dbus_error_init(&error
);
971 connection
= dbus_connection_open_private(address
, &error
);
973 log_warning("Failed to open private bus connection: %s", bus_error_message(&error
));
980 dbus_error_free(&error
);
984 static int bus_init_system(Manager
*m
) {
990 m
->system_bus
= manager_bus_connect_private(m
, DBUS_BUS_SYSTEM
);
991 if (!m
->system_bus
) {
992 log_debug("Failed to connect to system D-Bus, retrying later");
997 r
= bus_setup_loop(m
, m
->system_bus
);
1001 r
= manager_bus_async_register(m
, &m
->system_bus
);
1012 static int bus_init_api(Manager
*m
) {
1018 if (m
->running_as
== SYSTEMD_SYSTEM
) {
1019 m
->api_bus
= m
->system_bus
;
1020 /* In this mode there is no distinct connection to the API bus,
1021 * the API is published on the system bus.
1022 * bus_register_cb() is aware of that and will init the API
1023 * when the system bus gets registered.
1024 * No need to setup anything here. */
1028 m
->api_bus
= manager_bus_connect_private(m
, DBUS_BUS_SESSION
);
1030 log_debug("Failed to connect to API D-Bus, retrying later");
1035 r
= bus_setup_loop(m
, m
->api_bus
);
1039 r
= manager_bus_async_register(m
, &m
->api_bus
);
1050 static int bus_init_private(Manager
*m
) {
1053 static const char *const external_only
[] = {
1060 dbus_error_init(&error
);
1065 if (m
->running_as
== SYSTEMD_SYSTEM
) {
1067 /* We want the private bus only when running as init */
1071 unlink("/run/systemd/private");
1072 m
->private_bus
= dbus_server_listen("unix:path=/run/systemd/private", &error
);
1078 e
= secure_getenv("XDG_RUNTIME_DIR");
1082 if (asprintf(&p
, "%s/systemd/private", e
) < 0) {
1087 mkdir_parents_label(p
, 0755);
1091 escaped
= dbus_address_escape_value(e
);
1096 if (asprintf(&p
, "unix:path=%s/systemd/private", escaped
) < 0) {
1103 m
->private_bus
= dbus_server_listen(p
, &error
);
1107 if (!m
->private_bus
) {
1108 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error
));
1113 if (!dbus_server_set_auth_mechanisms(m
->private_bus
, (const char**) external_only
) ||
1114 !dbus_server_set_watch_functions(m
->private_bus
, bus_add_watch
, bus_remove_watch
, bus_toggle_watch
, m
, NULL
) ||
1115 !dbus_server_set_timeout_functions(m
->private_bus
, bus_add_timeout
, bus_remove_timeout
, bus_toggle_timeout
, m
, NULL
)) {
1120 dbus_server_set_new_connection_function(m
->private_bus
, bus_new_connection
, m
, NULL
);
1122 log_debug("Successfully created private D-Bus server.");
1127 bus_done_private(m
);
1128 dbus_error_free(&error
);
1133 int bus_init(Manager
*m
, bool try_bus_connect
) {
1136 if (set_ensure_allocated(&m
->bus_connections
, trivial_hash_func
, trivial_compare_func
) < 0 ||
1137 set_ensure_allocated(&m
->bus_connections_for_dispatch
, trivial_hash_func
, trivial_compare_func
) < 0)
1140 if (m
->name_data_slot
< 0)
1141 if (!dbus_pending_call_allocate_data_slot(&m
->name_data_slot
))
1144 if (m
->conn_data_slot
< 0)
1145 if (!dbus_pending_call_allocate_data_slot(&m
->conn_data_slot
))
1148 if (m
->subscribed_data_slot
< 0)
1149 if (!dbus_connection_allocate_data_slot(&m
->subscribed_data_slot
))
1152 if (try_bus_connect
) {
1153 if ((r
= bus_init_system(m
)) < 0 ||
1154 (r
= bus_init_api(m
)) < 0)
1158 if ((r
= bus_init_private(m
)) < 0)
1166 static void shutdown_connection(Manager
*m
, DBusConnection
*c
) {
1171 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
1172 JobBusClient
*cl
, *nextcl
;
1173 LIST_FOREACH_SAFE(client
, cl
, nextcl
, j
->bus_client_list
) {
1175 LIST_REMOVE(JobBusClient
, client
, j
->bus_client_list
, cl
);
1181 set_remove(m
->bus_connections
, c
);
1182 set_remove(m
->bus_connections_for_dispatch
, c
);
1184 if ((s
= BUS_CONNECTION_SUBSCRIBED(m
, c
))) {
1187 while ((t
= set_steal_first(s
)))
1193 if (m
->queued_message_connection
== c
) {
1194 m
->queued_message_connection
= NULL
;
1196 if (m
->queued_message
) {
1197 dbus_message_unref(m
->queued_message
);
1198 m
->queued_message
= NULL
;
1202 dbus_connection_set_dispatch_status_function(c
, NULL
, NULL
, NULL
);
1203 /* system manager cannot afford to block on DBus */
1204 if (m
->running_as
!= SYSTEMD_SYSTEM
)
1205 dbus_connection_flush(c
);
1206 dbus_connection_close(c
);
1207 dbus_connection_unref(c
);
1210 static void bus_done_api(Manager
*m
) {
1214 if (m
->running_as
== SYSTEMD_USER
)
1215 shutdown_connection(m
, m
->api_bus
);
1219 if (m
->queued_message
) {
1220 dbus_message_unref(m
->queued_message
);
1221 m
->queued_message
= NULL
;
1225 static void bus_done_system(Manager
*m
) {
1229 if (m
->running_as
== SYSTEMD_SYSTEM
)
1232 shutdown_connection(m
, m
->system_bus
);
1233 m
->system_bus
= NULL
;
1236 static void bus_done_private(Manager
*m
) {
1237 if (!m
->private_bus
)
1240 dbus_server_disconnect(m
->private_bus
);
1241 dbus_server_unref(m
->private_bus
);
1242 m
->private_bus
= NULL
;
1245 void bus_done(Manager
*m
) {
1250 bus_done_private(m
);
1252 while ((c
= set_steal_first(m
->bus_connections
)))
1253 shutdown_connection(m
, c
);
1255 while ((c
= set_steal_first(m
->bus_connections_for_dispatch
)))
1256 shutdown_connection(m
, c
);
1258 set_free(m
->bus_connections
);
1259 set_free(m
->bus_connections_for_dispatch
);
1261 if (m
->name_data_slot
>= 0)
1262 dbus_pending_call_free_data_slot(&m
->name_data_slot
);
1264 if (m
->conn_data_slot
>= 0)
1265 dbus_pending_call_free_data_slot(&m
->conn_data_slot
);
1267 if (m
->subscribed_data_slot
>= 0)
1268 dbus_connection_free_data_slot(&m
->subscribed_data_slot
);
1271 static void query_pid_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
1272 Manager
*m
= userdata
;
1277 dbus_error_init(&error
);
1279 assert_se(name
= BUS_PENDING_CALL_NAME(m
, pending
));
1280 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
1282 switch (dbus_message_get_type(reply
)) {
1284 case DBUS_MESSAGE_TYPE_ERROR
:
1286 assert_se(dbus_set_error_from_message(&error
, reply
));
1287 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error
));
1290 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
1293 if (!dbus_message_get_args(reply
,
1295 DBUS_TYPE_UINT32
, &r
,
1296 DBUS_TYPE_INVALID
)) {
1297 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error
));
1301 manager_dispatch_bus_query_pid_done(m
, name
, (pid_t
) r
);
1306 assert_not_reached("Invalid reply message");
1309 dbus_message_unref(reply
);
1310 dbus_error_free(&error
);
1313 int bus_query_pid(Manager
*m
, const char *name
) {
1314 DBusMessage
*message
= NULL
;
1315 DBusPendingCall
*pending
= NULL
;
1321 if (!(message
= dbus_message_new_method_call(
1324 DBUS_INTERFACE_DBUS
,
1325 "GetConnectionUnixProcessID")))
1328 if (!(dbus_message_append_args(
1330 DBUS_TYPE_STRING
, &name
,
1331 DBUS_TYPE_INVALID
)))
1334 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
1337 if (!(n
= strdup(name
)))
1340 if (!dbus_pending_call_set_data(pending
, m
->name_data_slot
, n
, free
))
1345 if (!dbus_pending_call_set_notify(pending
, query_pid_pending_cb
, m
, NULL
))
1348 dbus_message_unref(message
);
1349 dbus_pending_call_unref(pending
);
1357 dbus_pending_call_cancel(pending
);
1358 dbus_pending_call_unref(pending
);
1362 dbus_message_unref(message
);
1367 int bus_broadcast(Manager
*m
, DBusMessage
*message
) {
1375 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
)
1376 if (c
!= m
->system_bus
|| m
->running_as
== SYSTEMD_SYSTEM
)
1377 oom
= !dbus_connection_send(c
, message
, NULL
);
1379 SET_FOREACH(c
, m
->bus_connections
, i
)
1380 if (c
!= m
->system_bus
|| m
->running_as
== SYSTEMD_SYSTEM
)
1381 oom
= !dbus_connection_send(c
, message
, NULL
);
1383 return oom
? -ENOMEM
: 0;
1386 bool bus_has_subscriber(Manager
*m
) {
1392 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
)
1393 if (bus_connection_has_subscriber(m
, c
))
1396 SET_FOREACH(c
, m
->bus_connections
, i
)
1397 if (bus_connection_has_subscriber(m
, c
))
1403 bool bus_connection_has_subscriber(Manager
*m
, DBusConnection
*c
) {
1407 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m
, c
));
1410 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1417 /* When we are about to reexecute we add all D-Bus fds to the
1418 * set to pass over to the newly executed systemd. They won't
1419 * be used there however, except that they are closed at the
1420 * very end of deserialization, those making it possible for
1421 * clients to synchronously wait for systemd to reexec by
1422 * simply waiting for disconnection */
1424 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
) {
1427 if (dbus_connection_get_unix_fd(c
, &fd
)) {
1428 fd
= fdset_put_dup(fds
, fd
);
1435 SET_FOREACH(c
, m
->bus_connections
, i
) {
1438 if (dbus_connection_get_unix_fd(c
, &fd
)) {
1439 fd
= fdset_put_dup(fds
, fd
);
1449 void bus_broadcast_finished(
1451 usec_t firmware_usec
,
1455 usec_t userspace_usec
,
1456 usec_t total_usec
) {
1458 DBusMessage
*message
;
1462 message
= dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1468 assert_cc(sizeof(usec_t
) == sizeof(uint64_t));
1469 if (!dbus_message_append_args(message
,
1470 DBUS_TYPE_UINT64
, &firmware_usec
,
1471 DBUS_TYPE_UINT64
, &loader_usec
,
1472 DBUS_TYPE_UINT64
, &kernel_usec
,
1473 DBUS_TYPE_UINT64
, &initrd_usec
,
1474 DBUS_TYPE_UINT64
, &userspace_usec
,
1475 DBUS_TYPE_UINT64
, &total_usec
,
1476 DBUS_TYPE_INVALID
)) {
1482 if (bus_broadcast(m
, message
) < 0) {
1489 dbus_message_unref(message
);