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