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 "dbus-client-track.h"
46 #define CONNECTIONS_MAX 512
48 static void destroy_bus(Manager *m, sd_bus **bus);
50 int bus_send_queued_message(Manager *m) {
55 if (!m->queued_message)
58 assert(m->queued_message_bus);
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(m->queued_message_bus, m->queued_message, NULL);
66 log_warning("Failed to send queued message: %s", strerror(-r));
68 m->queued_message = sd_bus_message_unref(m->queued_message);
69 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
74 static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata) {
75 Manager *m = userdata;
83 r = sd_bus_message_read(message, "s", &cgroup);
85 bus_log_parse_error(r);
89 manager_notify_cgroup_empty(m, cgroup);
91 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
92 /* If we are running as system manager, forward the
93 * message to the system bus */
95 r = sd_bus_send(m->system_bus, message, NULL);
97 log_warning("Failed to forward Released message: %s", strerror(-r));
103 static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata) {
104 Manager *m = userdata;
110 if (bus == m->api_bus)
111 destroy_bus(m, &m->api_bus);
112 if (bus == m->system_bus)
113 destroy_bus(m, &m->system_bus);
114 if (set_remove(m->private_buses, bus)) {
115 log_debug("Got disconnect on private connection.");
116 destroy_bus(m, &bus);
122 static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
123 const char *name, *old_owner, *new_owner;
124 Manager *m = userdata;
131 r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
133 bus_log_parse_error(r);
137 manager_dispatch_bus_name_owner_changed(
139 isempty(old_owner) ? NULL : old_owner,
140 isempty(new_owner) ? NULL : new_owner);
145 static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata) {
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;
157 r = sd_bus_message_read(message, "s", &name);
159 bus_log_parse_error(r);
163 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
164 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
165 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
169 r = manager_load_unit(m, name, NULL, &error, &u);
173 if (u->refuse_manual_start) {
174 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %u may be requested by dependency only.", u->id);
178 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
182 /* Successfully queued, that's it for us */
186 if (!sd_bus_error_is_set(&error))
187 sd_bus_error_set_errno(&error, r);
189 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
191 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure", &reply);
193 bus_log_create_error(r);
197 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
199 bus_log_create_error(r);
203 r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
205 log_error("Failed to respond with to bus activation request: %s", strerror(-r));
212 static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
213 Manager *m = userdata;
223 r = manager_get_job_from_dbus_path(m, path, &j);
231 static Unit *find_unit(Manager *m, sd_bus *bus, const char *path) {
239 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
240 sd_bus_message *message;
243 message = sd_bus_get_current(bus);
247 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
251 u = manager_get_unit_by_pid(m, pid);
253 r = manager_load_unit_from_dbus_path(m, path, NULL, &u);
261 static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
262 Manager *m = userdata;
271 u = find_unit(m, bus, path);
279 static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
280 Manager *m = userdata;
289 u = find_unit(m, bus, path);
293 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
300 static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
301 Manager *m = userdata;
310 u = find_unit(m, bus, path);
314 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
317 if (!unit_get_cgroup_context(u))
324 static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
325 Manager *m = userdata;
335 u = find_unit(m, bus, path);
339 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
342 c = unit_get_cgroup_context(u);
350 static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
351 Manager *m = userdata;
361 u = find_unit(m, bus, path);
365 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
368 c = unit_get_exec_context(u);
376 static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
377 Manager *m = userdata;
387 u = find_unit(m, bus, path);
391 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
394 c = unit_get_kill_context(u);
402 static int bus_job_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
403 _cleanup_free_ char **l = NULL;
404 Manager *m = userdata;
409 l = new0(char*, hashmap_size(m->jobs)+1);
413 HASHMAP_FOREACH(j, m->jobs, i) {
414 l[k] = job_dbus_path(j);
421 assert(hashmap_size(m->jobs) == k);
429 static int bus_unit_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
430 _cleanup_free_ char **l = NULL;
431 Manager *m = userdata;
436 l = new0(char*, hashmap_size(m->units)+1);
440 HASHMAP_FOREACH(u, m->units, i) {
441 l[k] = unit_dbus_path(u);
454 static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
461 r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
463 log_error("Failed to register Manager vtable: %s", strerror(-r));
467 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
469 log_error("Failed to register Job vtable: %s", strerror(-r));
473 r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
475 log_error("Failed to add job enumerator: %s", strerror(-r));
479 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
481 log_error("Failed to register Unit vtable: %s", strerror(-r));
485 r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
487 log_error("Failed to add job enumerator: %s", strerror(-r));
491 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
492 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
494 log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
498 if (unit_vtable[t]->cgroup_context_offset > 0) {
499 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
501 log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
505 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
507 log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
512 if (unit_vtable[t]->exec_context_offset > 0) {
513 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
515 log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
520 if (unit_vtable[t]->kill_context_offset > 0) {
521 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
523 log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
532 static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
538 r = sd_bus_add_match(
541 "path='/org/freedesktop/DBus/Local',"
542 "interface='org.freedesktop.DBus.Local',"
543 "member='Disconnected'",
544 signal_disconnected, m);
547 log_error("Failed to register match for Disconnected message: %s", strerror(-r));
554 static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
555 _cleanup_bus_unref_ sd_bus *bus = NULL;
556 _cleanup_close_ int nfd = -1;
557 Manager *m = userdata;
564 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
566 log_warning("Failed to accept private connection, ignoring: %m");
570 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
571 log_warning("Too many concurrent connections, refusing");
575 r = set_ensure_allocated(&m->private_buses, trivial_hash_func, trivial_compare_func);
581 r = sd_bus_new(&bus);
583 log_warning("Failed to allocate new private connection bus: %s", strerror(-r));
587 r = sd_bus_set_fd(bus, nfd, nfd);
589 log_warning("Failed to set fd on new connection bus: %s", strerror(-r));
595 r = bus_check_peercred(bus);
597 log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
601 assert_se(sd_id128_randomize(&id) >= 0);
603 r = sd_bus_set_server(bus, 1, id);
605 log_warning("Failed to enable server support for new connection bus: %s", strerror(-r));
609 r = sd_bus_start(bus);
611 log_warning("Failed to start new connection bus: %s", strerror(-r));
615 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
617 log_warning("Failed to attach new connection bus to event loop: %s", strerror(-r));
621 if (m->running_as == SYSTEMD_SYSTEM) {
622 /* When we run as system instance we get the Released
623 * signal via a direct connection */
625 r = sd_bus_add_match(
628 "interface='org.freedesktop.systemd1.Agent',"
630 "path='/org/freedesktop/systemd1/agent'",
631 signal_agent_released, m);
634 log_warning("Failed to register Released match on new connection bus: %s", strerror(-r));
639 r = bus_setup_disconnected_match(m, bus);
643 r = bus_setup_api_vtables(m, bus);
645 log_warning("Failed to set up API vtables on new connection bus: %s", strerror(-r));
649 r = set_put(m->private_buses, bus);
651 log_warning("Failed to add new conenction bus to set: %s", strerror(-r));
657 log_debug("Accepted new private connection.");
662 static int bus_list_names(Manager *m, sd_bus *bus) {
663 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
664 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
671 r = sd_bus_call_method(
673 "org.freedesktop.DBus",
674 "/org/freedesktop/DBus",
675 "org.freedesktop.DBus",
680 log_error("Failed to get initial list of names: %s", bus_error_message(&error, r));
684 r = sd_bus_message_enter_container(reply, 'a', "s");
686 return bus_log_parse_error(r);
688 /* This is a bit hacky, we say the owner of the name is the
689 * name itself, because we don't want the extra traffic to
690 * figure out the real owner. */
691 while ((r = sd_bus_message_read(reply, "s", &name)) > 0)
692 manager_dispatch_bus_name_owner_changed(m, name, NULL, name);
694 return bus_log_parse_error(r);
696 r = sd_bus_message_exit_container(reply);
698 return bus_log_parse_error(r);
703 static int bus_setup_api(Manager *m, sd_bus *bus) {
709 r = bus_setup_api_vtables(m, bus);
713 r = sd_bus_add_match(
716 "sender='org.freedesktop.DBus',"
717 "path='/org/freedesktop/DBus',"
718 "interface='org.freedesktop.DBus',"
719 "member='NameOwnerChanged'",
720 signal_name_owner_changed, m);
722 log_warning("Failed to subscribe to NameOwnerChanged signal: %s", strerror(-r));
724 r = sd_bus_add_match(
727 "sender='org.freedesktop.DBus',"
728 "path='/org/freedesktop/DBus',"
729 "interface='org.freedesktop.systemd1.Activator',"
730 "member='ActivationRequest'",
731 signal_activation_request, m);
733 log_warning("Failed to subscribe to activation signal: %s", strerror(-r));
735 /* Allow replacing of our name, to ease implementation of
736 * reexecution, where we keep the old connection open until
737 * after the new connection is set up and the name installed
738 * to allow clients to synchronously wait for reexecution to
740 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING);
742 log_error("Failed to register name: %s", strerror(-r));
746 if (r != SD_BUS_NAME_PRIMARY_OWNER) {
747 log_error("Failed to acquire name.");
751 bus_list_names(m, bus);
753 log_debug("Successfully connected to API bus.");
757 static int bus_init_api(Manager *m) {
758 _cleanup_bus_unref_ sd_bus *bus = NULL;
764 /* The API and system bus is the same if we are running in system mode */
765 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
766 bus = sd_bus_ref(m->system_bus);
768 if (m->running_as == SYSTEMD_SYSTEM)
769 r = sd_bus_open_system(&bus);
771 r = sd_bus_open_user(&bus);
774 log_debug("Failed to connect to API bus, retrying later...");
778 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
780 log_error("Failed to attach API bus to event loop: %s", strerror(-r));
784 r = bus_setup_disconnected_match(m, bus);
789 r = bus_setup_api(m, bus);
791 log_error("Failed to set up API bus: %s", strerror(-r));
801 static int bus_setup_system(Manager *m, sd_bus *bus) {
807 if (m->running_as == SYSTEMD_SYSTEM)
810 /* If we are a user instance we get the Released message via
812 r = sd_bus_add_match(
815 "interface='org.freedesktop.systemd1.Agent',"
817 "path='/org/freedesktop/systemd1/agent'",
818 signal_agent_released, m);
821 log_warning("Failed to register Released match on system bus: %s", strerror(-r));
823 log_debug("Successfully connected to system bus.");
827 static int bus_init_system(Manager *m) {
828 _cleanup_bus_unref_ sd_bus *bus = NULL;
834 /* The API and system bus is the same if we are running in system mode */
835 if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
836 m->system_bus = sd_bus_ref(m->api_bus);
840 r = sd_bus_open_system(&bus);
842 log_debug("Failed to connect to system bus, retrying later...");
846 r = bus_setup_disconnected_match(m, bus);
850 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
852 log_error("Failed to attach system bus to event loop: %s", strerror(-r));
856 r = bus_setup_system(m, bus);
858 log_error("Fauiled to set up system bus: %s", strerror(-r));
868 static int bus_init_private(Manager *m) {
869 _cleanup_close_ int fd = -1;
870 union sockaddr_union sa = {
871 .un.sun_family = AF_UNIX
879 if (m->private_listen_fd >= 0)
882 if (m->running_as == SYSTEMD_SYSTEM) {
884 /* We want the private bus only when running as init */
888 strcpy(sa.un.sun_path, "/run/systemd/private");
889 salen = offsetof(union sockaddr_union, un.sun_path) + sizeof("/run/systemd/private") - 1;
891 size_t left = sizeof(sa.un.sun_path);
892 char *p = sa.un.sun_path;
895 e = secure_getenv("XDG_RUNTIME_DIR");
897 log_error("Failed to determine XDG_RUNTIME_DIR");
901 left = strpcpy(&p, left, e);
902 left = strpcpy(&p, left, "/systemd/private");
904 salen = sizeof(sa.un) - left;
906 mkdir_parents_label(sa.un.sun_path, 0755);
909 unlink(sa.un.sun_path);
911 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
913 log_error("Failed to allocate private socket: %m");
917 r = bind(fd, &sa.sa, salen);
919 log_error("Failed to bind private socket: %m");
923 r = listen(fd, SOMAXCONN);
925 log_error("Failed to make private socket listening: %m");
929 r = sd_event_add_io(m->event, fd, EPOLLIN, bus_on_connection, m, &s);
931 log_error("Failed to allocate event source: %s", strerror(-r));
935 m->private_listen_fd = fd;
936 m->private_listen_event_source = s;
939 log_debug("Successfully created private D-Bus server.");
944 int bus_init(Manager *m, bool try_bus_connect) {
947 if (try_bus_connect) {
948 r = bus_init_system(m);
957 r = bus_init_private(m);
964 static void destroy_bus(Manager *m, sd_bus **bus) {
974 /* Get rid of tracked clients on this bus */
975 bus_client_untrack_bus(m->subscribed, *bus);
976 HASHMAP_FOREACH(j, m->jobs, i)
977 bus_client_untrack_bus(j->subscribed, *bus);
979 /* Get rid of queued message on this bus */
980 if (m->queued_message_bus == *bus) {
981 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
983 if (m->queued_message)
984 m->queued_message = sd_bus_message_unref(m->queued_message);
987 /* Possibly flush unwritten data, but only if we are
988 * unprivileged, since we don't want to sync here */
989 if (m->running_as != SYSTEMD_SYSTEM)
992 /* And destroy the object */
994 *bus = sd_bus_unref(*bus);
997 void bus_done(Manager *m) {
1003 destroy_bus(m, &m->api_bus);
1005 destroy_bus(m, &m->system_bus);
1006 while ((b = set_steal_first(m->private_buses)))
1009 set_free(m->private_buses);
1010 set_free(m->subscribed);
1012 if (m->private_listen_event_source)
1013 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1015 if (m->private_listen_fd >= 0) {
1016 close_nointr_nofail(m->private_listen_fd);
1017 m->private_listen_fd = -1;
1021 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1029 /* When we are about to reexecute we add all D-Bus fds to the
1030 * set to pass over to the newly executed systemd. They won't
1031 * be used there however, except thatt they are closed at the
1032 * very end of deserialization, those making it possible for
1033 * clients to synchronously wait for systemd to reexec by
1034 * simply waiting for disconnection */
1037 fd = sd_bus_get_fd(m->api_bus);
1039 fd = fdset_put_dup(fds, fd);
1045 SET_FOREACH(b, m->private_buses, i) {
1046 fd = sd_bus_get_fd(b);
1048 fd = fdset_put_dup(fds, fd);
1054 /* We don't offer any APIs on the system bus (well, unless it
1055 * is the same as the API bus) hence we don't bother with it
1061 void bus_serialize(Manager *m, FILE *f) {
1065 bus_client_track_serialize(m, f, m->subscribed);
1068 int bus_deserialize_item(Manager *m, const char *line) {
1072 return bus_client_track_deserialize_item(m, &m->subscribed, line);