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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
18 You should have received a copy of the GNU 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>
32 #include "dbus-unit.h"
34 #include "dbus-manager.h"
35 #include "dbus-service.h"
36 #include "dbus-socket.h"
37 #include "dbus-target.h"
38 #include "dbus-device.h"
39 #include "dbus-mount.h"
40 #include "dbus-automount.h"
41 #include "dbus-snapshot.h"
42 #include "dbus-swap.h"
43 #include "dbus-timer.h"
44 #include "dbus-path.h"
45 #include "bus-errors.h"
47 #include "dbus-common.h"
49 #define CONNECTIONS_MAX 52
51 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
52 #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
53 /* Only used as a fallback */
54 #define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
56 static const char bus_properties_interface
[] = BUS_PROPERTIES_INTERFACE
;
57 static const char bus_introspectable_interface
[] = BUS_INTROSPECTABLE_INTERFACE
;
59 const char *const bus_interface_table
[] = {
60 "org.freedesktop.DBus.Properties", bus_properties_interface
,
61 "org.freedesktop.DBus.Introspectable", bus_introspectable_interface
,
62 "org.freedesktop.systemd1.Manager", bus_manager_interface
,
63 "org.freedesktop.systemd1.Job", bus_job_interface
,
64 "org.freedesktop.systemd1.Unit", bus_unit_interface
,
65 "org.freedesktop.systemd1.Service", bus_service_interface
,
66 "org.freedesktop.systemd1.Socket", bus_socket_interface
,
67 "org.freedesktop.systemd1.Target", bus_target_interface
,
68 "org.freedesktop.systemd1.Device", bus_device_interface
,
69 "org.freedesktop.systemd1.Mount", bus_mount_interface
,
70 "org.freedesktop.systemd1.Automount", bus_automount_interface
,
71 "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface
,
72 "org.freedesktop.systemd1.Swap", bus_swap_interface
,
73 "org.freedesktop.systemd1.Timer", bus_timer_interface
,
74 "org.freedesktop.systemd1.Path", bus_path_interface
,
78 static void bus_done_api(Manager
*m
);
79 static void bus_done_system(Manager
*m
);
80 static void bus_done_private(Manager
*m
);
81 static void shutdown_connection(Manager
*m
, DBusConnection
*c
);
83 static void bus_dispatch_status(DBusConnection
*bus
, DBusDispatchStatus status
, void *data
) {
89 /* We maintain two sets, one for those connections where we
90 * requested a dispatch, and another where we didn't. And then,
91 * we move the connections between the two sets. */
93 if (status
== DBUS_DISPATCH_COMPLETE
)
94 set_move_one(m
->bus_connections
, m
->bus_connections_for_dispatch
, bus
);
96 set_move_one(m
->bus_connections_for_dispatch
, m
->bus_connections
, bus
);
99 void bus_watch_event(Manager
*m
, Watch
*w
, int events
) {
103 /* This is called by the event loop whenever there is
104 * something happening on D-Bus' file handles. */
106 if (!dbus_watch_get_enabled(w
->data
.bus_watch
))
109 dbus_watch_handle(w
->data
.bus_watch
, bus_events_to_flags(events
));
112 static dbus_bool_t
bus_add_watch(DBusWatch
*bus_watch
, void *data
) {
115 struct epoll_event ev
;
120 if (!(w
= new0(Watch
, 1)))
123 w
->fd
= dbus_watch_get_unix_fd(bus_watch
);
124 w
->type
= WATCH_DBUS_WATCH
;
125 w
->data
.bus_watch
= bus_watch
;
128 ev
.events
= bus_flags_to_events(bus_watch
);
131 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0) {
133 if (errno
!= EEXIST
) {
138 /* Hmm, bloody D-Bus creates multiple watches on the
139 * same fd. epoll() does not like that. As a dirty
140 * hack we simply dup() the fd and hence get a second
141 * one we can safely add to the epoll(). */
143 if ((w
->fd
= dup(w
->fd
)) < 0) {
148 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0) {
149 close_nointr_nofail(w
->fd
);
154 w
->fd_is_dupped
= true;
157 dbus_watch_set_data(bus_watch
, w
, NULL
);
162 static void bus_remove_watch(DBusWatch
*bus_watch
, void *data
) {
169 w
= dbus_watch_get_data(bus_watch
);
173 assert(w
->type
== WATCH_DBUS_WATCH
);
174 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_DEL
, w
->fd
, NULL
) >= 0);
177 close_nointr_nofail(w
->fd
);
182 static void bus_toggle_watch(DBusWatch
*bus_watch
, void *data
) {
185 struct epoll_event ev
;
190 w
= dbus_watch_get_data(bus_watch
);
194 assert(w
->type
== WATCH_DBUS_WATCH
);
197 ev
.events
= bus_flags_to_events(bus_watch
);
200 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_MOD
, w
->fd
, &ev
) == 0);
203 static int bus_timeout_arm(Manager
*m
, Watch
*w
) {
204 struct itimerspec its
;
211 if (dbus_timeout_get_enabled(w
->data
.bus_timeout
)) {
212 timespec_store(&its
.it_value
, dbus_timeout_get_interval(w
->data
.bus_timeout
) * USEC_PER_MSEC
);
213 its
.it_interval
= its
.it_value
;
216 if (timerfd_settime(w
->fd
, 0, &its
, NULL
) < 0)
222 void bus_timeout_event(Manager
*m
, Watch
*w
, int events
) {
226 /* This is called by the event loop whenever there is
227 * something happening on D-Bus' file handles. */
229 if (!(dbus_timeout_get_enabled(w
->data
.bus_timeout
)))
232 dbus_timeout_handle(w
->data
.bus_timeout
);
235 static dbus_bool_t
bus_add_timeout(DBusTimeout
*timeout
, void *data
) {
238 struct epoll_event ev
;
243 if (!(w
= new0(Watch
, 1)))
246 if ((w
->fd
= timerfd_create(CLOCK_MONOTONIC
, TFD_NONBLOCK
|TFD_CLOEXEC
)) < 0)
249 w
->type
= WATCH_DBUS_TIMEOUT
;
250 w
->data
.bus_timeout
= timeout
;
252 if (bus_timeout_arm(m
, w
) < 0)
259 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, w
->fd
, &ev
) < 0)
262 dbus_timeout_set_data(timeout
, w
, NULL
);
268 close_nointr_nofail(w
->fd
);
274 static void bus_remove_timeout(DBusTimeout
*timeout
, void *data
) {
281 w
= dbus_timeout_get_data(timeout
);
285 assert(w
->type
== WATCH_DBUS_TIMEOUT
);
287 assert_se(epoll_ctl(m
->epoll_fd
, EPOLL_CTL_DEL
, w
->fd
, NULL
) >= 0);
288 close_nointr_nofail(w
->fd
);
292 static void bus_toggle_timeout(DBusTimeout
*timeout
, void *data
) {
300 w
= dbus_timeout_get_data(timeout
);
304 assert(w
->type
== WATCH_DBUS_TIMEOUT
);
306 if ((r
= bus_timeout_arm(m
, w
)) < 0)
307 log_error("Failed to rearm timer: %s", strerror(-r
));
310 static DBusHandlerResult
api_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
313 DBusMessage
*reply
= NULL
;
319 dbus_error_init(&error
);
321 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
322 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
)
323 log_debug("Got D-Bus request: %s.%s() on %s",
324 dbus_message_get_interface(message
),
325 dbus_message_get_member(message
),
326 dbus_message_get_path(message
));
328 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
329 log_debug("API D-Bus connection terminated.");
332 } else if (dbus_message_is_signal(message
, DBUS_INTERFACE_DBUS
, "NameOwnerChanged")) {
333 const char *name
, *old_owner
, *new_owner
;
335 if (!dbus_message_get_args(message
, &error
,
336 DBUS_TYPE_STRING
, &name
,
337 DBUS_TYPE_STRING
, &old_owner
,
338 DBUS_TYPE_STRING
, &new_owner
,
340 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error
));
342 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m
, connection
), (char*) name
))
343 log_debug("Subscription client vanished: %s (left: %u)", name
, set_size(BUS_CONNECTION_SUBSCRIBED(m
, connection
)));
345 if (old_owner
[0] == 0)
348 if (new_owner
[0] == 0)
351 manager_dispatch_bus_name_owner_changed(m
, name
, old_owner
, new_owner
);
353 } else if (dbus_message_is_signal(message
, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
356 if (!dbus_message_get_args(message
, &error
,
357 DBUS_TYPE_STRING
, &name
,
359 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error
));
364 log_debug("Got D-Bus activation request for %s", name
);
366 if (manager_unit_pending_inactive(m
, SPECIAL_DBUS_SERVICE
) ||
367 manager_unit_pending_inactive(m
, SPECIAL_DBUS_SOCKET
)) {
369 dbus_set_error(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
371 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
373 if (r
>= 0 && u
->refuse_manual_start
)
377 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, true, &error
, NULL
);
381 const char *id
, *text
;
383 log_debug("D-Bus activation failed for %s: %s", name
, strerror(-r
));
385 if (!(reply
= dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
388 id
= error
.name
? error
.name
: bus_errno_to_dbus(r
);
389 text
= bus_error(&error
, r
);
391 if (!dbus_message_set_destination(reply
, DBUS_SERVICE_DBUS
) ||
392 !dbus_message_append_args(reply
,
393 DBUS_TYPE_STRING
, &name
,
394 DBUS_TYPE_STRING
, &id
,
395 DBUS_TYPE_STRING
, &text
,
400 /* On success we don't do anything, the service will be spawned now */
404 dbus_error_free(&error
);
407 if (!dbus_connection_send(connection
, reply
, NULL
))
410 dbus_message_unref(reply
);
413 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
417 dbus_message_unref(reply
);
419 dbus_error_free(&error
);
421 return DBUS_HANDLER_RESULT_NEED_MEMORY
;
424 static DBusHandlerResult
system_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
432 dbus_error_init(&error
);
434 if (m
->api_bus
!= m
->system_bus
&&
435 (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
436 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
))
437 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
438 dbus_message_get_interface(message
),
439 dbus_message_get_member(message
),
440 dbus_message_get_path(message
));
442 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected")) {
443 log_debug("System D-Bus connection terminated.");
446 } else if (m
->running_as
!= MANAGER_SYSTEM
&&
447 dbus_message_is_signal(message
, "org.freedesktop.systemd1.Agent", "Released")) {
451 if (!dbus_message_get_args(message
, &error
,
452 DBUS_TYPE_STRING
, &cgroup
,
454 log_error("Failed to parse Released message: %s", bus_error_message(&error
));
456 cgroup_notify_empty(m
, cgroup
);
459 dbus_error_free(&error
);
460 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
463 static DBusHandlerResult
private_bus_message_filter(DBusConnection
*connection
, DBusMessage
*message
, void *data
) {
471 dbus_error_init(&error
);
473 if (dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_METHOD_CALL
||
474 dbus_message_get_type(message
) == DBUS_MESSAGE_TYPE_SIGNAL
)
475 log_debug("Got D-Bus request: %s.%s() on %s",
476 dbus_message_get_interface(message
),
477 dbus_message_get_member(message
),
478 dbus_message_get_path(message
));
480 if (dbus_message_is_signal(message
, DBUS_INTERFACE_LOCAL
, "Disconnected"))
481 shutdown_connection(m
, connection
);
482 else if (m
->running_as
== MANAGER_SYSTEM
&&
483 dbus_message_is_signal(message
, "org.freedesktop.systemd1.Agent", "Released")) {
487 if (!dbus_message_get_args(message
, &error
,
488 DBUS_TYPE_STRING
, &cgroup
,
490 log_error("Failed to parse Released message: %s", bus_error_message(&error
));
492 cgroup_notify_empty(m
, cgroup
);
494 /* Forward the message to the system bus, so that user
495 * instances are notified as well */
498 dbus_connection_send(m
->system_bus
, message
, NULL
);
501 dbus_error_free(&error
);
503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED
;
506 unsigned bus_dispatch(Manager
*m
) {
511 if (m
->queued_message
) {
512 /* If we cannot get rid of this message we won't
513 * dispatch any D-Bus messages, so that we won't end
514 * up wanting to queue another message. */
516 if (m
->queued_message_connection
)
517 if (!dbus_connection_send(m
->queued_message_connection
, m
->queued_message
, NULL
))
520 dbus_message_unref(m
->queued_message
);
521 m
->queued_message
= NULL
;
522 m
->queued_message_connection
= NULL
;
525 if ((c
= set_first(m
->bus_connections_for_dispatch
))) {
526 if (dbus_connection_dispatch(c
) == DBUS_DISPATCH_COMPLETE
)
527 set_move_one(m
->bus_connections
, m
->bus_connections_for_dispatch
, c
);
535 static void request_name_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
539 dbus_error_init(&error
);
541 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
543 switch (dbus_message_get_type(reply
)) {
545 case DBUS_MESSAGE_TYPE_ERROR
:
547 assert_se(dbus_set_error_from_message(&error
, reply
));
548 log_warning("RequestName() failed: %s", bus_error_message(&error
));
551 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
554 if (!dbus_message_get_args(reply
,
556 DBUS_TYPE_UINT32
, &r
,
557 DBUS_TYPE_INVALID
)) {
558 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error
));
563 log_debug("Successfully acquired name.");
565 log_error("Name already owned.");
571 assert_not_reached("Invalid reply message");
574 dbus_message_unref(reply
);
575 dbus_error_free(&error
);
578 static int request_name(Manager
*m
) {
579 const char *name
= "org.freedesktop.systemd1";
580 /* Allow replacing of our name, to ease implementation of
581 * reexecution, where we keep the old connection open until
582 * after the new connection is set up and the name installed
583 * to allow clients to synchronously wait for reexecution to
585 uint32_t flags
= DBUS_NAME_FLAG_ALLOW_REPLACEMENT
|DBUS_NAME_FLAG_REPLACE_EXISTING
;
586 DBusMessage
*message
= NULL
;
587 DBusPendingCall
*pending
= NULL
;
589 if (!(message
= dbus_message_new_method_call(
596 if (!dbus_message_append_args(
598 DBUS_TYPE_STRING
, &name
,
599 DBUS_TYPE_UINT32
, &flags
,
603 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
606 if (!dbus_pending_call_set_notify(pending
, request_name_pending_cb
, m
, NULL
))
609 dbus_message_unref(message
);
610 dbus_pending_call_unref(pending
);
612 /* We simple ask for the name and don't wait for it. Sooner or
613 * later we'll have it. */
619 dbus_pending_call_cancel(pending
);
620 dbus_pending_call_unref(pending
);
624 dbus_message_unref(message
);
629 static void query_name_list_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
632 Manager
*m
= userdata
;
636 dbus_error_init(&error
);
638 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
640 switch (dbus_message_get_type(reply
)) {
642 case DBUS_MESSAGE_TYPE_ERROR
:
644 assert_se(dbus_set_error_from_message(&error
, reply
));
645 log_warning("ListNames() failed: %s", bus_error_message(&error
));
648 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
652 if ((r
= bus_parse_strv(reply
, &l
)) < 0)
653 log_warning("Failed to parse ListNames() reply: %s", strerror(-r
));
658 /* This is a bit hacky, we say the
659 * owner of the name is the name
660 * itself, because we don't want the
661 * extra traffic to figure out the
663 manager_dispatch_bus_name_owner_changed(m
, *t
, NULL
, *t
);
672 assert_not_reached("Invalid reply message");
675 dbus_message_unref(reply
);
676 dbus_error_free(&error
);
679 static int query_name_list(Manager
*m
) {
680 DBusMessage
*message
= NULL
;
681 DBusPendingCall
*pending
= NULL
;
683 /* Asks for the currently installed bus names */
685 if (!(message
= dbus_message_new_method_call(
692 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
695 if (!dbus_pending_call_set_notify(pending
, query_name_list_pending_cb
, m
, NULL
))
698 dbus_message_unref(message
);
699 dbus_pending_call_unref(pending
);
701 /* We simple ask for the list and don't wait for it. Sooner or
702 * later we'll get it. */
708 dbus_pending_call_cancel(pending
);
709 dbus_pending_call_unref(pending
);
713 dbus_message_unref(message
);
718 static int bus_setup_loop(Manager
*m
, DBusConnection
*bus
) {
722 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
724 if (!dbus_connection_set_watch_functions(bus
, bus_add_watch
, bus_remove_watch
, bus_toggle_watch
, m
, NULL
) ||
725 !dbus_connection_set_timeout_functions(bus
, bus_add_timeout
, bus_remove_timeout
, bus_toggle_timeout
, m
, NULL
)) {
726 log_error("Not enough memory");
730 if (set_put(m
->bus_connections_for_dispatch
, bus
) < 0) {
731 log_error("Not enough memory");
735 dbus_connection_set_dispatch_status_function(bus
, bus_dispatch_status
, m
, NULL
);
739 static dbus_bool_t
allow_only_same_user(DBusConnection
*connection
, unsigned long uid
, void *data
) {
740 return uid
== 0 || uid
== geteuid();
743 static void bus_new_connection(
745 DBusConnection
*new_connection
,
752 if (set_size(m
->bus_connections
) >= CONNECTIONS_MAX
) {
753 log_error("Too many concurrent connections.");
757 dbus_connection_set_unix_user_function(new_connection
, allow_only_same_user
, NULL
, NULL
);
759 if (bus_setup_loop(m
, new_connection
) < 0)
762 if (!dbus_connection_register_object_path(new_connection
, "/org/freedesktop/systemd1", &bus_manager_vtable
, m
) ||
763 !dbus_connection_register_fallback(new_connection
, "/org/freedesktop/systemd1/unit", &bus_unit_vtable
, m
) ||
764 !dbus_connection_register_fallback(new_connection
, "/org/freedesktop/systemd1/job", &bus_job_vtable
, m
) ||
765 !dbus_connection_add_filter(new_connection
, private_bus_message_filter
, m
, NULL
)) {
766 log_error("Not enough memory.");
770 log_debug("Accepted connection on private bus.");
772 dbus_connection_ref(new_connection
);
775 static int init_registered_system_bus(Manager
*m
) {
778 if (!dbus_connection_add_filter(m
->system_bus
, system_bus_message_filter
, m
, NULL
)) {
779 log_error("Not enough memory");
783 if (m
->running_as
!= MANAGER_SYSTEM
) {
786 dbus_error_init(&error
);
788 dbus_bus_add_match(m
->system_bus
,
790 "interface='org.freedesktop.systemd1.Agent',"
792 "path='/org/freedesktop/systemd1/agent'",
795 if (dbus_error_is_set(&error
)) {
796 log_error("Failed to register match: %s", bus_error_message(&error
));
797 dbus_error_free(&error
);
802 log_debug("Successfully connected to system D-Bus bus %s as %s",
803 strnull((id
= dbus_connection_get_server_id(m
->system_bus
))),
804 strnull(dbus_bus_get_unique_name(m
->system_bus
)));
810 static int init_registered_api_bus(Manager
*m
) {
813 if (!dbus_connection_register_object_path(m
->api_bus
, "/org/freedesktop/systemd1", &bus_manager_vtable
, m
) ||
814 !dbus_connection_register_fallback(m
->api_bus
, "/org/freedesktop/systemd1/unit", &bus_unit_vtable
, m
) ||
815 !dbus_connection_register_fallback(m
->api_bus
, "/org/freedesktop/systemd1/job", &bus_job_vtable
, m
) ||
816 !dbus_connection_add_filter(m
->api_bus
, api_bus_message_filter
, m
, NULL
)) {
817 log_error("Not enough memory");
821 /* Get NameOwnerChange messages */
822 dbus_bus_add_match(m
->api_bus
,
824 "sender='"DBUS_SERVICE_DBUS
"',"
825 "interface='"DBUS_INTERFACE_DBUS
"',"
826 "member='NameOwnerChanged',"
827 "path='"DBUS_PATH_DBUS
"'",
830 /* Get activation requests */
831 dbus_bus_add_match(m
->api_bus
,
833 "sender='"DBUS_SERVICE_DBUS
"',"
834 "interface='org.freedesktop.systemd1.Activator',"
835 "member='ActivationRequest',"
836 "path='"DBUS_PATH_DBUS
"'",
843 r
= query_name_list(m
);
847 if (m
->running_as
== MANAGER_USER
) {
849 log_debug("Successfully connected to API D-Bus bus %s as %s",
850 strnull((id
= dbus_connection_get_server_id(m
->api_bus
))),
851 strnull(dbus_bus_get_unique_name(m
->api_bus
)));
854 log_debug("Successfully initialized API on the system bus");
859 static void bus_register_cb(DBusPendingCall
*pending
, void *userdata
) {
860 Manager
*m
= userdata
;
861 DBusConnection
**conn
;
867 dbus_error_init(&error
);
869 conn
= dbus_pending_call_get_data(pending
, m
->conn_data_slot
);
870 assert(conn
== &m
->system_bus
|| conn
== &m
->api_bus
);
872 reply
= dbus_pending_call_steal_reply(pending
);
874 switch (dbus_message_get_type(reply
)) {
875 case DBUS_MESSAGE_TYPE_ERROR
:
876 assert_se(dbus_set_error_from_message(&error
, reply
));
877 log_warning("Failed to register to bus: %s", bus_error_message(&error
));
880 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
881 if (!dbus_message_get_args(reply
, &error
,
882 DBUS_TYPE_STRING
, &name
,
883 DBUS_TYPE_INVALID
)) {
884 log_error("Failed to parse Hello reply: %s", bus_error_message(&error
));
889 log_debug("Received name %s in reply to Hello", name
);
890 if (!dbus_bus_set_unique_name(*conn
, name
)) {
891 log_error("Failed to set unique name");
896 if (conn
== &m
->system_bus
) {
897 r
= init_registered_system_bus(m
);
898 if (r
== 0 && m
->running_as
== MANAGER_SYSTEM
)
899 r
= init_registered_api_bus(m
);
901 r
= init_registered_api_bus(m
);
905 assert_not_reached("Invalid reply message");
908 dbus_message_unref(reply
);
909 dbus_error_free(&error
);
912 if (conn
== &m
->system_bus
) {
913 log_debug("Failed setting up the system bus");
916 log_debug("Failed setting up the API bus");
922 static int manager_bus_async_register(Manager
*m
, DBusConnection
**conn
) {
923 DBusMessage
*message
= NULL
;
924 DBusPendingCall
*pending
= NULL
;
926 message
= dbus_message_new_method_call(DBUS_SERVICE_DBUS
,
933 if (!dbus_connection_send_with_reply(*conn
, message
, &pending
, -1))
936 if (!dbus_pending_call_set_data(pending
, m
->conn_data_slot
, conn
, NULL
))
939 if (!dbus_pending_call_set_notify(pending
, bus_register_cb
, m
, NULL
))
942 dbus_message_unref(message
);
943 dbus_pending_call_unref(pending
);
948 dbus_pending_call_cancel(pending
);
949 dbus_pending_call_unref(pending
);
953 dbus_message_unref(message
);
958 static DBusConnection
* manager_bus_connect_private(Manager
*m
, DBusBusType type
) {
960 DBusConnection
*connection
;
964 case DBUS_BUS_SYSTEM
:
965 address
= getenv("DBUS_SYSTEM_BUS_ADDRESS");
966 if (!address
|| !address
[0])
967 address
= DBUS_SYSTEM_BUS_DEFAULT_ADDRESS
;
969 case DBUS_BUS_SESSION
:
970 address
= getenv("DBUS_SESSION_BUS_ADDRESS");
971 if (!address
|| !address
[0])
972 address
= DBUS_SESSION_BUS_DEFAULT_ADDRESS
;
975 assert_not_reached("Invalid bus type");
978 dbus_error_init(&error
);
980 connection
= dbus_connection_open_private(address
, &error
);
982 log_warning("Failed to open private bus connection: %s", bus_error_message(&error
));
989 dbus_connection_close(connection
);
990 dbus_error_free(&error
);
994 static int bus_init_system(Manager
*m
) {
1000 m
->system_bus
= manager_bus_connect_private(m
, DBUS_BUS_SYSTEM
);
1001 if (!m
->system_bus
) {
1002 log_debug("Failed to connect to system D-Bus, retrying later");
1007 r
= bus_setup_loop(m
, m
->system_bus
);
1011 r
= manager_bus_async_register(m
, &m
->system_bus
);
1022 static int bus_init_api(Manager
*m
) {
1028 if (m
->running_as
== MANAGER_SYSTEM
) {
1029 m
->api_bus
= m
->system_bus
;
1030 /* In this mode there is no distinct connection to the API bus,
1031 * the API is published on the system bus.
1032 * bus_register_cb() is aware of that and will init the API
1033 * when the system bus gets registered.
1034 * No need to setup anything here. */
1038 m
->api_bus
= manager_bus_connect_private(m
, DBUS_BUS_SESSION
);
1040 log_debug("Failed to connect to API D-Bus, retrying later");
1045 r
= bus_setup_loop(m
, m
->api_bus
);
1049 r
= manager_bus_async_register(m
, &m
->api_bus
);
1060 static int bus_init_private(Manager
*m
) {
1063 const char *const external_only
[] = {
1070 dbus_error_init(&error
);
1075 if (m
->running_as
== MANAGER_SYSTEM
) {
1077 /* We want the private bus only when running as init */
1081 unlink("/run/systemd/private");
1082 m
->private_bus
= dbus_server_listen("unix:path=/run/systemd/private", &error
);
1087 e
= getenv("XDG_RUNTIME_DIR");
1091 if (asprintf(&p
, "unix:path=%s/systemd/private", e
) < 0) {
1092 log_error("Not enough memory");
1097 mkdir_parents(p
+10, 0755);
1099 m
->private_bus
= dbus_server_listen(p
, &error
);
1103 if (!m
->private_bus
) {
1104 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error
));
1109 if (!dbus_server_set_auth_mechanisms(m
->private_bus
, (const char**) external_only
) ||
1110 !dbus_server_set_watch_functions(m
->private_bus
, bus_add_watch
, bus_remove_watch
, bus_toggle_watch
, m
, NULL
) ||
1111 !dbus_server_set_timeout_functions(m
->private_bus
, bus_add_timeout
, bus_remove_timeout
, bus_toggle_timeout
, m
, NULL
)) {
1112 log_error("Not enough memory");
1117 dbus_server_set_new_connection_function(m
->private_bus
, bus_new_connection
, m
, NULL
);
1119 log_debug("Successfully created private D-Bus server.");
1124 bus_done_private(m
);
1125 dbus_error_free(&error
);
1130 int bus_init(Manager
*m
, bool try_bus_connect
) {
1133 if (set_ensure_allocated(&m
->bus_connections
, trivial_hash_func
, trivial_compare_func
) < 0 ||
1134 set_ensure_allocated(&m
->bus_connections_for_dispatch
, trivial_hash_func
, trivial_compare_func
) < 0)
1137 if (m
->name_data_slot
< 0)
1138 if (!dbus_pending_call_allocate_data_slot(&m
->name_data_slot
))
1141 if (m
->conn_data_slot
< 0)
1142 if (!dbus_pending_call_allocate_data_slot(&m
->conn_data_slot
))
1145 if (m
->subscribed_data_slot
< 0)
1146 if (!dbus_connection_allocate_data_slot(&m
->subscribed_data_slot
))
1149 if (try_bus_connect
) {
1150 if ((r
= bus_init_system(m
)) < 0 ||
1151 (r
= bus_init_api(m
)) < 0)
1155 if ((r
= bus_init_private(m
)) < 0)
1160 log_error("Not enough memory");
1164 static void shutdown_connection(Manager
*m
, DBusConnection
*c
) {
1169 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1171 free(j
->bus_client
);
1172 j
->bus_client
= NULL
;
1177 set_remove(m
->bus_connections
, c
);
1178 set_remove(m
->bus_connections_for_dispatch
, c
);
1180 if ((s
= BUS_CONNECTION_SUBSCRIBED(m
, c
))) {
1183 while ((t
= set_steal_first(s
)))
1189 if (m
->queued_message_connection
== c
) {
1190 m
->queued_message_connection
= NULL
;
1192 if (m
->queued_message
) {
1193 dbus_message_unref(m
->queued_message
);
1194 m
->queued_message
= NULL
;
1198 dbus_connection_set_dispatch_status_function(c
, NULL
, NULL
, NULL
);
1199 /* system manager cannot afford to block on DBus */
1200 if (m
->running_as
!= MANAGER_SYSTEM
)
1201 dbus_connection_flush(c
);
1202 dbus_connection_close(c
);
1203 dbus_connection_unref(c
);
1206 static void bus_done_api(Manager
*m
) {
1210 if (m
->running_as
== MANAGER_USER
)
1211 shutdown_connection(m
, m
->api_bus
);
1215 if (m
->queued_message
) {
1216 dbus_message_unref(m
->queued_message
);
1217 m
->queued_message
= NULL
;
1221 static void bus_done_system(Manager
*m
) {
1225 if (m
->running_as
== MANAGER_SYSTEM
)
1228 shutdown_connection(m
, m
->system_bus
);
1229 m
->system_bus
= NULL
;
1232 static void bus_done_private(Manager
*m
) {
1233 if (!m
->private_bus
)
1236 dbus_server_disconnect(m
->private_bus
);
1237 dbus_server_unref(m
->private_bus
);
1238 m
->private_bus
= NULL
;
1241 void bus_done(Manager
*m
) {
1246 bus_done_private(m
);
1248 while ((c
= set_steal_first(m
->bus_connections
)))
1249 shutdown_connection(m
, c
);
1251 while ((c
= set_steal_first(m
->bus_connections_for_dispatch
)))
1252 shutdown_connection(m
, c
);
1254 set_free(m
->bus_connections
);
1255 set_free(m
->bus_connections_for_dispatch
);
1257 if (m
->name_data_slot
>= 0)
1258 dbus_pending_call_free_data_slot(&m
->name_data_slot
);
1260 if (m
->conn_data_slot
>= 0)
1261 dbus_pending_call_free_data_slot(&m
->conn_data_slot
);
1263 if (m
->subscribed_data_slot
>= 0)
1264 dbus_connection_free_data_slot(&m
->subscribed_data_slot
);
1267 static void query_pid_pending_cb(DBusPendingCall
*pending
, void *userdata
) {
1268 Manager
*m
= userdata
;
1273 dbus_error_init(&error
);
1275 assert_se(name
= BUS_PENDING_CALL_NAME(m
, pending
));
1276 assert_se(reply
= dbus_pending_call_steal_reply(pending
));
1278 switch (dbus_message_get_type(reply
)) {
1280 case DBUS_MESSAGE_TYPE_ERROR
:
1282 assert_se(dbus_set_error_from_message(&error
, reply
));
1283 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error
));
1286 case DBUS_MESSAGE_TYPE_METHOD_RETURN
: {
1289 if (!dbus_message_get_args(reply
,
1291 DBUS_TYPE_UINT32
, &r
,
1292 DBUS_TYPE_INVALID
)) {
1293 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error
));
1297 manager_dispatch_bus_query_pid_done(m
, name
, (pid_t
) r
);
1302 assert_not_reached("Invalid reply message");
1305 dbus_message_unref(reply
);
1306 dbus_error_free(&error
);
1309 int bus_query_pid(Manager
*m
, const char *name
) {
1310 DBusMessage
*message
= NULL
;
1311 DBusPendingCall
*pending
= NULL
;
1317 if (!(message
= dbus_message_new_method_call(
1320 DBUS_INTERFACE_DBUS
,
1321 "GetConnectionUnixProcessID")))
1324 if (!(dbus_message_append_args(
1326 DBUS_TYPE_STRING
, &name
,
1327 DBUS_TYPE_INVALID
)))
1330 if (!dbus_connection_send_with_reply(m
->api_bus
, message
, &pending
, -1))
1333 if (!(n
= strdup(name
)))
1336 if (!dbus_pending_call_set_data(pending
, m
->name_data_slot
, n
, free
))
1341 if (!dbus_pending_call_set_notify(pending
, query_pid_pending_cb
, m
, NULL
))
1344 dbus_message_unref(message
);
1345 dbus_pending_call_unref(pending
);
1353 dbus_pending_call_cancel(pending
);
1354 dbus_pending_call_unref(pending
);
1358 dbus_message_unref(message
);
1363 int bus_broadcast(Manager
*m
, DBusMessage
*message
) {
1371 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
)
1372 if (c
!= m
->system_bus
|| m
->running_as
== MANAGER_SYSTEM
)
1373 oom
= !dbus_connection_send(c
, message
, NULL
);
1375 SET_FOREACH(c
, m
->bus_connections
, i
)
1376 if (c
!= m
->system_bus
|| m
->running_as
== MANAGER_SYSTEM
)
1377 oom
= !dbus_connection_send(c
, message
, NULL
);
1379 return oom
? -ENOMEM
: 0;
1382 bool bus_has_subscriber(Manager
*m
) {
1388 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
)
1389 if (bus_connection_has_subscriber(m
, c
))
1392 SET_FOREACH(c
, m
->bus_connections
, i
)
1393 if (bus_connection_has_subscriber(m
, c
))
1399 bool bus_connection_has_subscriber(Manager
*m
, DBusConnection
*c
) {
1403 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m
, c
));
1406 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1413 /* When we are about to reexecute we add all D-Bus fds to the
1414 * set to pass over to the newly executed systemd. They won't
1415 * be used there however, except that they are closed at the
1416 * very end of deserialization, those making it possible for
1417 * clients to synchronously wait for systemd to reexec by
1418 * simply waiting for disconnection */
1420 SET_FOREACH(c
, m
->bus_connections_for_dispatch
, i
) {
1423 if (dbus_connection_get_unix_fd(c
, &fd
)) {
1424 fd
= fdset_put_dup(fds
, fd
);
1431 SET_FOREACH(c
, m
->bus_connections
, i
) {
1434 if (dbus_connection_get_unix_fd(c
, &fd
)) {
1435 fd
= fdset_put_dup(fds
, fd
);
1445 void bus_broadcast_finished(
1449 usec_t userspace_usec
,
1450 usec_t total_usec
) {
1452 DBusMessage
*message
;
1456 message
= dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1458 log_error("Out of memory.");
1462 assert_cc(sizeof(usec_t
) == sizeof(uint64_t));
1463 if (!dbus_message_append_args(message
,
1464 DBUS_TYPE_UINT64
, &kernel_usec
,
1465 DBUS_TYPE_UINT64
, &initrd_usec
,
1466 DBUS_TYPE_UINT64
, &userspace_usec
,
1467 DBUS_TYPE_UINT64
, &total_usec
,
1468 DBUS_TYPE_INVALID
)) {
1469 log_error("Out of memory.");
1474 if (bus_broadcast(m
, message
) < 0) {
1475 log_error("Out of memory.");
1481 dbus_message_unref(message
);