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