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