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