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