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/>.
23 #include <sys/epoll.h>
28 #include "bus-common-errors.h"
29 #include "bus-error.h"
30 #include "bus-internal.h"
32 #include "dbus-cgroup.h"
33 #include "dbus-execute.h"
35 #include "dbus-kill.h"
36 #include "dbus-manager.h"
37 #include "dbus-unit.h"
41 #include "selinux-access.h"
43 #include "string-util.h"
48 #define CONNECTIONS_MAX 4096
50 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
52 int bus_send_queued_message(Manager
*m
) {
57 if (!m
->queued_message
)
60 /* If we cannot get rid of this message we won't dispatch any
61 * D-Bus messages, so that we won't end up wanting to queue
64 r
= sd_bus_send(NULL
, m
->queued_message
, NULL
);
66 log_warning_errno(r
, "Failed to send queued message: %m");
68 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
73 static int signal_agent_released(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
74 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
75 const char *cgroup
, *me
;
76 Manager
*m
= userdata
;
84 /* ignore recursive events sent by us on the system/user bus */
85 bus
= sd_bus_message_get_bus(message
);
86 if (!sd_bus_is_server(bus
)) {
87 r
= sd_bus_get_unique_name(bus
, &me
);
91 if (streq_ptr(sd_bus_message_get_sender(message
), me
))
95 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
96 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
100 r
= sd_bus_creds_get_euid(creds
, &sender_uid
);
101 if (r
< 0 || sender_uid
!= 0)
104 /* parse 'cgroup-empty' notification */
105 r
= sd_bus_message_read(message
, "s", &cgroup
);
107 bus_log_parse_error(r
);
111 manager_notify_cgroup_empty(m
, cgroup
);
113 /* if running as system-instance, forward under our name */
114 if (m
->running_as
== MANAGER_SYSTEM
&& m
->system_bus
) {
115 r
= sd_bus_message_rewind(message
, 1);
117 r
= sd_bus_send(m
->system_bus
, message
, NULL
);
119 log_warning_errno(r
, "Failed to forward Released message: %m");
125 static int signal_disconnected(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
126 Manager
*m
= userdata
;
131 assert_se(bus
= sd_bus_message_get_bus(message
));
133 if (bus
== m
->api_bus
)
134 destroy_bus(m
, &m
->api_bus
);
135 if (bus
== m
->system_bus
)
136 destroy_bus(m
, &m
->system_bus
);
137 if (set_remove(m
->private_buses
, bus
)) {
138 log_debug("Got disconnect on private connection.");
139 destroy_bus(m
, &bus
);
145 static int signal_activation_request(sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
146 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
147 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
148 Manager
*m
= userdata
;
156 r
= sd_bus_message_read(message
, "s", &name
);
158 bus_log_parse_error(r
);
162 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
163 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
164 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
168 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
172 if (u
->refuse_manual_start
) {
173 r
= sd_bus_error_setf(&error
, BUS_ERROR_ONLY_BY_DEPENDENCY
, "Operation refused, %s may be requested by dependency only.", u
->id
);
177 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, true, &error
, NULL
);
181 /* Successfully queued, that's it for us */
185 if (!sd_bus_error_is_set(&error
))
186 sd_bus_error_set_errno(&error
, r
);
188 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
190 r
= sd_bus_message_new_signal(sd_bus_message_get_bus(message
), &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
192 bus_log_create_error(r
);
196 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
198 bus_log_create_error(r
);
202 r
= sd_bus_send_to(NULL
, reply
, "org.freedesktop.DBus", NULL
);
204 return log_error_errno(r
, "Failed to respond with to bus activation request: %m");
210 static int mac_selinux_filter(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
211 Manager
*m
= userdata
;
212 const char *verb
, *path
;
219 /* Our own method calls are all protected individually with
220 * selinux checks, but the built-in interfaces need to be
223 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
225 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
226 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
227 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
228 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
233 path
= sd_bus_message_get_path(message
);
235 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
237 r
= mac_selinux_access_check(message
, verb
, error
);
244 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
245 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
248 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
252 r
= sd_bus_creds_get_pid(creds
, &pid
);
256 u
= manager_get_unit_by_pid(m
, pid
);
258 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
262 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
268 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
276 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
277 Manager
*m
= userdata
;
287 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
295 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
303 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
304 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
305 sd_bus_message
*message
;
308 message
= sd_bus_get_current_message(bus
);
312 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
316 r
= sd_bus_creds_get_pid(creds
, &pid
);
320 u
= manager_get_unit_by_pid(m
, pid
);
322 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
334 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
335 Manager
*m
= userdata
;
343 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
346 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
347 Manager
*m
= userdata
;
357 r
= find_unit(m
, bus
, path
, &u
, error
);
361 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
368 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
369 Manager
*m
= userdata
;
379 r
= find_unit(m
, bus
, path
, &u
, error
);
383 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
386 if (!UNIT_HAS_CGROUP_CONTEXT(u
))
393 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
394 Manager
*m
= userdata
;
405 r
= find_unit(m
, bus
, path
, &u
, error
);
409 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
412 c
= unit_get_cgroup_context(u
);
420 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
421 Manager
*m
= userdata
;
432 r
= find_unit(m
, bus
, path
, &u
, error
);
436 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
439 c
= unit_get_exec_context(u
);
447 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
448 Manager
*m
= userdata
;
459 r
= find_unit(m
, bus
, path
, &u
, error
);
463 if (!streq_ptr(interface
, unit_dbus_interface_from_type(u
->type
)))
466 c
= unit_get_kill_context(u
);
474 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
475 _cleanup_free_
char **l
= NULL
;
476 Manager
*m
= userdata
;
481 l
= new0(char*, hashmap_size(m
->jobs
)+1);
485 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
486 l
[k
] = job_dbus_path(j
);
493 assert(hashmap_size(m
->jobs
) == k
);
501 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
502 _cleanup_free_
char **l
= NULL
;
503 Manager
*m
= userdata
;
508 l
= new0(char*, hashmap_size(m
->units
)+1);
512 HASHMAP_FOREACH(u
, m
->units
, i
) {
513 l
[k
] = unit_dbus_path(u
);
526 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
534 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
536 return log_error_errno(r
, "Failed to add SELinux access filter: %m");
539 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
541 return log_error_errno(r
, "Failed to register Manager vtable: %m");
543 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
545 return log_error_errno(r
, "Failed to register Job vtable: %m");
547 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
549 return log_error_errno(r
, "Failed to add job enumerator: %m");
551 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
553 return log_error_errno(r
, "Failed to register Unit vtable: %m");
555 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
557 return log_error_errno(r
, "Failed to add job enumerator: %m");
559 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
560 const char *interface
;
562 assert_se(interface
= unit_dbus_interface_from_type(t
));
564 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
566 return log_error_errno(r
, "Failed to register type specific vtable for %s: %m", interface
);
568 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
569 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
571 return log_error_errno(r
, "Failed to register control group unit vtable for %s: %m", interface
);
573 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
575 return log_error_errno(r
, "Failed to register control group vtable for %s: %m", interface
);
578 if (unit_vtable
[t
]->exec_context_offset
> 0) {
579 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
581 return log_error_errno(r
, "Failed to register execute vtable for %s: %m", interface
);
584 if (unit_vtable
[t
]->kill_context_offset
> 0) {
585 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
587 return log_error_errno(r
, "Failed to register kill vtable for %s: %m", interface
);
594 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
600 r
= sd_bus_add_match(
603 "sender='org.freedesktop.DBus.Local',"
605 "path='/org/freedesktop/DBus/Local',"
606 "interface='org.freedesktop.DBus.Local',"
607 "member='Disconnected'",
608 signal_disconnected
, m
);
611 return log_error_errno(r
, "Failed to register match for Disconnected message: %m");
616 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
617 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
618 _cleanup_close_
int nfd
= -1;
619 Manager
*m
= userdata
;
626 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
628 log_warning_errno(errno
, "Failed to accept private connection, ignoring: %m");
632 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
633 log_warning("Too many concurrent connections, refusing");
637 r
= set_ensure_allocated(&m
->private_buses
, NULL
);
643 r
= sd_bus_new(&bus
);
645 log_warning_errno(r
, "Failed to allocate new private connection bus: %m");
649 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
651 log_warning_errno(r
, "Failed to set fd on new connection bus: %m");
657 r
= bus_check_peercred(bus
);
659 log_warning_errno(r
, "Incoming private connection from unprivileged client, refusing: %m");
663 assert_se(sd_id128_randomize(&id
) >= 0);
665 r
= sd_bus_set_server(bus
, 1, id
);
667 log_warning_errno(r
, "Failed to enable server support for new connection bus: %m");
671 r
= sd_bus_negotiate_creds(bus
, 1,
672 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
673 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
674 SD_BUS_CREDS_SELINUX_CONTEXT
);
676 log_warning_errno(r
, "Failed to enable credentials for new connection: %m");
680 r
= sd_bus_start(bus
);
682 log_warning_errno(r
, "Failed to start new connection bus: %m");
686 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
688 log_warning_errno(r
, "Failed to attach new connection bus to event loop: %m");
692 if (m
->running_as
== MANAGER_SYSTEM
) {
693 /* When we run as system instance we get the Released
694 * signal via a direct connection */
696 r
= sd_bus_add_match(
700 "interface='org.freedesktop.systemd1.Agent',"
702 "path='/org/freedesktop/systemd1/agent'",
703 signal_agent_released
, m
);
706 log_warning_errno(r
, "Failed to register Released match on new connection bus: %m");
711 r
= bus_setup_disconnected_match(m
, bus
);
715 r
= bus_setup_api_vtables(m
, bus
);
717 log_warning_errno(r
, "Failed to set up API vtables on new connection bus: %m");
721 r
= set_put(m
->private_buses
, bus
);
723 log_warning_errno(r
, "Failed to add new connection bus to set: %m");
729 log_debug("Accepted new private connection.");
734 static int bus_list_names(Manager
*m
, sd_bus
*bus
) {
735 _cleanup_strv_free_
char **names
= NULL
;
742 r
= sd_bus_list_names(bus
, &names
, NULL
);
744 return log_error_errno(r
, "Failed to get initial list of names: %m");
746 /* This is a bit hacky, we say the owner of the name is the
747 * name itself, because we don't want the extra traffic to
748 * figure out the real owner. */
749 STRV_FOREACH(i
, names
) {
752 u
= hashmap_get(m
->watch_bus
, *i
);
754 UNIT_VTABLE(u
)->bus_name_owner_change(u
, *i
, NULL
, *i
);
760 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
769 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
770 r
= sd_bus_negotiate_creds(bus
, 1,
771 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
772 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
773 SD_BUS_CREDS_SELINUX_CONTEXT
);
775 log_warning_errno(r
, "Failed to enable credential passing, ignoring: %m");
777 r
= bus_setup_api_vtables(m
, bus
);
781 HASHMAP_FOREACH_KEY(u
, name
, m
->watch_bus
, i
) {
782 r
= unit_install_bus_match(u
, bus
, name
);
784 log_error_errno(r
, "Failed to subscribe to NameOwnerChanged signal: %m");
787 r
= sd_bus_add_match(
791 "sender='org.freedesktop.DBus',"
792 "path='/org/freedesktop/DBus',"
793 "interface='org.freedesktop.systemd1.Activator',"
794 "member='ActivationRequest'",
795 signal_activation_request
, m
);
797 log_warning_errno(r
, "Failed to subscribe to activation signal: %m");
799 /* Allow replacing of our name, to ease implementation of
800 * reexecution, where we keep the old connection open until
801 * after the new connection is set up and the name installed
802 * to allow clients to synchronously wait for reexecution to
804 r
= sd_bus_request_name(bus
,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
);
806 return log_error_errno(r
, "Failed to register name: %m");
808 bus_list_names(m
, bus
);
810 log_debug("Successfully connected to API bus.");
814 static int bus_init_api(Manager
*m
) {
815 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
821 /* The API and system bus is the same if we are running in system mode */
822 if (m
->running_as
== MANAGER_SYSTEM
&& m
->system_bus
)
823 bus
= sd_bus_ref(m
->system_bus
);
825 if (m
->running_as
== MANAGER_SYSTEM
)
826 r
= sd_bus_open_system(&bus
);
828 r
= sd_bus_open_user(&bus
);
831 log_debug("Failed to connect to API bus, retrying later...");
835 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
837 log_error_errno(r
, "Failed to attach API bus to event loop: %m");
841 r
= bus_setup_disconnected_match(m
, bus
);
846 r
= bus_setup_api(m
, bus
);
848 log_error_errno(r
, "Failed to set up API bus: %m");
858 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
864 /* On kdbus or if we are a user instance we get the Released message via the system bus */
865 if (m
->running_as
== MANAGER_USER
|| m
->kdbus_fd
>= 0) {
866 r
= sd_bus_add_match(
870 "interface='org.freedesktop.systemd1.Agent',"
872 "path='/org/freedesktop/systemd1/agent'",
873 signal_agent_released
, m
);
875 log_warning_errno(r
, "Failed to register Released match on system bus: %m");
878 log_debug("Successfully connected to system bus.");
882 static int bus_init_system(Manager
*m
) {
883 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
889 /* The API and system bus is the same if we are running in system mode */
890 if (m
->running_as
== MANAGER_SYSTEM
&& m
->api_bus
) {
891 m
->system_bus
= sd_bus_ref(m
->api_bus
);
895 r
= sd_bus_open_system(&bus
);
897 log_debug("Failed to connect to system bus, retrying later...");
901 r
= bus_setup_disconnected_match(m
, bus
);
905 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
907 log_error_errno(r
, "Failed to attach system bus to event loop: %m");
911 r
= bus_setup_system(m
, bus
);
913 log_error_errno(r
, "Failed to set up system bus: %m");
923 static int bus_init_private(Manager
*m
) {
924 _cleanup_close_
int fd
= -1;
925 union sockaddr_union sa
= {
926 .un
.sun_family
= AF_UNIX
934 if (m
->private_listen_fd
>= 0)
937 /* We don't need the private socket if we have kdbus */
938 if (m
->kdbus_fd
>= 0)
941 if (m
->running_as
== MANAGER_SYSTEM
) {
943 /* We want the private bus only when running as init */
947 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
948 salen
= offsetof(union sockaddr_union
, un
.sun_path
) + strlen("/run/systemd/private");
950 size_t left
= sizeof(sa
.un
.sun_path
);
951 char *p
= sa
.un
.sun_path
;
954 e
= secure_getenv("XDG_RUNTIME_DIR");
956 log_error("Failed to determine XDG_RUNTIME_DIR");
960 left
= strpcpy(&p
, left
, e
);
961 left
= strpcpy(&p
, left
, "/systemd/private");
963 salen
= sizeof(sa
.un
) - left
;
966 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
967 (void) unlink(sa
.un
.sun_path
);
969 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
971 return log_error_errno(errno
, "Failed to allocate private socket: %m");
973 r
= bind(fd
, &sa
.sa
, salen
);
975 return log_error_errno(errno
, "Failed to bind private socket: %m");
977 r
= listen(fd
, SOMAXCONN
);
979 return log_error_errno(errno
, "Failed to make private socket listening: %m");
981 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
983 return log_error_errno(r
, "Failed to allocate event source: %m");
985 (void) sd_event_source_set_description(s
, "bus-connection");
987 m
->private_listen_fd
= fd
;
988 m
->private_listen_event_source
= s
;
991 log_debug("Successfully created private D-Bus server.");
996 int bus_init(Manager
*m
, bool try_bus_connect
) {
999 if (try_bus_connect
) {
1000 r
= bus_init_system(m
);
1004 r
= bus_init_api(m
);
1009 r
= bus_init_private(m
);
1016 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1026 /* Get rid of tracked clients on this bus */
1027 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1028 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1030 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1031 if (j
->clients
&& sd_bus_track_get_bus(j
->clients
) == *bus
)
1032 j
->clients
= sd_bus_track_unref(j
->clients
);
1034 /* Get rid of queued message on this bus */
1035 if (m
->queued_message
&& sd_bus_message_get_bus(m
->queued_message
) == *bus
)
1036 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1038 /* Possibly flush unwritten data, but only if we are
1039 * unprivileged, since we don't want to sync here */
1040 if (m
->running_as
!= MANAGER_SYSTEM
)
1043 /* And destroy the object */
1045 *bus
= sd_bus_unref(*bus
);
1048 void bus_done(Manager
*m
) {
1054 destroy_bus(m
, &m
->api_bus
);
1056 destroy_bus(m
, &m
->system_bus
);
1057 while ((b
= set_steal_first(m
->private_buses
)))
1060 m
->private_buses
= set_free(m
->private_buses
);
1062 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1063 m
->deserialized_subscribed
= strv_free(m
->deserialized_subscribed
);
1065 if (m
->private_listen_event_source
)
1066 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1068 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1070 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1073 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1081 /* When we are about to reexecute we add all D-Bus fds to the
1082 * set to pass over to the newly executed systemd. They won't
1083 * be used there however, except thatt they are closed at the
1084 * very end of deserialization, those making it possible for
1085 * clients to synchronously wait for systemd to reexec by
1086 * simply waiting for disconnection */
1089 fd
= sd_bus_get_fd(m
->api_bus
);
1091 fd
= fdset_put_dup(fds
, fd
);
1097 SET_FOREACH(b
, m
->private_buses
, i
) {
1098 fd
= sd_bus_get_fd(b
);
1100 fd
= fdset_put_dup(fds
, fd
);
1106 /* We don't offer any APIs on the system bus (well, unless it
1107 * is the same as the API bus) hence we don't bother with it
1113 int bus_foreach_bus(
1115 sd_bus_track
*subscribed2
,
1116 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1123 /* Send to all direct buses, unconditionally */
1124 SET_FOREACH(b
, m
->private_buses
, i
) {
1125 r
= send_message(b
, userdata
);
1130 /* Send to API bus, but only if somebody is subscribed */
1131 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1132 sd_bus_track_count(subscribed2
) > 0) {
1133 r
= send_message(m
->api_bus
, userdata
);
1141 void bus_track_serialize(sd_bus_track
*t
, FILE *f
) {
1146 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
))
1147 fprintf(f
, "subscribed=%s\n", n
);
1150 int bus_track_deserialize_item(char ***l
, const char *line
) {
1157 e
= startswith(line
, "subscribed=");
1161 r
= strv_extend(l
, e
);
1168 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, char ***l
) {
1175 if (!strv_isempty(*l
) && m
->api_bus
) {
1179 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1185 STRV_FOREACH(i
, *l
) {
1188 k
= sd_bus_track_add_name(*t
, *i
);
1199 int bus_verify_manage_units_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1200 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1203 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1204 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1207 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1208 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);
1211 int bus_verify_set_environment_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1212 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.set-environment", NULL
, false, UID_INVALID
, &m
->polkit_registry
, error
);