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