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