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>
32 #include "dbus-unit.h"
34 #include "dbus-manager.h"
35 #include "dbus-execute.h"
36 #include "dbus-kill.h"
37 #include "dbus-cgroup.h"
41 #include "bus-error.h"
42 #include "bus-errors.h"
44 #include "bus-internal.h"
45 #include "selinux-access.h"
47 #define CONNECTIONS_MAX 512
49 static void destroy_bus(Manager
*m
, sd_bus
**bus
);
51 int bus_send_queued_message(Manager
*m
) {
56 if (!m
->queued_message
)
59 assert(m
->queued_message_bus
);
61 /* If we cannot get rid of this message we won't dispatch any
62 * D-Bus messages, so that we won't end up wanting to queue
65 r
= sd_bus_send(m
->queued_message_bus
, m
->queued_message
, NULL
);
67 log_warning_errno(-r
, "Failed to send queued message: %m");
69 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
70 m
->queued_message_bus
= sd_bus_unref(m
->queued_message_bus
);
75 static int signal_agent_released(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
76 Manager
*m
= userdata
;
84 r
= sd_bus_message_read(message
, "s", &cgroup
);
86 bus_log_parse_error(r
);
90 manager_notify_cgroup_empty(m
, cgroup
);
92 if (m
->running_as
== SYSTEMD_SYSTEM
&& m
->system_bus
) {
93 /* If we are running as system manager, forward the
94 * message to the system bus */
96 r
= sd_bus_send(m
->system_bus
, message
, NULL
);
98 log_warning_errno(-r
, "Failed to forward Released message: %m");
104 static int signal_disconnected(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
105 Manager
*m
= userdata
;
111 if (bus
== m
->api_bus
)
112 destroy_bus(m
, &m
->api_bus
);
113 if (bus
== m
->system_bus
)
114 destroy_bus(m
, &m
->system_bus
);
115 if (set_remove(m
->private_buses
, bus
)) {
116 log_debug("Got disconnect on private connection.");
117 destroy_bus(m
, &bus
);
123 static int signal_name_owner_changed(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
124 const char *name
, *old_owner
, *new_owner
;
125 Manager
*m
= userdata
;
132 r
= sd_bus_message_read(message
, "sss", &name
, &old_owner
, &new_owner
);
134 bus_log_parse_error(r
);
138 manager_dispatch_bus_name_owner_changed(
140 isempty(old_owner
) ? NULL
: old_owner
,
141 isempty(new_owner
) ? NULL
: new_owner
);
146 static int signal_activation_request(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*ret_error
) {
147 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
148 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
149 Manager
*m
= userdata
;
158 r
= sd_bus_message_read(message
, "s", &name
);
160 bus_log_parse_error(r
);
164 if (manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SERVICE
) ||
165 manager_unit_inactive_or_pending(m
, SPECIAL_DBUS_SOCKET
)) {
166 r
= sd_bus_error_setf(&error
, BUS_ERROR_SHUTTING_DOWN
, "Refusing activation, D-Bus is shutting down.");
170 r
= manager_load_unit(m
, name
, NULL
, &error
, &u
);
174 if (u
->refuse_manual_start
) {
175 r
= sd_bus_error_setf(&error
, BUS_ERROR_ONLY_BY_DEPENDENCY
, "Operation refused, %s may be requested by dependency only.", u
->id
);
179 r
= manager_add_job(m
, JOB_START
, u
, JOB_REPLACE
, true, &error
, NULL
);
183 /* Successfully queued, that's it for us */
187 if (!sd_bus_error_is_set(&error
))
188 sd_bus_error_set_errno(&error
, r
);
190 log_debug("D-Bus activation failed for %s: %s", name
, bus_error_message(&error
, r
));
192 r
= sd_bus_message_new_signal(bus
, &reply
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
194 bus_log_create_error(r
);
198 r
= sd_bus_message_append(reply
, "sss", name
, error
.name
, error
.message
);
200 bus_log_create_error(r
);
204 r
= sd_bus_send_to(bus
, reply
, "org.freedesktop.DBus", NULL
);
206 log_error_errno(-r
, "Failed to respond with to bus activation request: %m");
214 static int mac_selinux_filter(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
215 Manager
*m
= userdata
;
216 const char *verb
, *path
;
224 /* Our own method calls are all protected individually with
225 * selinux checks, but the built-in interfaces need to be
228 if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", "Set"))
230 else if (sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Introspectable", NULL
) ||
231 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Properties", NULL
) ||
232 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.ObjectManager", NULL
) ||
233 sd_bus_message_is_method_call(message
, "org.freedesktop.DBus.Peer", NULL
))
238 path
= sd_bus_message_get_path(message
);
240 if (object_path_startswith("/org/freedesktop/systemd1", path
)) {
242 r
= mac_selinux_access_check(message
, verb
, error
);
249 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
250 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
253 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
257 r
= sd_bus_creds_get_pid(creds
, &pid
);
261 u
= manager_get_unit_by_pid(m
, pid
);
263 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
267 manager_load_unit_from_dbus_path(m
, path
, NULL
, &u
);
273 r
= mac_selinux_unit_access_check(u
, message
, verb
, error
);
281 static int bus_job_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
282 Manager
*m
= userdata
;
292 r
= manager_get_job_from_dbus_path(m
, path
, &j
);
300 static int find_unit(Manager
*m
, sd_bus
*bus
, const char *path
, Unit
**unit
, sd_bus_error
*error
) {
308 if (streq_ptr(path
, "/org/freedesktop/systemd1/unit/self")) {
309 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
310 sd_bus_message
*message
;
313 message
= sd_bus_get_current_message(bus
);
317 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
321 r
= sd_bus_creds_get_pid(creds
, &pid
);
325 u
= manager_get_unit_by_pid(m
, pid
);
327 r
= manager_load_unit_from_dbus_path(m
, path
, error
, &u
);
339 static int bus_unit_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
340 Manager
*m
= userdata
;
348 return find_unit(m
, bus
, path
, (Unit
**) found
, error
);
351 static int bus_unit_interface_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
352 Manager
*m
= userdata
;
362 r
= find_unit(m
, bus
, path
, &u
, error
);
366 if (!streq_ptr(interface
, UNIT_VTABLE(u
)->bus_interface
))
373 static int bus_unit_cgroup_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
374 Manager
*m
= userdata
;
384 r
= find_unit(m
, bus
, path
, &u
, error
);
388 if (!streq_ptr(interface
, UNIT_VTABLE(u
)->bus_interface
))
391 if (!unit_get_cgroup_context(u
))
398 static int bus_cgroup_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
399 Manager
*m
= userdata
;
410 r
= find_unit(m
, bus
, path
, &u
, error
);
414 if (!streq_ptr(interface
, UNIT_VTABLE(u
)->bus_interface
))
417 c
= unit_get_cgroup_context(u
);
425 static int bus_exec_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
426 Manager
*m
= userdata
;
437 r
= find_unit(m
, bus
, path
, &u
, error
);
441 if (!streq_ptr(interface
, UNIT_VTABLE(u
)->bus_interface
))
444 c
= unit_get_exec_context(u
);
452 static int bus_kill_context_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
453 Manager
*m
= userdata
;
464 r
= find_unit(m
, bus
, path
, &u
, error
);
468 if (!streq_ptr(interface
, UNIT_VTABLE(u
)->bus_interface
))
471 c
= unit_get_kill_context(u
);
479 static int bus_job_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
480 _cleanup_free_
char **l
= NULL
;
481 Manager
*m
= userdata
;
486 l
= new0(char*, hashmap_size(m
->jobs
)+1);
490 HASHMAP_FOREACH(j
, m
->jobs
, i
) {
491 l
[k
] = job_dbus_path(j
);
498 assert(hashmap_size(m
->jobs
) == k
);
506 static int bus_unit_enumerate(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
507 _cleanup_free_
char **l
= NULL
;
508 Manager
*m
= userdata
;
513 l
= new0(char*, hashmap_size(m
->units
)+1);
517 HASHMAP_FOREACH(u
, m
->units
, i
) {
518 l
[k
] = unit_dbus_path(u
);
531 static int bus_setup_api_vtables(Manager
*m
, sd_bus
*bus
) {
539 r
= sd_bus_add_filter(bus
, NULL
, mac_selinux_filter
, m
);
541 log_error_errno(-r
, "Failed to add SELinux access filter: %m");
546 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable
, m
);
548 log_error_errno(-r
, "Failed to register Manager vtable: %m");
552 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable
, bus_job_find
, m
);
554 log_error_errno(-r
, "Failed to register Job vtable: %m");
558 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/job", bus_job_enumerate
, m
);
560 log_error_errno(-r
, "Failed to add job enumerator: %m");
564 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable
, bus_unit_find
, m
);
566 log_error_errno(-r
, "Failed to register Unit vtable: %m");
570 r
= sd_bus_add_node_enumerator(bus
, NULL
, "/org/freedesktop/systemd1/unit", bus_unit_enumerate
, m
);
572 log_error_errno(-r
, "Failed to add job enumerator: %m");
576 for (t
= 0; t
< _UNIT_TYPE_MAX
; t
++) {
577 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", unit_vtable
[t
]->bus_interface
, unit_vtable
[t
]->bus_vtable
, bus_unit_interface_find
, m
);
579 log_error_errno(-r
, "Failed to register type specific vtable for %s: %m", unit_vtable
[t
]->bus_interface
);
583 if (unit_vtable
[t
]->cgroup_context_offset
> 0) {
584 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", unit_vtable
[t
]->bus_interface
, bus_unit_cgroup_vtable
, bus_unit_cgroup_find
, m
);
586 log_error_errno(-r
, "Failed to register control group unit vtable for %s: %m", unit_vtable
[t
]->bus_interface
);
590 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", unit_vtable
[t
]->bus_interface
, bus_cgroup_vtable
, bus_cgroup_context_find
, m
);
592 log_error_errno(-r
, "Failed to register control group vtable for %s: %m", unit_vtable
[t
]->bus_interface
);
597 if (unit_vtable
[t
]->exec_context_offset
> 0) {
598 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", unit_vtable
[t
]->bus_interface
, bus_exec_vtable
, bus_exec_context_find
, m
);
600 log_error_errno(-r
, "Failed to register execute vtable for %s: %m", unit_vtable
[t
]->bus_interface
);
605 if (unit_vtable
[t
]->kill_context_offset
> 0) {
606 r
= sd_bus_add_fallback_vtable(bus
, NULL
, "/org/freedesktop/systemd1/unit", unit_vtable
[t
]->bus_interface
, bus_kill_vtable
, bus_kill_context_find
, m
);
608 log_error_errno(-r
, "Failed to register kill vtable for %s: %m", unit_vtable
[t
]->bus_interface
);
617 static int bus_setup_disconnected_match(Manager
*m
, sd_bus
*bus
) {
623 r
= sd_bus_add_match(
626 "sender='org.freedesktop.DBus.Local',"
628 "path='/org/freedesktop/DBus/Local',"
629 "interface='org.freedesktop.DBus.Local',"
630 "member='Disconnected'",
631 signal_disconnected
, m
);
634 log_error_errno(-r
, "Failed to register match for Disconnected message: %m");
641 static int bus_on_connection(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
642 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
643 _cleanup_close_
int nfd
= -1;
644 Manager
*m
= userdata
;
651 nfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
653 log_warning("Failed to accept private connection, ignoring: %m");
657 if (set_size(m
->private_buses
) >= CONNECTIONS_MAX
) {
658 log_warning("Too many concurrent connections, refusing");
662 r
= set_ensure_allocated(&m
->private_buses
, NULL
);
668 r
= sd_bus_new(&bus
);
670 log_warning_errno(-r
, "Failed to allocate new private connection bus: %m");
674 r
= sd_bus_set_fd(bus
, nfd
, nfd
);
676 log_warning_errno(-r
, "Failed to set fd on new connection bus: %m");
682 r
= bus_check_peercred(bus
);
684 log_warning_errno(-r
, "Incoming private connection from unprivileged client, refusing: %m");
688 assert_se(sd_id128_randomize(&id
) >= 0);
690 r
= sd_bus_set_server(bus
, 1, id
);
692 log_warning_errno(-r
, "Failed to enable server support for new connection bus: %m");
696 r
= sd_bus_start(bus
);
698 log_warning_errno(-r
, "Failed to start new connection bus: %m");
702 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
704 log_warning_errno(-r
, "Failed to attach new connection bus to event loop: %m");
708 if (m
->running_as
== SYSTEMD_SYSTEM
) {
709 /* When we run as system instance we get the Released
710 * signal via a direct connection */
712 r
= sd_bus_add_match(
716 "interface='org.freedesktop.systemd1.Agent',"
718 "path='/org/freedesktop/systemd1/agent'",
719 signal_agent_released
, m
);
722 log_warning_errno(-r
, "Failed to register Released match on new connection bus: %m");
727 r
= bus_setup_disconnected_match(m
, bus
);
731 r
= bus_setup_api_vtables(m
, bus
);
733 log_warning_errno(-r
, "Failed to set up API vtables on new connection bus: %m");
737 r
= set_put(m
->private_buses
, bus
);
739 log_warning_errno(-r
, "Failed to add new conenction bus to set: %m");
745 log_debug("Accepted new private connection.");
750 static int bus_list_names(Manager
*m
, sd_bus
*bus
) {
751 _cleanup_strv_free_
char **names
= NULL
;
758 r
= sd_bus_list_names(bus
, &names
, NULL
);
760 log_error_errno(-r
, "Failed to get initial list of names: %m");
764 /* This is a bit hacky, we say the owner of the name is the
765 * name itself, because we don't want the extra traffic to
766 * figure out the real owner. */
767 STRV_FOREACH(i
, names
)
768 manager_dispatch_bus_name_owner_changed(m
, *i
, NULL
, *i
);
773 static int bus_setup_api(Manager
*m
, sd_bus
*bus
) {
779 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
780 r
= sd_bus_negotiate_creds(bus
, 1,
781 SD_BUS_CREDS_PID
|SD_BUS_CREDS_UID
|
782 SD_BUS_CREDS_EUID
|SD_BUS_CREDS_EFFECTIVE_CAPS
|
783 SD_BUS_CREDS_SELINUX_CONTEXT
);
785 log_warning_errno(-r
, "Failed to enable credential passing, ignoring: %m");
787 r
= bus_setup_api_vtables(m
, bus
);
791 r
= sd_bus_add_match(
795 "sender='org.freedesktop.DBus',"
796 "path='/org/freedesktop/DBus',"
797 "interface='org.freedesktop.DBus',"
798 "member='NameOwnerChanged'",
799 signal_name_owner_changed
, m
);
801 log_warning_errno(-r
, "Failed to subscribe to NameOwnerChanged signal: %m");
803 r
= sd_bus_add_match(
807 "sender='org.freedesktop.DBus',"
808 "path='/org/freedesktop/DBus',"
809 "interface='org.freedesktop.systemd1.Activator',"
810 "member='ActivationRequest'",
811 signal_activation_request
, m
);
813 log_warning_errno(-r
, "Failed to subscribe to activation signal: %m");
815 /* Allow replacing of our name, to ease implementation of
816 * reexecution, where we keep the old connection open until
817 * after the new connection is set up and the name installed
818 * to allow clients to synchronously wait for reexecution to
820 r
= sd_bus_request_name(bus
,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING
|SD_BUS_NAME_ALLOW_REPLACEMENT
);
822 log_error_errno(-r
, "Failed to register name: %m");
826 bus_list_names(m
, bus
);
828 log_debug("Successfully connected to API bus.");
832 static int bus_init_api(Manager
*m
) {
833 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
839 /* The API and system bus is the same if we are running in system mode */
840 if (m
->running_as
== SYSTEMD_SYSTEM
&& m
->system_bus
)
841 bus
= sd_bus_ref(m
->system_bus
);
843 if (m
->running_as
== SYSTEMD_SYSTEM
)
844 r
= sd_bus_open_system(&bus
);
846 r
= sd_bus_open_user(&bus
);
849 log_debug("Failed to connect to API bus, retrying later...");
853 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
855 log_error_errno(-r
, "Failed to attach API bus to event loop: %m");
859 r
= bus_setup_disconnected_match(m
, bus
);
864 r
= bus_setup_api(m
, bus
);
866 log_error_errno(-r
, "Failed to set up API bus: %m");
876 static int bus_setup_system(Manager
*m
, sd_bus
*bus
) {
882 if (m
->running_as
== SYSTEMD_SYSTEM
)
885 /* If we are a user instance we get the Released message via
887 r
= sd_bus_add_match(
891 "interface='org.freedesktop.systemd1.Agent',"
893 "path='/org/freedesktop/systemd1/agent'",
894 signal_agent_released
, m
);
897 log_warning_errno(-r
, "Failed to register Released match on system bus: %m");
899 log_debug("Successfully connected to system bus.");
903 static int bus_init_system(Manager
*m
) {
904 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
910 /* The API and system bus is the same if we are running in system mode */
911 if (m
->running_as
== SYSTEMD_SYSTEM
&& m
->api_bus
) {
912 m
->system_bus
= sd_bus_ref(m
->api_bus
);
916 r
= sd_bus_open_system(&bus
);
918 log_debug("Failed to connect to system bus, retrying later...");
922 r
= bus_setup_disconnected_match(m
, bus
);
926 r
= sd_bus_attach_event(bus
, m
->event
, SD_EVENT_PRIORITY_NORMAL
);
928 log_error_errno(-r
, "Failed to attach system bus to event loop: %m");
932 r
= bus_setup_system(m
, bus
);
934 log_error_errno(-r
, "Failed to set up system bus: %m");
944 static int bus_init_private(Manager
*m
) {
945 _cleanup_close_
int fd
= -1;
946 union sockaddr_union sa
= {
947 .un
.sun_family
= AF_UNIX
955 if (m
->private_listen_fd
>= 0)
958 /* We don't need the private socket if we have kdbus */
959 if (m
->kdbus_fd
>= 0)
962 if (m
->running_as
== SYSTEMD_SYSTEM
) {
964 /* We want the private bus only when running as init */
968 strcpy(sa
.un
.sun_path
, "/run/systemd/private");
969 salen
= offsetof(union sockaddr_union
, un
.sun_path
) + strlen("/run/systemd/private");
971 size_t left
= sizeof(sa
.un
.sun_path
);
972 char *p
= sa
.un
.sun_path
;
975 e
= secure_getenv("XDG_RUNTIME_DIR");
977 log_error("Failed to determine XDG_RUNTIME_DIR");
981 left
= strpcpy(&p
, left
, e
);
982 left
= strpcpy(&p
, left
, "/systemd/private");
984 salen
= sizeof(sa
.un
) - left
;
987 (void) mkdir_parents_label(sa
.un
.sun_path
, 0755);
988 (void) unlink(sa
.un
.sun_path
);
990 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
992 log_error("Failed to allocate private socket: %m");
996 r
= bind(fd
, &sa
.sa
, salen
);
998 log_error("Failed to bind private socket: %m");
1002 r
= listen(fd
, SOMAXCONN
);
1004 log_error("Failed to make private socket listening: %m");
1008 r
= sd_event_add_io(m
->event
, &s
, fd
, EPOLLIN
, bus_on_connection
, m
);
1010 log_error_errno(-r
, "Failed to allocate event source: %m");
1014 m
->private_listen_fd
= fd
;
1015 m
->private_listen_event_source
= s
;
1018 log_debug("Successfully created private D-Bus server.");
1023 int bus_init(Manager
*m
, bool try_bus_connect
) {
1026 if (try_bus_connect
) {
1027 r
= bus_init_system(m
);
1031 r
= bus_init_api(m
);
1036 r
= bus_init_private(m
);
1043 static void destroy_bus(Manager
*m
, sd_bus
**bus
) {
1053 /* Get rid of tracked clients on this bus */
1054 if (m
->subscribed
&& sd_bus_track_get_bus(m
->subscribed
) == *bus
)
1055 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1057 HASHMAP_FOREACH(j
, m
->jobs
, i
)
1058 if (j
->clients
&& sd_bus_track_get_bus(j
->clients
) == *bus
)
1059 j
->clients
= sd_bus_track_unref(j
->clients
);
1061 /* Get rid of queued message on this bus */
1062 if (m
->queued_message_bus
== *bus
) {
1063 m
->queued_message_bus
= sd_bus_unref(m
->queued_message_bus
);
1065 if (m
->queued_message
)
1066 m
->queued_message
= sd_bus_message_unref(m
->queued_message
);
1069 /* Possibly flush unwritten data, but only if we are
1070 * unprivileged, since we don't want to sync here */
1071 if (m
->running_as
!= SYSTEMD_SYSTEM
)
1074 /* And destroy the object */
1076 *bus
= sd_bus_unref(*bus
);
1079 void bus_done(Manager
*m
) {
1085 destroy_bus(m
, &m
->api_bus
);
1087 destroy_bus(m
, &m
->system_bus
);
1088 while ((b
= set_steal_first(m
->private_buses
)))
1091 set_free(m
->private_buses
);
1092 m
->private_buses
= NULL
;
1094 m
->subscribed
= sd_bus_track_unref(m
->subscribed
);
1095 strv_free(m
->deserialized_subscribed
);
1096 m
->deserialized_subscribed
= NULL
;
1098 if (m
->private_listen_event_source
)
1099 m
->private_listen_event_source
= sd_event_source_unref(m
->private_listen_event_source
);
1101 m
->private_listen_fd
= safe_close(m
->private_listen_fd
);
1103 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
1106 int bus_fdset_add_all(Manager
*m
, FDSet
*fds
) {
1114 /* When we are about to reexecute we add all D-Bus fds to the
1115 * set to pass over to the newly executed systemd. They won't
1116 * be used there however, except thatt they are closed at the
1117 * very end of deserialization, those making it possible for
1118 * clients to synchronously wait for systemd to reexec by
1119 * simply waiting for disconnection */
1122 fd
= sd_bus_get_fd(m
->api_bus
);
1124 fd
= fdset_put_dup(fds
, fd
);
1130 SET_FOREACH(b
, m
->private_buses
, i
) {
1131 fd
= sd_bus_get_fd(b
);
1133 fd
= fdset_put_dup(fds
, fd
);
1139 /* We don't offer any APIs on the system bus (well, unless it
1140 * is the same as the API bus) hence we don't bother with it
1146 int bus_foreach_bus(
1148 sd_bus_track
*subscribed2
,
1149 int (*send_message
)(sd_bus
*bus
, void *userdata
),
1156 /* Send to all direct busses, unconditionally */
1157 SET_FOREACH(b
, m
->private_buses
, i
) {
1158 r
= send_message(b
, userdata
);
1163 /* Send to API bus, but only if somebody is subscribed */
1164 if (sd_bus_track_count(m
->subscribed
) > 0 ||
1165 sd_bus_track_count(subscribed2
) > 0) {
1166 r
= send_message(m
->api_bus
, userdata
);
1174 void bus_track_serialize(sd_bus_track
*t
, FILE *f
) {
1179 for (n
= sd_bus_track_first(t
); n
; n
= sd_bus_track_next(t
))
1180 fprintf(f
, "subscribed=%s\n", n
);
1183 int bus_track_deserialize_item(char ***l
, const char *line
) {
1189 e
= startswith(line
, "subscribed=");
1193 return strv_extend(l
, e
);
1196 int bus_track_coldplug(Manager
*m
, sd_bus_track
**t
, char ***l
) {
1203 if (!strv_isempty(*l
) && m
->api_bus
) {
1207 r
= sd_bus_track_new(m
->api_bus
, t
, NULL
, NULL
);
1213 STRV_FOREACH(i
, *l
) {
1216 k
= sd_bus_track_add_name(*t
, *i
);
1228 int bus_verify_manage_unit_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1229 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-units", false, &m
->polkit_registry
, error
);
1232 /* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
1233 int bus_verify_manage_unit_async_for_kill(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1234 return bus_verify_polkit_async(call
, CAP_KILL
, "org.freedesktop.systemd1.manage-units", false, &m
->polkit_registry
, error
);
1237 int bus_verify_manage_unit_files_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1238 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.manage-unit-files", false, &m
->polkit_registry
, error
);
1241 int bus_verify_reload_daemon_async(Manager
*m
, sd_bus_message
*call
, sd_bus_error
*error
) {
1242 return bus_verify_polkit_async(call
, CAP_SYS_ADMIN
, "org.freedesktop.systemd1.reload-daemon", false, &m
->polkit_registry
, error
);