]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus.c
man: add an additional note about journalctl -u
[thirdparty/systemd.git] / src / core / dbus.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7334b09
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
a7334b09 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
ea430986 21#include <errno.h>
07630cea 22#include <sys/epoll.h>
ea430986
LP
23#include <unistd.h>
24
718db961 25#include "sd-bus.h"
07630cea 26
b5efdb8a 27#include "alloc-util.h"
07630cea
LP
28#include "bus-common-errors.h"
29#include "bus-error.h"
30#include "bus-internal.h"
31#include "bus-util.h"
32#include "dbus-cgroup.h"
718db961 33#include "dbus-execute.h"
07630cea 34#include "dbus-job.h"
718db961 35#include "dbus-kill.h"
07630cea
LP
36#include "dbus-manager.h"
37#include "dbus-unit.h"
3ffd4af2
LP
38#include "dbus.h"
39#include "fd-util.h"
5b5e6dea 40#include "fs-util.h"
07630cea
LP
41#include "log.h"
42#include "missing.h"
43#include "mkdir.h"
dccca82b 44#include "process-util.h"
07630cea 45#include "selinux-access.h"
8f6df3fa 46#include "special.h"
07630cea
LP
47#include "string-util.h"
48#include "strv.h"
718db961 49#include "strxcpyx.h"
ee104e11 50#include "user-util.h"
4288f619 51
cbecf9bf 52#define CONNECTIONS_MAX 4096
5e8d1c9a 53
718db961
LP
54static void destroy_bus(Manager *m, sd_bus **bus);
55
56int bus_send_queued_message(Manager *m) {
57 int r;
8e274523 58
8e274523 59 assert(m);
2e317f52 60
718db961
LP
61 if (!m->queued_message)
62 return 0;
8e274523 63
718db961
LP
64 /* If we cannot get rid of this message we won't dispatch any
65 * D-Bus messages, so that we won't end up wanting to queue
66 * another message. */
ea430986 67
8f88ecf6 68 r = sd_bus_send(NULL, m->queued_message, NULL);
718db961 69 if (r < 0)
da927ba9 70 log_warning_errno(r, "Failed to send queued message: %m");
ea430986 71
718db961 72 m->queued_message = sd_bus_message_unref(m->queued_message);
ea430986 73
718db961 74 return 0;
ea430986
LP
75}
76
d8fdc620
LP
77int bus_forward_agent_released(Manager *m, const char *path) {
78 int r;
79
80 assert(m);
81 assert(path);
82
83 if (!MANAGER_IS_SYSTEM(m))
84 return 0;
85
86 if (!m->system_bus)
87 return 0;
88
89 /* If we are running a system instance we forward the agent message on the system bus, so that the user
90 * instances get notified about this, too */
91
92 r = sd_bus_emit_signal(m->system_bus,
93 "/org/freedesktop/systemd1/agent",
94 "org.freedesktop.systemd1.Agent",
95 "Released",
96 "s", path);
97 if (r < 0)
d5f15326 98 return log_debug_errno(r, "Failed to propagate agent release message: %m");
d8fdc620
LP
99
100 return 1;
101}
102
19070062 103static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 104 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
718db961 105 Manager *m = userdata;
d8fdc620 106 const char *cgroup;
0a069ce6 107 uid_t sender_uid;
718db961 108 int r;
ea430986 109
718db961 110 assert(message);
ea430986
LP
111 assert(m);
112
0a069ce6
DH
113 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
114 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
115 if (r < 0)
116 return r;
117
118 r = sd_bus_creds_get_euid(creds, &sender_uid);
119 if (r < 0 || sender_uid != 0)
120 return 0;
121
122 /* parse 'cgroup-empty' notification */
718db961
LP
123 r = sd_bus_message_read(message, "s", &cgroup);
124 if (r < 0) {
125 bus_log_parse_error(r);
126 return 0;
127 }
ea430986 128
718db961 129 manager_notify_cgroup_empty(m, cgroup);
718db961
LP
130 return 0;
131}
ea430986 132
19070062 133static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 134 Manager *m = userdata;
19070062 135 sd_bus *bus;
ea430986 136
718db961
LP
137 assert(message);
138 assert(m);
19070062 139 assert_se(bus = sd_bus_message_get_bus(message));
ea430986 140
718db961 141 if (bus == m->api_bus)
4502c403 142 bus_done_api(m);
718db961 143 if (bus == m->system_bus)
4502c403
LP
144 bus_done_system(m);
145
718db961
LP
146 if (set_remove(m->private_buses, bus)) {
147 log_debug("Got disconnect on private connection.");
148 destroy_bus(m, &bus);
ea430986
LP
149 }
150
718db961 151 return 0;
ea430986
LP
152}
153
19070062 154static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
4afd3348
LP
155 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
156 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
718db961
LP
157 Manager *m = userdata;
158 const char *name;
159 Unit *u;
160 int r;
ea430986 161
718db961 162 assert(message);
ea430986
LP
163 assert(m);
164
718db961
LP
165 r = sd_bus_message_read(message, "s", &name);
166 if (r < 0) {
167 bus_log_parse_error(r);
168 return 0;
169 }
ea430986 170
718db961
LP
171 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
172 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
173 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
174 goto failed;
175 }
ea430986 176
718db961
LP
177 r = manager_load_unit(m, name, NULL, &error, &u);
178 if (r < 0)
179 goto failed;
ea430986 180
718db961 181 if (u->refuse_manual_start) {
7e974e85 182 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
718db961 183 goto failed;
ea430986
LP
184 }
185
4bd29fe5 186 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, NULL);
718db961
LP
187 if (r < 0)
188 goto failed;
ea430986 189
718db961 190 /* Successfully queued, that's it for us */
ea430986 191 return 0;
ea430986 192
718db961
LP
193failed:
194 if (!sd_bus_error_is_set(&error))
195 sd_bus_error_set_errno(&error, r);
ea430986 196
718db961 197 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
ea430986 198
966c66e3 199 r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
718db961
LP
200 if (r < 0) {
201 bus_log_create_error(r);
202 return 0;
203 }
204
fa0fed49 205 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
718db961
LP
206 if (r < 0) {
207 bus_log_create_error(r);
208 return 0;
209 }
210
966c66e3 211 r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL);
23bbb0de
MS
212 if (r < 0)
213 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
ea430986 214
718db961 215 return 0;
ea430986
LP
216}
217
349cc4a5 218#if HAVE_SELINUX
19070062 219static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) {
969987ea
LP
220 Manager *m = userdata;
221 const char *verb, *path;
222 Unit *u = NULL;
223 Job *j;
224 int r;
225
969987ea
LP
226 assert(message);
227
228 /* Our own method calls are all protected individually with
229 * selinux checks, but the built-in interfaces need to be
230 * protected too. */
231
232 if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
233 verb = "reload";
234 else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
235 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
236 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
237 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
238 verb = "status";
239 else
240 return 0;
241
242 path = sd_bus_message_get_path(message);
243
244 if (object_path_startswith("/org/freedesktop/systemd1", path)) {
245
8a188de9 246 r = mac_selinux_access_check(message, verb, error);
969987ea
LP
247 if (r < 0)
248 return r;
249
250 return 0;
251 }
252
253 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
4afd3348 254 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
969987ea
LP
255 pid_t pid;
256
5b12334d
LP
257 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
258 if (r < 0)
259 return 0;
260
261 r = sd_bus_creds_get_pid(creds, &pid);
969987ea
LP
262 if (r < 0)
263 return 0;
264
265 u = manager_get_unit_by_pid(m, pid);
266 } else {
267 r = manager_get_job_from_dbus_path(m, path, &j);
268 if (r >= 0)
269 u = j->unit;
270 else
271 manager_load_unit_from_dbus_path(m, path, NULL, &u);
272 }
273
274 if (!u)
275 return 0;
276
8a188de9 277 r = mac_selinux_unit_access_check(u, message, verb, error);
969987ea
LP
278 if (r < 0)
279 return r;
280
281 return 0;
282}
ad5b215d 283#endif
969987ea 284
f00c3121 285static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
286 Manager *m = userdata;
287 Job *j;
288 int r;
ea430986 289
718db961
LP
290 assert(bus);
291 assert(path);
292 assert(interface);
293 assert(found);
ea430986
LP
294 assert(m);
295
718db961
LP
296 r = manager_get_job_from_dbus_path(m, path, &j);
297 if (r < 0)
298 return 0;
ea430986 299
718db961
LP
300 *found = j;
301 return 1;
302}
ea430986 303
f00c3121 304static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
a8cfb1b3 305 Unit *u = NULL; /* just to appease gcc, initialization is not really necessary */
718db961 306 int r;
ea430986 307
718db961
LP
308 assert(m);
309 assert(bus);
310 assert(path);
ea430986 311
718db961 312 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
4afd3348 313 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
718db961
LP
314 sd_bus_message *message;
315 pid_t pid;
ea430986 316
19befb2d 317 message = sd_bus_get_current_message(bus);
718db961 318 if (!message)
f00c3121 319 return 0;
ea430986 320
5b12334d 321 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
718db961 322 if (r < 0)
5b12334d
LP
323 return r;
324
325 r = sd_bus_creds_get_pid(creds, &pid);
326 if (r < 0)
327 return r;
ea430986 328
718db961 329 u = manager_get_unit_by_pid(m, pid);
a8cfb1b3
ZJS
330 if (!u)
331 return 0;
718db961 332 } else {
f00c3121 333 r = manager_load_unit_from_dbus_path(m, path, error, &u);
718db961 334 if (r < 0)
f00c3121 335 return 0;
a8cfb1b3 336 assert(u);
718db961 337 }
ea430986 338
f00c3121
LP
339 *unit = u;
340 return 1;
ea430986
LP
341}
342
f00c3121 343static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961 344 Manager *m = userdata;
ea430986 345
718db961
LP
346 assert(bus);
347 assert(path);
348 assert(interface);
349 assert(found);
ea430986
LP
350 assert(m);
351
f00c3121 352 return find_unit(m, bus, path, (Unit**) found, error);
ea430986
LP
353}
354
f00c3121 355static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
356 Manager *m = userdata;
357 Unit *u;
f00c3121 358 int r;
ea430986 359
718db961
LP
360 assert(bus);
361 assert(path);
362 assert(interface);
363 assert(found);
ea430986
LP
364 assert(m);
365
f00c3121
LP
366 r = find_unit(m, bus, path, &u, error);
367 if (r <= 0)
368 return r;
3df5bf61 369
21b735e7 370 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 371 return 0;
ea430986 372
718db961
LP
373 *found = u;
374 return 1;
ea430986
LP
375}
376
f00c3121 377static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
378 Manager *m = userdata;
379 Unit *u;
f00c3121 380 int r;
c1e1601e 381
718db961
LP
382 assert(bus);
383 assert(path);
384 assert(interface);
385 assert(found);
c1e1601e
LP
386 assert(m);
387
f00c3121
LP
388 r = find_unit(m, bus, path, &u, error);
389 if (r <= 0)
390 return r;
05e343b7 391
21b735e7 392 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 393 return 0;
05e343b7 394
35b7ff80 395 if (!UNIT_HAS_CGROUP_CONTEXT(u))
718db961 396 return 0;
0034c15c 397
718db961
LP
398 *found = u;
399 return 1;
400}
0034c15c 401
f00c3121 402static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
403 Manager *m = userdata;
404 CGroupContext *c;
405 Unit *u;
f00c3121 406 int r;
af25ec12 407
718db961
LP
408 assert(bus);
409 assert(path);
410 assert(interface);
411 assert(found);
412 assert(m);
0034c15c 413
f00c3121
LP
414 r = find_unit(m, bus, path, &u, error);
415 if (r <= 0)
416 return r;
0034c15c 417
21b735e7 418 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 419 return 0;
0034c15c 420
718db961
LP
421 c = unit_get_cgroup_context(u);
422 if (!c)
423 return 0;
c1e1601e 424
718db961
LP
425 *found = c;
426 return 1;
427}
0034c15c 428
f00c3121 429static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
430 Manager *m = userdata;
431 ExecContext *c;
432 Unit *u;
f00c3121 433 int r;
0034c15c 434
718db961
LP
435 assert(bus);
436 assert(path);
437 assert(interface);
438 assert(found);
439 assert(m);
0034c15c 440
f00c3121
LP
441 r = find_unit(m, bus, path, &u, error);
442 if (r <= 0)
443 return r;
0034c15c 444
21b735e7 445 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 446 return 0;
0034c15c 447
718db961
LP
448 c = unit_get_exec_context(u);
449 if (!c)
450 return 0;
0034c15c 451
718db961
LP
452 *found = c;
453 return 1;
c1e1601e
LP
454}
455
f00c3121 456static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
457 Manager *m = userdata;
458 KillContext *c;
459 Unit *u;
f00c3121 460 int r;
8e274523 461
718db961
LP
462 assert(bus);
463 assert(path);
464 assert(interface);
465 assert(found);
8e274523
LP
466 assert(m);
467
f00c3121
LP
468 r = find_unit(m, bus, path, &u, error);
469 if (r <= 0)
470 return r;
8e274523 471
21b735e7 472 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 473 return 0;
8e274523 474
718db961
LP
475 c = unit_get_kill_context(u);
476 if (!c)
477 return 0;
53c6a358 478
718db961
LP
479 *found = c;
480 return 1;
481}
8e274523 482
f00c3121 483static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
f0c03de8 484 _cleanup_strv_free_ char **l = NULL;
718db961
LP
485 Manager *m = userdata;
486 unsigned k = 0;
487 Iterator i;
488 Job *j;
8e274523 489
718db961
LP
490 l = new0(char*, hashmap_size(m->jobs)+1);
491 if (!l)
492 return -ENOMEM;
8e274523 493
718db961
LP
494 HASHMAP_FOREACH(j, m->jobs, i) {
495 l[k] = job_dbus_path(j);
496 if (!l[k])
497 return -ENOMEM;
5e8d1c9a 498
718db961
LP
499 k++;
500 }
5e8d1c9a 501
718db961 502 assert(hashmap_size(m->jobs) == k);
3c661fad 503
718db961
LP
504 *nodes = l;
505 l = NULL;
5e8d1c9a 506
718db961
LP
507 return k;
508}
53c6a358 509
f00c3121 510static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
f0c03de8 511 _cleanup_strv_free_ char **l = NULL;
718db961
LP
512 Manager *m = userdata;
513 unsigned k = 0;
514 Iterator i;
515 Unit *u;
3c661fad 516
718db961
LP
517 l = new0(char*, hashmap_size(m->units)+1);
518 if (!l)
519 return -ENOMEM;
53c6a358 520
718db961
LP
521 HASHMAP_FOREACH(u, m->units, i) {
522 l[k] = unit_dbus_path(u);
523 if (!l[k])
524 return -ENOMEM;
53c6a358 525
718db961 526 k++;
3c661fad
LP
527 }
528
718db961
LP
529 *nodes = l;
530 l = NULL;
5e8d1c9a 531
718db961 532 return k;
5e8d1c9a
LP
533}
534
718db961
LP
535static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
536 UnitType t;
537 int r;
5e8d1c9a 538
ea430986 539 assert(m);
718db961 540 assert(bus);
ea430986 541
349cc4a5 542#if HAVE_SELINUX
8a188de9 543 r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
23bbb0de
MS
544 if (r < 0)
545 return log_error_errno(r, "Failed to add SELinux access filter: %m");
ad5b215d 546#endif
969987ea 547
19befb2d 548 r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
23bbb0de
MS
549 if (r < 0)
550 return log_error_errno(r, "Failed to register Manager vtable: %m");
a16e1123 551
19befb2d 552 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
23bbb0de
MS
553 if (r < 0)
554 return log_error_errno(r, "Failed to register Job vtable: %m");
c1e1601e 555
19befb2d 556 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
23bbb0de
MS
557 if (r < 0)
558 return log_error_errno(r, "Failed to add job enumerator: %m");
61902ea3 559
19befb2d 560 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
23bbb0de
MS
561 if (r < 0)
562 return log_error_errno(r, "Failed to register Unit vtable: %m");
61902ea3 563
19befb2d 564 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
23bbb0de
MS
565 if (r < 0)
566 return log_error_errno(r, "Failed to add job enumerator: %m");
61902ea3 567
718db961 568 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
21b735e7
LP
569 const char *interface;
570
571 assert_se(interface = unit_dbus_interface_from_type(t));
572
573 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
23bbb0de 574 if (r < 0)
21b735e7 575 return log_error_errno(r, "Failed to register type specific vtable for %s: %m", interface);
61902ea3 576
718db961 577 if (unit_vtable[t]->cgroup_context_offset > 0) {
21b735e7 578 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
23bbb0de 579 if (r < 0)
21b735e7 580 return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", interface);
61902ea3 581
21b735e7 582 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
23bbb0de 583 if (r < 0)
21b735e7 584 return log_error_errno(r, "Failed to register control group vtable for %s: %m", interface);
61902ea3
LP
585 }
586
718db961 587 if (unit_vtable[t]->exec_context_offset > 0) {
21b735e7 588 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_exec_vtable, bus_exec_context_find, m);
23bbb0de 589 if (r < 0)
21b735e7 590 return log_error_errno(r, "Failed to register execute vtable for %s: %m", interface);
718db961 591 }
61902ea3 592
718db961 593 if (unit_vtable[t]->kill_context_offset > 0) {
21b735e7 594 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_kill_vtable, bus_kill_context_find, m);
23bbb0de 595 if (r < 0)
21b735e7 596 return log_error_errno(r, "Failed to register kill vtable for %s: %m", interface);
718db961 597 }
61902ea3
LP
598 }
599
718db961 600 return 0;
61902ea3
LP
601}
602
718db961
LP
603static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
604 int r;
61902ea3 605
718db961
LP
606 assert(m);
607 assert(bus);
61902ea3 608
75152a4d 609 r = sd_bus_match_signal_async(
718db961 610 bus,
19befb2d 611 NULL,
75152a4d
LP
612 "org.freedesktop.DBus.Local",
613 "/org/freedesktop/DBus/Local",
614 "org.freedesktop.DBus.Local",
615 "Disconnected",
616 signal_disconnected, NULL, m);
23bbb0de 617 if (r < 0)
75152a4d 618 return log_error_errno(r, "Failed to request match for Disconnected message: %m");
05e343b7 619
718db961 620 return 0;
ea430986
LP
621}
622
718db961 623static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
4afd3348 624 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
718db961 625 _cleanup_close_ int nfd = -1;
6dded4c7 626 Manager *m = userdata;
718db961
LP
627 sd_id128_t id;
628 int r;
6dded4c7 629
718db961 630 assert(s);
6dded4c7
LP
631 assert(m);
632
718db961
LP
633 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
634 if (nfd < 0) {
56f64d95 635 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
718db961
LP
636 return 0;
637 }
6dded4c7 638
718db961
LP
639 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
640 log_warning("Too many concurrent connections, refusing");
641 return 0;
642 }
6dded4c7 643
d5099efc 644 r = set_ensure_allocated(&m->private_buses, NULL);
718db961
LP
645 if (r < 0) {
646 log_oom();
647 return 0;
648 }
6dded4c7 649
718db961
LP
650 r = sd_bus_new(&bus);
651 if (r < 0) {
da927ba9 652 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
718db961
LP
653 return 0;
654 }
6dded4c7 655
030fa56c
LP
656 (void) sd_bus_set_description(bus, "private-bus-connection");
657
718db961
LP
658 r = sd_bus_set_fd(bus, nfd, nfd);
659 if (r < 0) {
da927ba9 660 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
718db961
LP
661 return 0;
662 }
6dded4c7 663
718db961 664 nfd = -1;
6dded4c7 665
718db961
LP
666 r = bus_check_peercred(bus);
667 if (r < 0) {
da927ba9 668 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
718db961
LP
669 return 0;
670 }
6dded4c7 671
718db961 672 assert_se(sd_id128_randomize(&id) >= 0);
6dded4c7 673
718db961
LP
674 r = sd_bus_set_server(bus, 1, id);
675 if (r < 0) {
da927ba9 676 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
718db961
LP
677 return 0;
678 }
6dded4c7 679
0674bbea
LP
680 r = sd_bus_negotiate_creds(bus, 1,
681 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
682 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
683 SD_BUS_CREDS_SELINUX_CONTEXT);
684 if (r < 0) {
685 log_warning_errno(r, "Failed to enable credentials for new connection: %m");
686 return 0;
687 }
688
a5ea30b7
LP
689 r = sd_bus_set_sender(bus, "org.freedesktop.systemd1");
690 if (r < 0) {
691 log_warning_errno(r, "Failed to set direct connection sender: %m");
692 return 0;
693 }
694
718db961
LP
695 r = sd_bus_start(bus);
696 if (r < 0) {
da927ba9 697 log_warning_errno(r, "Failed to start new connection bus: %m");
718db961 698 return 0;
6dded4c7
LP
699 }
700
718db961
LP
701 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
702 if (r < 0) {
da927ba9 703 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
718db961 704 return 0;
6dded4c7
LP
705 }
706
718db961
LP
707 r = bus_setup_disconnected_match(m, bus);
708 if (r < 0)
709 return 0;
6dded4c7 710
718db961
LP
711 r = bus_setup_api_vtables(m, bus);
712 if (r < 0) {
da927ba9 713 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
718db961
LP
714 return 0;
715 }
6dded4c7 716
718db961
LP
717 r = set_put(m->private_buses, bus);
718 if (r < 0) {
05a08cb6 719 log_warning_errno(r, "Failed to add new connection bus to set: %m");
718db961 720 return 0;
6dded4c7
LP
721 }
722
718db961 723 bus = NULL;
6dded4c7 724
718db961 725 log_debug("Accepted new private connection.");
6dded4c7 726
8e274523
LP
727 return 0;
728}
729
5f109056 730static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata) {
0e7be129 731 _cleanup_strv_free_ char **names = NULL;
5f109056 732 Manager *m = userdata;
d8ccf5fd
DM
733 const char *name;
734 Iterator i;
735 Unit *u;
718db961 736 int r;
5e8d1c9a 737
5f109056 738 assert(es);
5e8d1c9a 739 assert(m);
5f109056
LP
740 assert(m->sync_bus_names_event_source == es);
741
742 /* First things first, destroy the defer event so that we aren't triggered again */
743 m->sync_bus_names_event_source = sd_event_source_unref(m->sync_bus_names_event_source);
744
745 /* Let's see if there's anything to do still? */
746 if (!m->api_bus)
747 return 0;
748 if (hashmap_isempty(m->watch_bus))
749 return 0;
5e8d1c9a 750
5f109056
LP
751 /* OK, let's sync up the names. Let's see which names are currently on the bus. */
752 r = sd_bus_list_names(m->api_bus, &names, NULL);
23bbb0de
MS
753 if (r < 0)
754 return log_error_errno(r, "Failed to get initial list of names: %m");
5e8d1c9a 755
d8ccf5fd
DM
756 /* We have to synchronize the current bus names with the
757 * list of active services. To do this, walk the list of
758 * all units with bus names. */
759 HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
760 Service *s = SERVICE(u);
761
762 assert(s);
bbc29086 763
d8ccf5fd
DM
764 if (!streq_ptr(s->bus_name, name)) {
765 log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name);
766 continue;
767 }
768
769 /* Check if a service's bus name is in the list of currently
770 * active names */
771 if (strv_contains(names, name)) {
772 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
773 const char *unique;
774
775 /* If it is, determine its current owner */
5f109056 776 r = sd_bus_get_name_creds(m->api_bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds);
d8ccf5fd 777 if (r < 0) {
ddbf0d4b 778 log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name);
d8ccf5fd
DM
779 continue;
780 }
781
782 r = sd_bus_creds_get_unique_name(creds, &unique);
783 if (r < 0) {
ddbf0d4b 784 log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name);
d8ccf5fd
DM
785 continue;
786 }
787
788 /* Now, let's compare that to the previous bus owner, and
789 * if it's still the same, all is fine, so just don't
790 * bother the service. Otherwise, the name has apparently
791 * changed, so synthesize a name owner changed signal. */
792
793 if (!streq_ptr(unique, s->bus_name_owner))
794 UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, unique);
795 } else {
796 /* So, the name we're watching is not on the bus.
797 * This either means it simply hasn't appeared yet,
798 * or it was lost during the daemon reload.
799 * Check if the service has a stored name owner,
800 * and synthesize a name loss signal in this case. */
801
802 if (s->bus_name_owner)
803 UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, NULL);
804 }
bbc29086 805 }
5e8d1c9a 806
718db961 807 return 0;
5e8d1c9a
LP
808}
809
5f109056
LP
810int manager_enqueue_sync_bus_names(Manager *m) {
811 int r;
812
813 assert(m);
814
815 /* Enqueues a request to synchronize the bus names in a later event loop iteration. The callers generally don't
816 * want us to invoke ->bus_name_owner_change() unit calls from their stack frames as this might result in event
817 * dispatching on its own creating loops, hence we simply create a defer event for the event loop and exit. */
818
819 if (m->sync_bus_names_event_source)
820 return 0;
821
822 r = sd_event_add_defer(m->event, &m->sync_bus_names_event_source, manager_dispatch_sync_bus_names, m);
823 if (r < 0)
824 return log_error_errno(r, "Failed to create bus name synchronization event: %m");
825
826 r = sd_event_source_set_priority(m->sync_bus_names_event_source, SD_EVENT_PRIORITY_IDLE);
827 if (r < 0)
828 return log_error_errno(r, "Failed to set event priority: %m");
829
830 r = sd_event_source_set_enabled(m->sync_bus_names_event_source, SD_EVENT_ONESHOT);
831 if (r < 0)
832 return log_error_errno(r, "Failed to set even to oneshot: %m");
833
834 (void) sd_event_source_set_description(m->sync_bus_names_event_source, "manager-sync-bus-names");
835 return 0;
836}
837
718db961 838static int bus_setup_api(Manager *m, sd_bus *bus) {
bbc29086
DM
839 Iterator i;
840 char *name;
841 Unit *u;
718db961 842 int r;
f278026d 843
718db961
LP
844 assert(m);
845 assert(bus);
c1e1601e 846
8fd00193
LP
847 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
848 r = sd_bus_negotiate_creds(bus, 1,
849 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
850 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
851 SD_BUS_CREDS_SELINUX_CONTEXT);
852 if (r < 0)
da927ba9 853 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
8fd00193 854
718db961
LP
855 r = bus_setup_api_vtables(m, bus);
856 if (r < 0)
857 return r;
cbd37330 858
bbc29086 859 HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
9806e87d 860 r = unit_install_bus_match(u, bus, name);
bbc29086 861 if (r < 0)
8ea823b6 862 log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
bbc29086 863 }
718db961 864
75152a4d 865 r = sd_bus_match_signal_async(
718db961 866 bus,
19befb2d 867 NULL,
75152a4d
LP
868 "org.freedesktop.DBus",
869 "/org/freedesktop/DBus",
870 "org.freedesktop.systemd1.Activator",
871 "ActivationRequest",
872 signal_activation_request, NULL, m);
718db961 873 if (r < 0)
da927ba9 874 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
cbd37330 875
0c0b9306
LP
876 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
877 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
878 * reexecution to finish */
879 r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT, NULL, NULL);
23bbb0de 880 if (r < 0)
0c0b9306 881 return log_error_errno(r, "Failed to request name: %m");
53c6a358 882
718db961 883 log_debug("Successfully connected to API bus.");
5f109056 884
f278026d
LP
885 return 0;
886}
887
8559b3b7 888int bus_init_api(Manager *m) {
4afd3348 889 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
f278026d
LP
890 int r;
891
718db961
LP
892 if (m->api_bus)
893 return 0;
cbd37330 894
718db961 895 /* The API and system bus is the same if we are running in system mode */
463d0d15 896 if (MANAGER_IS_SYSTEM(m) && m->system_bus)
718db961
LP
897 bus = sd_bus_ref(m->system_bus);
898 else {
463d0d15 899 if (MANAGER_IS_SYSTEM(m))
718db961
LP
900 r = sd_bus_open_system(&bus);
901 else
902 r = sd_bus_open_user(&bus);
dc7118ba
MS
903 if (r < 0)
904 return log_error_errno(r, "Failed to connect to API bus: %m");
cbd37330 905
718db961 906 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
dc7118ba
MS
907 if (r < 0)
908 return log_error_errno(r, "Failed to attach API bus to event loop: %m");
cbd37330 909
718db961
LP
910 r = bus_setup_disconnected_match(m, bus);
911 if (r < 0)
dc7118ba 912 return r;
cbd37330
MS
913 }
914
718db961 915 r = bus_setup_api(m, bus);
dc7118ba
MS
916 if (r < 0)
917 return log_error_errno(r, "Failed to set up API bus: %m");
cbd37330 918
718db961
LP
919 m->api_bus = bus;
920 bus = NULL;
cbd37330 921
5f109056
LP
922 r = manager_enqueue_sync_bus_names(m);
923 if (r < 0)
924 return r;
925
cbd37330 926 return 0;
cbd37330
MS
927}
928
718db961
LP
929static int bus_setup_system(Manager *m, sd_bus *bus) {
930 int r;
cbd37330 931
718db961
LP
932 assert(m);
933 assert(bus);
cbd37330 934
d8fdc620
LP
935 /* if we are a user instance we get the Released message via the system bus */
936 if (MANAGER_IS_USER(m)) {
75152a4d 937 r = sd_bus_match_signal_async(
f5b51ea7
DH
938 bus,
939 NULL,
75152a4d
LP
940 NULL,
941 "/org/freedesktop/systemd1/agent",
942 "org.freedesktop.systemd1.Agent",
943 "Released",
944 signal_agent_released, NULL, m);
f5b51ea7 945 if (r < 0)
75152a4d 946 log_warning_errno(r, "Failed to request Released match on system bus: %m");
f5b51ea7 947 }
718db961
LP
948
949 log_debug("Successfully connected to system bus.");
950 return 0;
cbd37330
MS
951}
952
8559b3b7 953int bus_init_system(Manager *m) {
4afd3348 954 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
cbd37330
MS
955 int r;
956
957 if (m->system_bus)
958 return 0;
959
718db961 960 /* The API and system bus is the same if we are running in system mode */
931e4754
LP
961 if (MANAGER_IS_SYSTEM(m) && m->api_bus)
962 bus = sd_bus_ref(m->api_bus);
963 else {
964 r = sd_bus_open_system(&bus);
965 if (r < 0)
966 return log_error_errno(r, "Failed to connect to system bus: %m");
cbd37330 967
931e4754
LP
968 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
969 if (r < 0)
970 return log_error_errno(r, "Failed to attach system bus to event loop: %m");
cbd37330 971
931e4754
LP
972 r = bus_setup_disconnected_match(m, bus);
973 if (r < 0)
974 return r;
975 }
cbd37330 976
718db961 977 r = bus_setup_system(m, bus);
dc7118ba
MS
978 if (r < 0)
979 return log_error_errno(r, "Failed to set up system bus: %m");
cbd37330 980
718db961
LP
981 m->system_bus = bus;
982 bus = NULL;
cbd37330
MS
983
984 return 0;
5e8d1c9a
LP
985}
986
8559b3b7 987int bus_init_private(Manager *m) {
718db961
LP
988 _cleanup_close_ int fd = -1;
989 union sockaddr_union sa = {
990 .un.sun_family = AF_UNIX
5e8d1c9a 991 };
718db961
LP
992 sd_event_source *s;
993 socklen_t salen;
994 int r;
5e8d1c9a
LP
995
996 assert(m);
997
718db961 998 if (m->private_listen_fd >= 0)
5e8d1c9a
LP
999 return 0;
1000
463d0d15 1001 if (MANAGER_IS_SYSTEM(m)) {
be81bfc4
LP
1002
1003 /* We want the private bus only when running as init */
df0ff127 1004 if (getpid_cached() != 1)
be81bfc4
LP
1005 return 0;
1006
718db961 1007 strcpy(sa.un.sun_path, "/run/systemd/private");
fc2fffe7 1008 salen = SOCKADDR_UN_LEN(sa.un);
be81bfc4 1009 } else {
718db961
LP
1010 size_t left = sizeof(sa.un.sun_path);
1011 char *p = sa.un.sun_path;
be81bfc4 1012 const char *e;
be81bfc4 1013
4db17f29 1014 e = secure_getenv("XDG_RUNTIME_DIR");
718db961
LP
1015 if (!e) {
1016 log_error("Failed to determine XDG_RUNTIME_DIR");
1017 return -EHOSTDOWN;
be81bfc4
LP
1018 }
1019
718db961
LP
1020 left = strpcpy(&p, left, e);
1021 left = strpcpy(&p, left, "/systemd/private");
92f30349 1022
718db961 1023 salen = sizeof(sa.un) - left;
be81bfc4 1024 }
5e8d1c9a 1025
f0e62e89
LP
1026 (void) mkdir_parents_label(sa.un.sun_path, 0755);
1027 (void) unlink(sa.un.sun_path);
718db961
LP
1028
1029 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
4a62c710
MS
1030 if (fd < 0)
1031 return log_error_errno(errno, "Failed to allocate private socket: %m");
5e8d1c9a 1032
718db961 1033 r = bind(fd, &sa.sa, salen);
4a62c710
MS
1034 if (r < 0)
1035 return log_error_errno(errno, "Failed to bind private socket: %m");
5e8d1c9a 1036
718db961 1037 r = listen(fd, SOMAXCONN);
4a62c710
MS
1038 if (r < 0)
1039 return log_error_errno(errno, "Failed to make private socket listening: %m");
5e8d1c9a 1040
5b5e6dea
LP
1041 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
1042 (void) touch(sa.un.sun_path);
1043
151b9b96 1044 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
23bbb0de
MS
1045 if (r < 0)
1046 return log_error_errno(r, "Failed to allocate event source: %m");
5e8d1c9a 1047
7dfbe2e3
TG
1048 (void) sd_event_source_set_description(s, "bus-connection");
1049
718db961
LP
1050 m->private_listen_fd = fd;
1051 m->private_listen_event_source = s;
1052 fd = -1;
5e8d1c9a 1053
718db961 1054 log_debug("Successfully created private D-Bus server.");
5e8d1c9a 1055
718db961 1056 return 0;
5e8d1c9a
LP
1057}
1058
718db961 1059static void destroy_bus(Manager *m, sd_bus **bus) {
a567261a 1060 Iterator i;
8367fea5 1061 Unit *u;
718db961 1062 Job *j;
a567261a 1063
718db961
LP
1064 assert(m);
1065 assert(bus);
5e8d1c9a 1066
718db961 1067 if (!*bus)
cbd37330 1068 return;
f278026d 1069
8367fea5
LP
1070 /* Make sure all bus slots watching names are released. */
1071 HASHMAP_FOREACH(u, m->watch_bus, i) {
1072 if (!u->match_bus_slot)
1073 continue;
1074
1075 if (sd_bus_slot_get_bus(u->match_bus_slot) != *bus)
1076 continue;
1077
1078 u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
1079 }
1080
718db961 1081 /* Get rid of tracked clients on this bus */
8f8f05a9
LP
1082 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1083 m->subscribed = sd_bus_track_unref(m->subscribed);
1084
718db961 1085 HASHMAP_FOREACH(j, m->jobs, i)
1a465207
LP
1086 if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
1087 j->bus_track = sd_bus_track_unref(j->bus_track);
c1e1601e 1088
dfeff664
LP
1089 HASHMAP_FOREACH(u, m->units, i)
1090 if (u->bus_track && sd_bus_track_get_bus(u->bus_track) == *bus)
1091 u->bus_track = sd_bus_track_unref(u->bus_track);
1092
718db961 1093 /* Get rid of queued message on this bus */
8f88ecf6
LP
1094 if (m->queued_message && sd_bus_message_get_bus(m->queued_message) == *bus)
1095 m->queued_message = sd_bus_message_unref(m->queued_message);
f278026d 1096
718db961
LP
1097 /* Possibly flush unwritten data, but only if we are
1098 * unprivileged, since we don't want to sync here */
463d0d15 1099 if (!MANAGER_IS_SYSTEM(m))
718db961 1100 sd_bus_flush(*bus);
5e8d1c9a 1101
718db961
LP
1102 /* And destroy the object */
1103 sd_bus_close(*bus);
1104 *bus = sd_bus_unref(*bus);
5e8d1c9a
LP
1105}
1106
4502c403 1107void bus_done_api(Manager *m) {
05e343b7 1108 assert(m);
05e343b7 1109
718db961
LP
1110 if (m->api_bus)
1111 destroy_bus(m, &m->api_bus);
4502c403
LP
1112}
1113
1114void bus_done_system(Manager *m) {
1115 assert(m);
1116
718db961
LP
1117 if (m->system_bus)
1118 destroy_bus(m, &m->system_bus);
4502c403
LP
1119}
1120
1121void bus_done_private(Manager *m) {
1122 sd_bus *b;
1123
1124 assert(m);
1125
718db961
LP
1126 while ((b = set_steal_first(m->private_buses)))
1127 destroy_bus(m, &b);
05e343b7 1128
525d3cc7 1129 m->private_buses = set_free(m->private_buses);
8f8f05a9 1130
4502c403
LP
1131 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1132 m->private_listen_fd = safe_close(m->private_listen_fd);
1133}
1134
1135void bus_done(Manager *m) {
1136 assert(m);
05e343b7 1137
4502c403
LP
1138 bus_done_api(m);
1139 bus_done_system(m);
1140 bus_done_private(m);
05e343b7 1141
4502c403 1142 assert(!m->subscribed);
283868e1 1143
4502c403 1144 m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
283868e1 1145 bus_verify_polkit_async_registry_free(m->polkit_registry);
a567261a 1146}
b23de6af
LP
1147
1148int bus_fdset_add_all(Manager *m, FDSet *fds) {
1149 Iterator i;
718db961
LP
1150 sd_bus *b;
1151 int fd;
b23de6af
LP
1152
1153 assert(m);
1154 assert(fds);
1155
1156 /* When we are about to reexecute we add all D-Bus fds to the
1157 * set to pass over to the newly executed systemd. They won't
718db961 1158 * be used there however, except thatt they are closed at the
b23de6af 1159 * very end of deserialization, those making it possible for
44143309 1160 * clients to synchronously wait for systemd to reexec by
b23de6af
LP
1161 * simply waiting for disconnection */
1162
718db961
LP
1163 if (m->api_bus) {
1164 fd = sd_bus_get_fd(m->api_bus);
1165 if (fd >= 0) {
b23de6af 1166 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1167 if (fd < 0)
1168 return fd;
1169 }
1170 }
1171
718db961
LP
1172 SET_FOREACH(b, m->private_buses, i) {
1173 fd = sd_bus_get_fd(b);
1174 if (fd >= 0) {
b23de6af 1175 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1176 if (fd < 0)
1177 return fd;
1178 }
1179 }
1180
718db961
LP
1181 /* We don't offer any APIs on the system bus (well, unless it
1182 * is the same as the API bus) hence we don't bother with it
1183 * here */
6fa48533 1184
718db961 1185 return 0;
6fa48533
LP
1186}
1187
8f8f05a9
LP
1188int bus_foreach_bus(
1189 Manager *m,
1190 sd_bus_track *subscribed2,
1191 int (*send_message)(sd_bus *bus, void *userdata),
1192 void *userdata) {
1193
1194 Iterator i;
1195 sd_bus *b;
1196 int r, ret = 0;
1197
ff9b60f3 1198 /* Send to all direct buses, unconditionally */
8f8f05a9 1199 SET_FOREACH(b, m->private_buses, i) {
9fc677e3
LP
1200
1201 /* Don't bother with enqueing these messages to clients that haven't started yet */
1202 if (sd_bus_is_ready(b) <= 0)
1203 continue;
1204
8f8f05a9
LP
1205 r = send_message(b, userdata);
1206 if (r < 0)
1207 ret = r;
1208 }
1209
1210 /* Send to API bus, but only if somebody is subscribed */
6edd281c
LP
1211 if (m->api_bus &&
1212 (sd_bus_track_count(m->subscribed) > 0 ||
1213 sd_bus_track_count(subscribed2) > 0)) {
8f8f05a9
LP
1214 r = send_message(m->api_bus, userdata);
1215 if (r < 0)
1216 ret = r;
1217 }
1218
1219 return ret;
1220}
1221
05a98afd 1222void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
8f8f05a9
LP
1223 const char *n;
1224
6fa48533 1225 assert(f);
05a98afd 1226 assert(prefix);
6fa48533 1227
05a98afd
LP
1228 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
1229 int c, j;
230314d7 1230
05a98afd 1231 c = sd_bus_track_count_name(t, n);
8f8f05a9 1232
05a98afd
LP
1233 for (j = 0; j < c; j++) {
1234 fputs(prefix, f);
1235 fputc('=', f);
1236 fputs(n, f);
1237 fputc('\n', f);
1238 }
1239 }
8f8f05a9
LP
1240}
1241
05a98afd 1242int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) {
8f8f05a9
LP
1243 int r = 0;
1244
1245 assert(m);
1246 assert(t);
8f8f05a9 1247
05a98afd
LP
1248 if (strv_isempty(l))
1249 return 0;
8f8f05a9 1250
05a98afd
LP
1251 if (!m->api_bus)
1252 return 0;
8f8f05a9 1253
05a98afd
LP
1254 if (!*t) {
1255 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1256 if (r < 0)
1257 return r;
8f8f05a9
LP
1258 }
1259
05a98afd
LP
1260 r = sd_bus_track_set_recursive(*t, recursive);
1261 if (r < 0)
1262 return r;
1263
984794ba 1264 return bus_track_add_name_many(*t, l);
6fa48533 1265}
283868e1 1266
1d22e906 1267int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1268 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1
SW
1269}
1270
283868e1 1271int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1272 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1
SW
1273}
1274
1275int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1276 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1 1277}
1d22e906
LP
1278
1279int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1280 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error);
1d22e906 1281}
e0a08581
LP
1282
1283uint64_t manager_bus_n_queued_write(Manager *m) {
1284 uint64_t c = 0;
1285 Iterator i;
1286 sd_bus *b;
1287 int r;
1288
1289 /* Returns the total number of messages queued for writing on all our direct and API busses. */
1290
1291 SET_FOREACH(b, m->private_buses, i) {
1292 uint64_t k;
1293
1294 r = sd_bus_get_n_queued_write(b, &k);
1295 if (r < 0)
1296 log_debug_errno(r, "Failed to query queued messages for private bus: %m");
1297 else
1298 c += k;
1299 }
1300
1301 if (m->api_bus) {
1302 uint64_t k;
1303
1304 r = sd_bus_get_n_queued_write(m->api_bus, &k);
1305 if (r < 0)
1306 log_debug_errno(r, "Failed to query queued messages for API bus: %m");
1307 else
1308 c += k;
1309 }
1310
1311 return c;
1312}