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