]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus.c
core/unit: reduce scope of variables
[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 find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
a8cfb1b3 278 Unit *u = NULL; /* just to appease gcc, initialization is not really necessary */
718db961 279 int r;
ea430986 280
718db961
LP
281 assert(m);
282 assert(bus);
283 assert(path);
ea430986 284
718db961 285 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
4afd3348 286 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
718db961
LP
287 sd_bus_message *message;
288 pid_t pid;
ea430986 289
19befb2d 290 message = sd_bus_get_current_message(bus);
718db961 291 if (!message)
f00c3121 292 return 0;
ea430986 293
5b12334d 294 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
718db961 295 if (r < 0)
5b12334d
LP
296 return r;
297
298 r = sd_bus_creds_get_pid(creds, &pid);
299 if (r < 0)
300 return r;
ea430986 301
718db961 302 u = manager_get_unit_by_pid(m, pid);
a8cfb1b3
ZJS
303 if (!u)
304 return 0;
718db961 305 } else {
f00c3121 306 r = manager_load_unit_from_dbus_path(m, path, error, &u);
718db961 307 if (r < 0)
f00c3121 308 return 0;
a8cfb1b3 309 assert(u);
718db961 310 }
ea430986 311
f00c3121
LP
312 *unit = u;
313 return 1;
ea430986
LP
314}
315
f00c3121 316static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961 317 Manager *m = userdata;
ea430986 318
718db961
LP
319 assert(bus);
320 assert(path);
321 assert(interface);
322 assert(found);
ea430986
LP
323 assert(m);
324
f00c3121 325 return find_unit(m, bus, path, (Unit**) found, error);
ea430986
LP
326}
327
f00c3121 328static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
329 Manager *m = userdata;
330 Unit *u;
f00c3121 331 int r;
ea430986 332
718db961
LP
333 assert(bus);
334 assert(path);
335 assert(interface);
336 assert(found);
ea430986
LP
337 assert(m);
338
f00c3121
LP
339 r = find_unit(m, bus, path, &u, error);
340 if (r <= 0)
341 return r;
3df5bf61 342
21b735e7 343 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 344 return 0;
ea430986 345
718db961
LP
346 *found = u;
347 return 1;
ea430986
LP
348}
349
f00c3121 350static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
351 Manager *m = userdata;
352 Unit *u;
f00c3121 353 int r;
c1e1601e 354
718db961
LP
355 assert(bus);
356 assert(path);
357 assert(interface);
358 assert(found);
c1e1601e
LP
359 assert(m);
360
f00c3121
LP
361 r = find_unit(m, bus, path, &u, error);
362 if (r <= 0)
363 return r;
05e343b7 364
21b735e7 365 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 366 return 0;
05e343b7 367
35b7ff80 368 if (!UNIT_HAS_CGROUP_CONTEXT(u))
718db961 369 return 0;
0034c15c 370
718db961
LP
371 *found = u;
372 return 1;
373}
0034c15c 374
f00c3121 375static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
376 Manager *m = userdata;
377 CGroupContext *c;
378 Unit *u;
f00c3121 379 int r;
af25ec12 380
718db961
LP
381 assert(bus);
382 assert(path);
383 assert(interface);
384 assert(found);
385 assert(m);
0034c15c 386
f00c3121
LP
387 r = find_unit(m, bus, path, &u, error);
388 if (r <= 0)
389 return r;
0034c15c 390
21b735e7 391 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 392 return 0;
0034c15c 393
718db961
LP
394 c = unit_get_cgroup_context(u);
395 if (!c)
396 return 0;
c1e1601e 397
718db961
LP
398 *found = c;
399 return 1;
400}
0034c15c 401
f00c3121 402static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
403 Manager *m = userdata;
404 ExecContext *c;
405 Unit *u;
f00c3121 406 int r;
0034c15c 407
718db961
LP
408 assert(bus);
409 assert(path);
410 assert(interface);
411 assert(found);
412 assert(m);
0034c15c 413
f00c3121
LP
414 r = find_unit(m, bus, path, &u, error);
415 if (r <= 0)
416 return r;
0034c15c 417
21b735e7 418 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 419 return 0;
0034c15c 420
718db961
LP
421 c = unit_get_exec_context(u);
422 if (!c)
423 return 0;
0034c15c 424
718db961
LP
425 *found = c;
426 return 1;
c1e1601e
LP
427}
428
f00c3121 429static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
430 Manager *m = userdata;
431 KillContext *c;
432 Unit *u;
f00c3121 433 int r;
8e274523 434
718db961
LP
435 assert(bus);
436 assert(path);
437 assert(interface);
438 assert(found);
8e274523
LP
439 assert(m);
440
f00c3121
LP
441 r = find_unit(m, bus, path, &u, error);
442 if (r <= 0)
443 return r;
8e274523 444
21b735e7 445 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 446 return 0;
8e274523 447
718db961
LP
448 c = unit_get_kill_context(u);
449 if (!c)
450 return 0;
53c6a358 451
718db961
LP
452 *found = c;
453 return 1;
454}
8e274523 455
f00c3121 456static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
f0c03de8 457 _cleanup_strv_free_ char **l = NULL;
718db961
LP
458 Manager *m = userdata;
459 unsigned k = 0;
460 Iterator i;
461 Unit *u;
3c661fad 462
718db961
LP
463 l = new0(char*, hashmap_size(m->units)+1);
464 if (!l)
465 return -ENOMEM;
53c6a358 466
718db961
LP
467 HASHMAP_FOREACH(u, m->units, i) {
468 l[k] = unit_dbus_path(u);
469 if (!l[k])
470 return -ENOMEM;
53c6a358 471
718db961 472 k++;
3c661fad
LP
473 }
474
ae2a15bc 475 *nodes = TAKE_PTR(l);
5e8d1c9a 476
718db961 477 return k;
5e8d1c9a
LP
478}
479
f6e9aa9e
ZJS
480static const BusObjectImplementation unit_object = {
481 "/org/freedesktop/systemd1/unit",
482 "org.freedesktop.systemd1.Unit",
483 .fallback_vtables = BUS_FALLBACK_VTABLES(
484 { bus_unit_vtable, bus_unit_find }),
485 .node_enumerator = bus_unit_enumerate,
486};
487
488static const BusObjectImplementation bus_automount_object = {
489 "/org/freedesktop/systemd1/unit",
490 "org.freedesktop.systemd1.Automount",
491 .fallback_vtables = BUS_FALLBACK_VTABLES(
492 { bus_automount_vtable, bus_unit_interface_find }),
493};
494
495static const BusObjectImplementation bus_device_object = {
496 "/org/freedesktop/systemd1/unit",
497 "org.freedesktop.systemd1.Device",
498 .fallback_vtables = BUS_FALLBACK_VTABLES(
499 { bus_device_vtable, bus_unit_interface_find }),
500};
501
502static const BusObjectImplementation bus_mount_object = {
503 "/org/freedesktop/systemd1/unit",
504 "org.freedesktop.systemd1.Mount",
505 .fallback_vtables = BUS_FALLBACK_VTABLES(
506 { bus_mount_vtable, bus_unit_interface_find },
507 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
508 { bus_cgroup_vtable, bus_cgroup_context_find },
509 { bus_exec_vtable, bus_exec_context_find },
510 { bus_kill_vtable, bus_kill_context_find }),
511};
512
513static const BusObjectImplementation bus_path_object = {
514 "/org/freedesktop/systemd1/unit",
515 "org.freedesktop.systemd1.Path",
516 .fallback_vtables = BUS_FALLBACK_VTABLES(
517 { bus_path_vtable, bus_unit_interface_find }),
518};
519
520static const BusObjectImplementation bus_scope_object = {
521 "/org/freedesktop/systemd1/unit",
522 "org.freedesktop.systemd1.Scope",
523 .fallback_vtables = BUS_FALLBACK_VTABLES(
524 { bus_scope_vtable, bus_unit_interface_find },
525 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
526 { bus_cgroup_vtable, bus_cgroup_context_find },
527 { bus_kill_vtable, bus_kill_context_find }),
528};
529
530static const BusObjectImplementation bus_service_object = {
531 "/org/freedesktop/systemd1/unit",
532 "org.freedesktop.systemd1.Service",
533 .fallback_vtables = BUS_FALLBACK_VTABLES(
534 { bus_service_vtable, bus_unit_interface_find },
535 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
536 { bus_cgroup_vtable, bus_cgroup_context_find },
537 { bus_exec_vtable, bus_exec_context_find },
538 { bus_kill_vtable, bus_kill_context_find }),
539};
540
541static const BusObjectImplementation bus_slice_object = {
542 "/org/freedesktop/systemd1/unit",
543 "org.freedesktop.systemd1.Slice",
544 .fallback_vtables = BUS_FALLBACK_VTABLES(
545 { bus_slice_vtable, bus_unit_interface_find },
546 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
547 { bus_cgroup_vtable, bus_cgroup_context_find }),
548};
549
550static const BusObjectImplementation bus_socket_object = {
551 "/org/freedesktop/systemd1/unit",
552 "org.freedesktop.systemd1.Socket",
553 .fallback_vtables = BUS_FALLBACK_VTABLES(
554 { bus_socket_vtable, bus_unit_interface_find },
555 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
556 { bus_cgroup_vtable, bus_cgroup_context_find },
557 { bus_exec_vtable, bus_exec_context_find },
558 { bus_kill_vtable, bus_kill_context_find }),
559};
560
561static const BusObjectImplementation bus_swap_object = {
562 "/org/freedesktop/systemd1/unit",
563 "org.freedesktop.systemd1.Swap",
564 .fallback_vtables = BUS_FALLBACK_VTABLES(
565 { bus_swap_vtable, bus_unit_interface_find },
566 { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
567 { bus_cgroup_vtable, bus_cgroup_context_find },
568 { bus_exec_vtable, bus_exec_context_find },
569 { bus_kill_vtable, bus_kill_context_find }),
570};
571
572static const BusObjectImplementation bus_target_object = {
573 "/org/freedesktop/systemd1/unit",
574 "org.freedesktop.systemd1.Target",
575 .fallback_vtables = BUS_FALLBACK_VTABLES(
576 { bus_target_vtable, bus_unit_interface_find }),
577};
578
579static const BusObjectImplementation bus_timer_object = {
580 "/org/freedesktop/systemd1/unit",
581 "org.freedesktop.systemd1.Timer",
582 .fallback_vtables = BUS_FALLBACK_VTABLES(
583 { bus_timer_vtable, bus_unit_interface_find }),
584};
585
586static const BusObjectImplementation bus_manager_object = {
587 "/org/freedesktop/systemd1",
588 "org.freedesktop.systemd1.Manager",
589 .vtables = BUS_VTABLES(bus_manager_vtable),
590 .children = BUS_IMPLEMENTATIONS(
591 &job_object,
592 &unit_object,
593 &bus_automount_object,
594 &bus_device_object,
595 &bus_mount_object,
596 &bus_path_object,
597 &bus_scope_object,
598 &bus_service_object,
599 &bus_slice_object,
600 &bus_socket_object,
601 &bus_swap_object,
602 &bus_target_object,
603 &bus_timer_object),
604};
605
606static const BusObjectImplementation manager_log_control_object = {
607 "/org/freedesktop/LogControl1",
608 "org.freedesktop.LogControl1",
609 .vtables = BUS_VTABLES(bus_manager_log_control_vtable),
610};
611
5c08257b
ZJS
612int bus_manager_introspect_implementations(FILE *out, const char *pattern) {
613 return bus_introspect_implementations(
614 out,
615 pattern,
616 BUS_IMPLEMENTATIONS(&bus_manager_object,
617 &manager_log_control_object));
618}
619
718db961 620static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
718db961 621 int r;
5e8d1c9a 622
ea430986 623 assert(m);
718db961 624 assert(bus);
ea430986 625
349cc4a5 626#if HAVE_SELINUX
8a188de9 627 r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
23bbb0de
MS
628 if (r < 0)
629 return log_error_errno(r, "Failed to add SELinux access filter: %m");
ad5b215d 630#endif
969987ea 631
f6e9aa9e 632 r = bus_add_implementation(bus, &bus_manager_object, m);
23bbb0de 633 if (r < 0)
f6e9aa9e 634 return r;
61902ea3 635
f6e9aa9e 636 return bus_add_implementation(bus, &manager_log_control_object, m);
61902ea3
LP
637}
638
718db961
LP
639static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
640 int r;
61902ea3 641
718db961
LP
642 assert(m);
643 assert(bus);
61902ea3 644
75152a4d 645 r = sd_bus_match_signal_async(
718db961 646 bus,
19befb2d 647 NULL,
75152a4d
LP
648 "org.freedesktop.DBus.Local",
649 "/org/freedesktop/DBus/Local",
650 "org.freedesktop.DBus.Local",
651 "Disconnected",
652 signal_disconnected, NULL, m);
23bbb0de 653 if (r < 0)
75152a4d 654 return log_error_errno(r, "Failed to request match for Disconnected message: %m");
05e343b7 655
718db961 656 return 0;
ea430986
LP
657}
658
718db961 659static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
bd62b744 660 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
718db961 661 _cleanup_close_ int nfd = -1;
6dded4c7 662 Manager *m = userdata;
718db961
LP
663 sd_id128_t id;
664 int r;
6dded4c7 665
718db961 666 assert(s);
6dded4c7
LP
667 assert(m);
668
718db961
LP
669 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
670 if (nfd < 0) {
4ff9bc2e
LP
671 if (ERRNO_IS_ACCEPT_AGAIN(errno))
672 return 0;
673
56f64d95 674 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
718db961
LP
675 return 0;
676 }
6dded4c7 677
718db961
LP
678 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
679 log_warning("Too many concurrent connections, refusing");
680 return 0;
681 }
6dded4c7 682
d5099efc 683 r = set_ensure_allocated(&m->private_buses, NULL);
718db961
LP
684 if (r < 0) {
685 log_oom();
686 return 0;
687 }
6dded4c7 688
718db961
LP
689 r = sd_bus_new(&bus);
690 if (r < 0) {
da927ba9 691 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
718db961
LP
692 return 0;
693 }
6dded4c7 694
030fa56c
LP
695 (void) sd_bus_set_description(bus, "private-bus-connection");
696
718db961
LP
697 r = sd_bus_set_fd(bus, nfd, nfd);
698 if (r < 0) {
da927ba9 699 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
718db961
LP
700 return 0;
701 }
6dded4c7 702
718db961 703 nfd = -1;
6dded4c7 704
718db961
LP
705 r = bus_check_peercred(bus);
706 if (r < 0) {
da927ba9 707 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
718db961
LP
708 return 0;
709 }
6dded4c7 710
718db961 711 assert_se(sd_id128_randomize(&id) >= 0);
6dded4c7 712
718db961
LP
713 r = sd_bus_set_server(bus, 1, id);
714 if (r < 0) {
da927ba9 715 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
718db961
LP
716 return 0;
717 }
6dded4c7 718
0674bbea
LP
719 r = sd_bus_negotiate_creds(bus, 1,
720 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
721 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
722 SD_BUS_CREDS_SELINUX_CONTEXT);
723 if (r < 0) {
724 log_warning_errno(r, "Failed to enable credentials for new connection: %m");
725 return 0;
726 }
727
a5ea30b7
LP
728 r = sd_bus_set_sender(bus, "org.freedesktop.systemd1");
729 if (r < 0) {
730 log_warning_errno(r, "Failed to set direct connection sender: %m");
731 return 0;
732 }
733
718db961
LP
734 r = sd_bus_start(bus);
735 if (r < 0) {
da927ba9 736 log_warning_errno(r, "Failed to start new connection bus: %m");
718db961 737 return 0;
6dded4c7
LP
738 }
739
718db961
LP
740 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
741 if (r < 0) {
da927ba9 742 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
718db961 743 return 0;
6dded4c7
LP
744 }
745
718db961
LP
746 r = bus_setup_disconnected_match(m, bus);
747 if (r < 0)
748 return 0;
6dded4c7 749
718db961
LP
750 r = bus_setup_api_vtables(m, bus);
751 if (r < 0) {
da927ba9 752 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
718db961
LP
753 return 0;
754 }
6dded4c7 755
718db961
LP
756 r = set_put(m->private_buses, bus);
757 if (r < 0) {
05a08cb6 758 log_warning_errno(r, "Failed to add new connection bus to set: %m");
718db961 759 return 0;
6dded4c7
LP
760 }
761
718db961 762 bus = NULL;
6dded4c7 763
718db961 764 log_debug("Accepted new private connection.");
6dded4c7 765
8e274523
LP
766 return 0;
767}
768
718db961 769static int bus_setup_api(Manager *m, sd_bus *bus) {
bbc29086
DM
770 Iterator i;
771 char *name;
772 Unit *u;
718db961 773 int r;
f278026d 774
718db961
LP
775 assert(m);
776 assert(bus);
c1e1601e 777
8fd00193
LP
778 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
779 r = sd_bus_negotiate_creds(bus, 1,
780 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
781 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
782 SD_BUS_CREDS_SELINUX_CONTEXT);
783 if (r < 0)
da927ba9 784 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
8fd00193 785
718db961
LP
786 r = bus_setup_api_vtables(m, bus);
787 if (r < 0)
788 return r;
cbd37330 789
bbc29086 790 HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
9806e87d 791 r = unit_install_bus_match(u, bus, name);
bbc29086 792 if (r < 0)
8ea823b6 793 log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
bbc29086 794 }
718db961 795
75152a4d 796 r = sd_bus_match_signal_async(
718db961 797 bus,
19befb2d 798 NULL,
75152a4d
LP
799 "org.freedesktop.DBus",
800 "/org/freedesktop/DBus",
801 "org.freedesktop.systemd1.Activator",
802 "ActivationRequest",
803 signal_activation_request, NULL, m);
718db961 804 if (r < 0)
da927ba9 805 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
cbd37330 806
0c0b9306
LP
807 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
808 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
809 * reexecution to finish */
810 r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT, NULL, NULL);
23bbb0de 811 if (r < 0)
0c0b9306 812 return log_error_errno(r, "Failed to request name: %m");
53c6a358 813
718db961 814 log_debug("Successfully connected to API bus.");
5f109056 815
f278026d
LP
816 return 0;
817}
818
8559b3b7 819int bus_init_api(Manager *m) {
b1a4981a 820 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
f278026d
LP
821 int r;
822
718db961
LP
823 if (m->api_bus)
824 return 0;
cbd37330 825
718db961 826 /* The API and system bus is the same if we are running in system mode */
463d0d15 827 if (MANAGER_IS_SYSTEM(m) && m->system_bus)
718db961
LP
828 bus = sd_bus_ref(m->system_bus);
829 else {
463d0d15 830 if (MANAGER_IS_SYSTEM(m))
56fbd718 831 r = sd_bus_open_system_with_description(&bus, "bus-api-system");
718db961 832 else
56fbd718 833 r = sd_bus_open_user_with_description(&bus, "bus-api-user");
dc7118ba
MS
834 if (r < 0)
835 return log_error_errno(r, "Failed to connect to API bus: %m");
cbd37330 836
718db961 837 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
dc7118ba
MS
838 if (r < 0)
839 return log_error_errno(r, "Failed to attach API bus to event loop: %m");
cbd37330 840
718db961
LP
841 r = bus_setup_disconnected_match(m, bus);
842 if (r < 0)
dc7118ba 843 return r;
cbd37330
MS
844 }
845
718db961 846 r = bus_setup_api(m, bus);
dc7118ba
MS
847 if (r < 0)
848 return log_error_errno(r, "Failed to set up API bus: %m");
cbd37330 849
1cc6c93a 850 m->api_bus = TAKE_PTR(bus);
cbd37330
MS
851
852 return 0;
cbd37330
MS
853}
854
718db961
LP
855static int bus_setup_system(Manager *m, sd_bus *bus) {
856 int r;
cbd37330 857
718db961
LP
858 assert(m);
859 assert(bus);
cbd37330 860
d8fdc620
LP
861 /* if we are a user instance we get the Released message via the system bus */
862 if (MANAGER_IS_USER(m)) {
75152a4d 863 r = sd_bus_match_signal_async(
f5b51ea7
DH
864 bus,
865 NULL,
75152a4d
LP
866 NULL,
867 "/org/freedesktop/systemd1/agent",
868 "org.freedesktop.systemd1.Agent",
869 "Released",
870 signal_agent_released, NULL, m);
f5b51ea7 871 if (r < 0)
75152a4d 872 log_warning_errno(r, "Failed to request Released match on system bus: %m");
f5b51ea7 873 }
718db961
LP
874
875 log_debug("Successfully connected to system bus.");
876 return 0;
cbd37330
MS
877}
878
8559b3b7 879int bus_init_system(Manager *m) {
b1a4981a 880 _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
cbd37330
MS
881 int r;
882
883 if (m->system_bus)
884 return 0;
885
718db961 886 /* The API and system bus is the same if we are running in system mode */
931e4754
LP
887 if (MANAGER_IS_SYSTEM(m) && m->api_bus)
888 bus = sd_bus_ref(m->api_bus);
889 else {
56fbd718 890 r = sd_bus_open_system_with_description(&bus, "bus-system");
931e4754
LP
891 if (r < 0)
892 return log_error_errno(r, "Failed to connect to system bus: %m");
cbd37330 893
931e4754
LP
894 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
895 if (r < 0)
896 return log_error_errno(r, "Failed to attach system bus to event loop: %m");
cbd37330 897
931e4754
LP
898 r = bus_setup_disconnected_match(m, bus);
899 if (r < 0)
900 return r;
901 }
cbd37330 902
718db961 903 r = bus_setup_system(m, bus);
dc7118ba
MS
904 if (r < 0)
905 return log_error_errno(r, "Failed to set up system bus: %m");
cbd37330 906
1cc6c93a 907 m->system_bus = TAKE_PTR(bus);
cbd37330
MS
908
909 return 0;
5e8d1c9a
LP
910}
911
8559b3b7 912int bus_init_private(Manager *m) {
718db961 913 _cleanup_close_ int fd = -1;
f36a9d59
ZJS
914 union sockaddr_union sa;
915 socklen_t sa_len;
718db961 916 sd_event_source *s;
f36a9d59 917 int r;
5e8d1c9a
LP
918
919 assert(m);
920
718db961 921 if (m->private_listen_fd >= 0)
5e8d1c9a
LP
922 return 0;
923
463d0d15 924 if (MANAGER_IS_SYSTEM(m)) {
be81bfc4
LP
925
926 /* We want the private bus only when running as init */
df0ff127 927 if (getpid_cached() != 1)
be81bfc4
LP
928 return 0;
929
f36a9d59 930 r = sockaddr_un_set_path(&sa.un, "/run/systemd/private");
be81bfc4 931 } else {
15a3e96f 932 const char *e, *joined;
be81bfc4 933
4db17f29 934 e = secure_getenv("XDG_RUNTIME_DIR");
baaa35ad
ZJS
935 if (!e)
936 return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN),
937 "XDG_RUNTIME_DIR is not set, refusing.");
be81bfc4 938
15a3e96f 939 joined = strjoina(e, "/systemd/private");
f36a9d59 940 r = sockaddr_un_set_path(&sa.un, joined);
be81bfc4 941 }
f36a9d59
ZJS
942 if (r < 0)
943 return log_error_errno(r, "Can't set path for AF_UNIX socket to bind to: %m");
944 sa_len = r;
5e8d1c9a 945
f0e62e89 946 (void) mkdir_parents_label(sa.un.sun_path, 0755);
155b6876 947 (void) sockaddr_un_unlink(&sa.un);
718db961
LP
948
949 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
4a62c710
MS
950 if (fd < 0)
951 return log_error_errno(errno, "Failed to allocate private socket: %m");
5e8d1c9a 952
f36a9d59 953 r = bind(fd, &sa.sa, sa_len);
4a62c710
MS
954 if (r < 0)
955 return log_error_errno(errno, "Failed to bind private socket: %m");
5e8d1c9a 956
718db961 957 r = listen(fd, SOMAXCONN);
4a62c710
MS
958 if (r < 0)
959 return log_error_errno(errno, "Failed to make private socket listening: %m");
5e8d1c9a 960
5b5e6dea
LP
961 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
962 (void) touch(sa.un.sun_path);
963
151b9b96 964 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
23bbb0de
MS
965 if (r < 0)
966 return log_error_errno(r, "Failed to allocate event source: %m");
5e8d1c9a 967
7dfbe2e3
TG
968 (void) sd_event_source_set_description(s, "bus-connection");
969
0b7e8b32 970 m->private_listen_fd = TAKE_FD(fd);
718db961 971 m->private_listen_event_source = s;
5e8d1c9a 972
718db961 973 log_debug("Successfully created private D-Bus server.");
5e8d1c9a 974
718db961 975 return 0;
5e8d1c9a
LP
976}
977
718db961 978static void destroy_bus(Manager *m, sd_bus **bus) {
a567261a 979 Iterator i;
8367fea5 980 Unit *u;
718db961 981 Job *j;
a567261a 982
718db961
LP
983 assert(m);
984 assert(bus);
5e8d1c9a 985
718db961 986 if (!*bus)
cbd37330 987 return;
f278026d 988
8367fea5
LP
989 /* Make sure all bus slots watching names are released. */
990 HASHMAP_FOREACH(u, m->watch_bus, i) {
a5b07847
LP
991 if (u->match_bus_slot && sd_bus_slot_get_bus(u->match_bus_slot) == *bus)
992 u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
993 if (u->get_name_owner_slot && sd_bus_slot_get_bus(u->get_name_owner_slot) == *bus)
994 u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
8367fea5
LP
995 }
996
718db961 997 /* Get rid of tracked clients on this bus */
8f8f05a9
LP
998 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
999 m->subscribed = sd_bus_track_unref(m->subscribed);
1000
718db961 1001 HASHMAP_FOREACH(j, m->jobs, i)
1a465207
LP
1002 if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
1003 j->bus_track = sd_bus_track_unref(j->bus_track);
c1e1601e 1004
d9e45bc3 1005 HASHMAP_FOREACH(u, m->units, i) {
dfeff664
LP
1006 if (u->bus_track && sd_bus_track_get_bus(u->bus_track) == *bus)
1007 u->bus_track = sd_bus_track_unref(u->bus_track);
1008
d9e45bc3
MS
1009 /* Get rid of pending freezer messages on this bus */
1010 if (u->pending_freezer_message && sd_bus_message_get_bus(u->pending_freezer_message) == *bus)
1011 u->pending_freezer_message = sd_bus_message_unref(u->pending_freezer_message);
1012 }
1013
718db961 1014 /* Get rid of queued message on this bus */
209de525
LP
1015 if (m->pending_reload_message && sd_bus_message_get_bus(m->pending_reload_message) == *bus)
1016 m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message);
f278026d 1017
718db961
LP
1018 /* Possibly flush unwritten data, but only if we are
1019 * unprivileged, since we don't want to sync here */
463d0d15 1020 if (!MANAGER_IS_SYSTEM(m))
718db961 1021 sd_bus_flush(*bus);
5e8d1c9a 1022
718db961 1023 /* And destroy the object */
81a40363 1024 *bus = sd_bus_close_unref(*bus);
5e8d1c9a
LP
1025}
1026
4502c403 1027void bus_done_api(Manager *m) {
9f77ba24 1028 destroy_bus(m, &m->api_bus);
4502c403
LP
1029}
1030
1031void bus_done_system(Manager *m) {
9f77ba24 1032 destroy_bus(m, &m->system_bus);
4502c403
LP
1033}
1034
1035void bus_done_private(Manager *m) {
1036 sd_bus *b;
1037
1038 assert(m);
1039
718db961
LP
1040 while ((b = set_steal_first(m->private_buses)))
1041 destroy_bus(m, &b);
05e343b7 1042
525d3cc7 1043 m->private_buses = set_free(m->private_buses);
8f8f05a9 1044
4502c403
LP
1045 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1046 m->private_listen_fd = safe_close(m->private_listen_fd);
1047}
1048
1049void bus_done(Manager *m) {
1050 assert(m);
05e343b7 1051
4502c403
LP
1052 bus_done_api(m);
1053 bus_done_system(m);
1054 bus_done_private(m);
05e343b7 1055
4502c403 1056 assert(!m->subscribed);
283868e1 1057
4502c403 1058 m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
283868e1 1059 bus_verify_polkit_async_registry_free(m->polkit_registry);
a567261a 1060}
b23de6af
LP
1061
1062int bus_fdset_add_all(Manager *m, FDSet *fds) {
1063 Iterator i;
718db961
LP
1064 sd_bus *b;
1065 int fd;
b23de6af
LP
1066
1067 assert(m);
1068 assert(fds);
1069
1070 /* When we are about to reexecute we add all D-Bus fds to the
1071 * set to pass over to the newly executed systemd. They won't
718db961 1072 * be used there however, except thatt they are closed at the
b23de6af 1073 * very end of deserialization, those making it possible for
44143309 1074 * clients to synchronously wait for systemd to reexec by
b23de6af
LP
1075 * simply waiting for disconnection */
1076
718db961
LP
1077 if (m->api_bus) {
1078 fd = sd_bus_get_fd(m->api_bus);
1079 if (fd >= 0) {
b23de6af 1080 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1081 if (fd < 0)
1082 return fd;
1083 }
1084 }
1085
718db961
LP
1086 SET_FOREACH(b, m->private_buses, i) {
1087 fd = sd_bus_get_fd(b);
1088 if (fd >= 0) {
b23de6af 1089 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1090 if (fd < 0)
1091 return fd;
1092 }
1093 }
1094
718db961
LP
1095 /* We don't offer any APIs on the system bus (well, unless it
1096 * is the same as the API bus) hence we don't bother with it
1097 * here */
6fa48533 1098
718db961 1099 return 0;
6fa48533
LP
1100}
1101
8f8f05a9
LP
1102int bus_foreach_bus(
1103 Manager *m,
1104 sd_bus_track *subscribed2,
1105 int (*send_message)(sd_bus *bus, void *userdata),
1106 void *userdata) {
1107
1108 Iterator i;
1109 sd_bus *b;
1110 int r, ret = 0;
1111
ff9b60f3 1112 /* Send to all direct buses, unconditionally */
8f8f05a9 1113 SET_FOREACH(b, m->private_buses, i) {
9fc677e3 1114
86b52a39 1115 /* Don't bother with enqueuing these messages to clients that haven't started yet */
9fc677e3
LP
1116 if (sd_bus_is_ready(b) <= 0)
1117 continue;
1118
8f8f05a9
LP
1119 r = send_message(b, userdata);
1120 if (r < 0)
1121 ret = r;
1122 }
1123
1124 /* Send to API bus, but only if somebody is subscribed */
6edd281c
LP
1125 if (m->api_bus &&
1126 (sd_bus_track_count(m->subscribed) > 0 ||
1127 sd_bus_track_count(subscribed2) > 0)) {
8f8f05a9
LP
1128 r = send_message(m->api_bus, userdata);
1129 if (r < 0)
1130 ret = r;
1131 }
1132
1133 return ret;
1134}
1135
05a98afd 1136void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
8f8f05a9
LP
1137 const char *n;
1138
6fa48533 1139 assert(f);
05a98afd 1140 assert(prefix);
6fa48533 1141
05a98afd
LP
1142 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
1143 int c, j;
230314d7 1144
05a98afd 1145 c = sd_bus_track_count_name(t, n);
d68c645b
LP
1146 for (j = 0; j < c; j++)
1147 (void) serialize_item(f, prefix, n);
05a98afd 1148 }
8f8f05a9
LP
1149}
1150
05a98afd 1151int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) {
c53aafb7 1152 int r;
8f8f05a9
LP
1153
1154 assert(m);
1155 assert(t);
8f8f05a9 1156
05a98afd
LP
1157 if (strv_isempty(l))
1158 return 0;
8f8f05a9 1159
05a98afd
LP
1160 if (!m->api_bus)
1161 return 0;
8f8f05a9 1162
05a98afd
LP
1163 if (!*t) {
1164 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1165 if (r < 0)
1166 return r;
8f8f05a9
LP
1167 }
1168
05a98afd
LP
1169 r = sd_bus_track_set_recursive(*t, recursive);
1170 if (r < 0)
1171 return r;
1172
984794ba 1173 return bus_track_add_name_many(*t, l);
6fa48533 1174}
283868e1 1175
1d22e906 1176int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1177 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1
SW
1178}
1179
283868e1 1180int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1181 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
1182}
1183
1184int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1185 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1 1186}
1d22e906
LP
1187
1188int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1189 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error);
1d22e906 1190}
e0a08581
LP
1191
1192uint64_t manager_bus_n_queued_write(Manager *m) {
1193 uint64_t c = 0;
1194 Iterator i;
1195 sd_bus *b;
1196 int r;
1197
5238e957 1198 /* Returns the total number of messages queued for writing on all our direct and API buses. */
e0a08581
LP
1199
1200 SET_FOREACH(b, m->private_buses, i) {
1201 uint64_t k;
1202
1203 r = sd_bus_get_n_queued_write(b, &k);
1204 if (r < 0)
1205 log_debug_errno(r, "Failed to query queued messages for private bus: %m");
1206 else
1207 c += k;
1208 }
1209
1210 if (m->api_bus) {
1211 uint64_t k;
1212
1213 r = sd_bus_get_n_queued_write(m->api_bus, &k);
1214 if (r < 0)
1215 log_debug_errno(r, "Failed to query queued messages for API bus: %m");
1216 else
1217 c += k;
1218 }
1219
1220 return c;
1221}
bbc1acab
YW
1222
1223static void vtable_dump_bus_properties(FILE *f, const sd_bus_vtable *table) {
1224 const sd_bus_vtable *i;
1225
1226 for (i = table; i->type != _SD_BUS_VTABLE_END; i++) {
1227 if (!IN_SET(i->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY) ||
1228 (i->flags & (SD_BUS_VTABLE_DEPRECATED | SD_BUS_VTABLE_HIDDEN)) != 0)
1229 continue;
1230
1231 fprintf(f, "%s\n", i->x.property.member);
1232 }
1233}
1234
1235void dump_bus_properties(FILE *f) {
1236 assert(f);
1237
1238 vtable_dump_bus_properties(f, bus_automount_vtable);
1239 vtable_dump_bus_properties(f, bus_cgroup_vtable);
1240 vtable_dump_bus_properties(f, bus_device_vtable);
1241 vtable_dump_bus_properties(f, bus_exec_vtable);
1242 vtable_dump_bus_properties(f, bus_job_vtable);
1243 vtable_dump_bus_properties(f, bus_kill_vtable);
1244 vtable_dump_bus_properties(f, bus_manager_vtable);
1245 vtable_dump_bus_properties(f, bus_mount_vtable);
1246 vtable_dump_bus_properties(f, bus_path_vtable);
1247 vtable_dump_bus_properties(f, bus_scope_vtable);
1248 vtable_dump_bus_properties(f, bus_service_vtable);
1249 vtable_dump_bus_properties(f, bus_slice_vtable);
1250 vtable_dump_bus_properties(f, bus_socket_vtable);
1251 vtable_dump_bus_properties(f, bus_swap_vtable);
1252 vtable_dump_bus_properties(f, bus_target_vtable);
1253 vtable_dump_bus_properties(f, bus_timer_vtable);
1254 vtable_dump_bus_properties(f, bus_unit_vtable);
1255 vtable_dump_bus_properties(f, bus_unit_cgroup_vtable);
1256}