]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus.c
add bash completion for systemd-cgtop
[thirdparty/systemd.git] / src / core / dbus.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ea430986 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
ea430986
LP
22#include <sys/epoll.h>
23#include <sys/timerfd.h>
24#include <errno.h>
25#include <unistd.h>
26
718db961 27#include "sd-bus.h"
ea430986
LP
28#include "log.h"
29#include "strv.h"
49e942b2 30#include "mkdir.h"
4db17f29 31#include "missing.h"
4139c1b2
LP
32#include "dbus-unit.h"
33#include "dbus-job.h"
34#include "dbus-manager.h"
718db961
LP
35#include "dbus-execute.h"
36#include "dbus-kill.h"
37#include "dbus-cgroup.h"
8f6df3fa 38#include "special.h"
718db961
LP
39#include "dbus.h"
40#include "bus-util.h"
41#include "bus-error.h"
42#include "bus-errors.h"
43#include "strxcpyx.h"
44#include "dbus-client-track.h"
969987ea
LP
45#include "bus-internal.h"
46#include "selinux-access.h"
4288f619 47
417b1a62 48#define CONNECTIONS_MAX 512
5e8d1c9a 49
718db961
LP
50static void destroy_bus(Manager *m, sd_bus **bus);
51
52int bus_send_queued_message(Manager *m) {
53 int r;
8e274523 54
8e274523 55 assert(m);
2e317f52 56
718db961
LP
57 if (!m->queued_message)
58 return 0;
8e274523 59
718db961 60 assert(m->queued_message_bus);
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
718db961
LP
66 r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
67 if (r < 0)
68 log_warning("Failed to send queued message: %s", strerror(-r));
ea430986 69
718db961
LP
70 m->queued_message = sd_bus_message_unref(m->queued_message);
71 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
ea430986 72
718db961 73 return 0;
ea430986
LP
74}
75
ebcf1f97 76static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
77 Manager *m = userdata;
78 const char *cgroup;
79 int r;
ea430986 80
718db961
LP
81 assert(bus);
82 assert(message);
ea430986
LP
83 assert(m);
84
718db961
LP
85 r = sd_bus_message_read(message, "s", &cgroup);
86 if (r < 0) {
87 bus_log_parse_error(r);
88 return 0;
89 }
ea430986 90
718db961 91 manager_notify_cgroup_empty(m, cgroup);
ea430986 92
718db961
LP
93 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
94 /* If we are running as system manager, forward the
95 * message to the system bus */
ea430986 96
718db961
LP
97 r = sd_bus_send(m->system_bus, message, NULL);
98 if (r < 0)
99 log_warning("Failed to forward Released message: %s", strerror(-r));
100 }
ea430986 101
718db961
LP
102 return 0;
103}
ea430986 104
ebcf1f97 105static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 106 Manager *m = userdata;
ea430986 107
718db961
LP
108 assert(bus);
109 assert(message);
110 assert(m);
ea430986 111
718db961
LP
112 if (bus == m->api_bus)
113 destroy_bus(m, &m->api_bus);
114 if (bus == m->system_bus)
115 destroy_bus(m, &m->system_bus);
116 if (set_remove(m->private_buses, bus)) {
117 log_debug("Got disconnect on private connection.");
118 destroy_bus(m, &bus);
ea430986
LP
119 }
120
718db961 121 return 0;
ea430986
LP
122}
123
ebcf1f97 124static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
125 const char *name, *old_owner, *new_owner;
126 Manager *m = userdata;
127 int r;
ea430986 128
718db961
LP
129 assert(bus);
130 assert(message);
ea430986
LP
131 assert(m);
132
718db961
LP
133 r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
134 if (r < 0) {
135 bus_log_parse_error(r);
136 return 0;
137 }
ea430986 138
718db961
LP
139 manager_dispatch_bus_name_owner_changed(
140 m, name,
141 isempty(old_owner) ? NULL : old_owner,
142 isempty(new_owner) ? NULL : new_owner);
ea430986 143
718db961 144 return 0;
ea430986
LP
145}
146
ebcf1f97 147static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
718db961
LP
148 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
149 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
150 Manager *m = userdata;
151 const char *name;
152 Unit *u;
153 int r;
ea430986 154
718db961
LP
155 assert(bus);
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) {
d14ab08b 176 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only.", u->id);
718db961 177 goto failed;
ea430986
LP
178 }
179
718db961
LP
180 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
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
151b9b96 193 r = sd_bus_message_new_signal(bus, &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
205 r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
206 if (r < 0) {
207 log_error("Failed to respond with to bus activation request: %s", strerror(-r));
208 return r;
209 }
ea430986 210
718db961 211 return 0;
ea430986
LP
212}
213
ad5b215d 214#ifdef HAVE_SELINUX
969987ea
LP
215static int selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
216 Manager *m = userdata;
217 const char *verb, *path;
218 Unit *u = NULL;
219 Job *j;
220 int r;
221
222 assert(bus);
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
243 r = selinux_access_check(bus, message, verb, error);
244 if (r < 0)
245 return r;
246
247 return 0;
248 }
249
250 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
5b12334d 251 _cleanup_bus_creds_unref_ 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
274 r = selinux_unit_access_check(u, bus, message, verb, error);
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) {
718db961
LP
302 Unit *u;
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")) {
5b12334d 310 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
718db961
LP
311 sd_bus_message *message;
312 pid_t pid;
ea430986 313
718db961
LP
314 message = sd_bus_get_current(bus);
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
LP
326 u = manager_get_unit_by_pid(m, pid);
327 } else {
f00c3121 328 r = manager_load_unit_from_dbus_path(m, path, error, &u);
718db961 329 if (r < 0)
f00c3121 330 return 0;
718db961 331 }
ea430986 332
f00c3121
LP
333 if (!u)
334 return 0;
335
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
718db961
LP
367 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
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
718db961
LP
389 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
390 return 0;
05e343b7 391
718db961
LP
392 if (!unit_get_cgroup_context(u))
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
718db961
LP
415 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
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
718db961
LP
442 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
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
718db961
LP
469 if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
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) {
718db961
LP
481 _cleanup_free_ char **l = NULL;
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) {
718db961
LP
508 _cleanup_free_ char **l = NULL;
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
ad5b215d 539#ifdef HAVE_SELINUX
969987ea
LP
540 r = sd_bus_add_filter(bus, selinux_filter, m);
541 if (r < 0) {
542 log_error("Failed to add SELinux access filter: %s", strerror(-r));
543 return r;
544 }
ad5b215d 545#endif
969987ea 546
718db961
LP
547 r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
548 if (r < 0) {
549 log_error("Failed to register Manager vtable: %s", strerror(-r));
550 return r;
a16e1123
LP
551 }
552
718db961
LP
553 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
554 if (r < 0) {
555 log_error("Failed to register Job vtable: %s", strerror(-r));
556 return r;
fd18e1f4 557 }
c1e1601e 558
718db961
LP
559 r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
560 if (r < 0) {
561 log_error("Failed to add job enumerator: %s", strerror(-r));
562 return r;
563 }
61902ea3 564
718db961
LP
565 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
566 if (r < 0) {
567 log_error("Failed to register Unit vtable: %s", strerror(-r));
568 return r;
569 }
61902ea3 570
718db961
LP
571 r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
572 if (r < 0) {
573 log_error("Failed to add job enumerator: %s", strerror(-r));
574 return r;
575 }
61902ea3 576
718db961
LP
577 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
578 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
579 if (r < 0) {
580 log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
581 return r;
582 }
61902ea3 583
718db961
LP
584 if (unit_vtable[t]->cgroup_context_offset > 0) {
585 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
586 if (r < 0) {
587 log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
588 return r;
589 }
61902ea3 590
718db961
LP
591 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
592 if (r < 0) {
593 log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
594 return r;
595 }
61902ea3
LP
596 }
597
718db961
LP
598 if (unit_vtable[t]->exec_context_offset > 0) {
599 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
600 if (r < 0) {
601 log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
602 return r;
603 }
604 }
61902ea3 605
718db961
LP
606 if (unit_vtable[t]->kill_context_offset > 0) {
607 r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
608 if (r < 0) {
609 log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
610 return r;
611 }
612 }
61902ea3
LP
613 }
614
718db961 615 return 0;
61902ea3
LP
616}
617
718db961
LP
618static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
619 int r;
61902ea3 620
718db961
LP
621 assert(m);
622 assert(bus);
61902ea3 623
718db961
LP
624 r = sd_bus_add_match(
625 bus,
27fc65e1 626 "sender='org.freedesktop.DBus.Local',"
718db961
LP
627 "type='signal',"
628 "path='/org/freedesktop/DBus/Local',"
629 "interface='org.freedesktop.DBus.Local',"
630 "member='Disconnected'",
631 signal_disconnected, m);
05e343b7 632
718db961
LP
633 if (r < 0) {
634 log_error("Failed to register match for Disconnected message: %s", strerror(-r));
635 return r;
05e343b7
LP
636 }
637
718db961 638 return 0;
ea430986
LP
639}
640
718db961
LP
641static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
642 _cleanup_bus_unref_ sd_bus *bus = NULL;
643 _cleanup_close_ int nfd = -1;
6dded4c7 644 Manager *m = userdata;
718db961
LP
645 sd_id128_t id;
646 int r;
6dded4c7 647
718db961 648 assert(s);
6dded4c7
LP
649 assert(m);
650
718db961
LP
651 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
652 if (nfd < 0) {
653 log_warning("Failed to accept private connection, ignoring: %m");
654 return 0;
655 }
6dded4c7 656
718db961
LP
657 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
658 log_warning("Too many concurrent connections, refusing");
659 return 0;
660 }
6dded4c7 661
718db961
LP
662 r = set_ensure_allocated(&m->private_buses, trivial_hash_func, trivial_compare_func);
663 if (r < 0) {
664 log_oom();
665 return 0;
666 }
6dded4c7 667
718db961
LP
668 r = sd_bus_new(&bus);
669 if (r < 0) {
670 log_warning("Failed to allocate new private connection bus: %s", strerror(-r));
671 return 0;
672 }
6dded4c7 673
718db961
LP
674 r = sd_bus_set_fd(bus, nfd, nfd);
675 if (r < 0) {
676 log_warning("Failed to set fd on new connection bus: %s", strerror(-r));
677 return 0;
678 }
6dded4c7 679
718db961 680 nfd = -1;
6dded4c7 681
718db961
LP
682 r = bus_check_peercred(bus);
683 if (r < 0) {
684 log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
685 return 0;
686 }
6dded4c7 687
718db961 688 assert_se(sd_id128_randomize(&id) >= 0);
6dded4c7 689
718db961
LP
690 r = sd_bus_set_server(bus, 1, id);
691 if (r < 0) {
692 log_warning("Failed to enable server support for new connection bus: %s", strerror(-r));
693 return 0;
694 }
6dded4c7 695
718db961
LP
696 r = sd_bus_start(bus);
697 if (r < 0) {
698 log_warning("Failed to start new connection bus: %s", strerror(-r));
699 return 0;
6dded4c7
LP
700 }
701
718db961
LP
702 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
703 if (r < 0) {
704 log_warning("Failed to attach new connection bus to event loop: %s", strerror(-r));
705 return 0;
6dded4c7
LP
706 }
707
718db961
LP
708 if (m->running_as == SYSTEMD_SYSTEM) {
709 /* When we run as system instance we get the Released
710 * signal via a direct connection */
711
712 r = sd_bus_add_match(
713 bus,
714 "type='signal',"
715 "interface='org.freedesktop.systemd1.Agent',"
716 "member='Released',"
717 "path='/org/freedesktop/systemd1/agent'",
718 signal_agent_released, m);
719
720 if (r < 0) {
721 log_warning("Failed to register Released match on new connection bus: %s", strerror(-r));
722 return 0;
723 }
724 }
6dded4c7 725
718db961
LP
726 r = bus_setup_disconnected_match(m, bus);
727 if (r < 0)
728 return 0;
6dded4c7 729
718db961
LP
730 r = bus_setup_api_vtables(m, bus);
731 if (r < 0) {
732 log_warning("Failed to set up API vtables on new connection bus: %s", strerror(-r));
733 return 0;
734 }
6dded4c7 735
718db961
LP
736 r = set_put(m->private_buses, bus);
737 if (r < 0) {
738 log_warning("Failed to add new conenction bus to set: %s", strerror(-r));
739 return 0;
6dded4c7
LP
740 }
741
718db961 742 bus = NULL;
6dded4c7 743
718db961 744 log_debug("Accepted new private connection.");
6dded4c7 745
8e274523
LP
746 return 0;
747}
748
718db961 749static int bus_list_names(Manager *m, sd_bus *bus) {
0e7be129
LP
750 _cleanup_strv_free_ char **names = NULL;
751 char **i;
718db961 752 int r;
5e8d1c9a
LP
753
754 assert(m);
718db961 755 assert(bus);
5e8d1c9a 756
0e7be129 757 r = sd_bus_list_names(bus, &names, NULL);
718db961 758 if (r < 0) {
0e7be129 759 log_error("Failed to get initial list of names: %s", strerror(-r));
718db961 760 return r;
5e8d1c9a
LP
761 }
762
718db961
LP
763 /* This is a bit hacky, we say the owner of the name is the
764 * name itself, because we don't want the extra traffic to
765 * figure out the real owner. */
0e7be129
LP
766 STRV_FOREACH(i, names)
767 manager_dispatch_bus_name_owner_changed(m, *i, NULL, *i);
5e8d1c9a 768
718db961 769 return 0;
5e8d1c9a
LP
770}
771
718db961
LP
772static int bus_setup_api(Manager *m, sd_bus *bus) {
773 int r;
f278026d 774
718db961
LP
775 assert(m);
776 assert(bus);
c1e1601e 777
718db961
LP
778 r = bus_setup_api_vtables(m, bus);
779 if (r < 0)
780 return r;
cbd37330 781
718db961
LP
782 r = sd_bus_add_match(
783 bus,
784 "type='signal',"
785 "sender='org.freedesktop.DBus',"
786 "path='/org/freedesktop/DBus',"
787 "interface='org.freedesktop.DBus',"
788 "member='NameOwnerChanged'",
789 signal_name_owner_changed, m);
790 if (r < 0)
791 log_warning("Failed to subscribe to NameOwnerChanged signal: %s", strerror(-r));
792
793 r = sd_bus_add_match(
794 bus,
795 "type='signal',"
796 "sender='org.freedesktop.DBus',"
797 "path='/org/freedesktop/DBus',"
798 "interface='org.freedesktop.systemd1.Activator',"
799 "member='ActivationRequest'",
800 signal_activation_request, m);
801 if (r < 0)
802 log_warning("Failed to subscribe to activation signal: %s", strerror(-r));
cbd37330 803
718db961
LP
804 /* Allow replacing of our name, to ease implementation of
805 * reexecution, where we keep the old connection open until
806 * after the new connection is set up and the name installed
807 * to allow clients to synchronously wait for reexecution to
808 * finish */
29a07cdb 809 r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
718db961
LP
810 if (r < 0) {
811 log_error("Failed to register name: %s", strerror(-r));
812 return r;
813 }
53c6a358 814
718db961 815 bus_list_names(m, bus);
f278026d 816
718db961 817 log_debug("Successfully connected to API bus.");
f278026d
LP
818 return 0;
819}
820
718db961
LP
821static int bus_init_api(Manager *m) {
822 _cleanup_bus_unref_ sd_bus *bus = NULL;
f278026d
LP
823 int r;
824
718db961
LP
825 if (m->api_bus)
826 return 0;
cbd37330 827
718db961
LP
828 /* The API and system bus is the same if we are running in system mode */
829 if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
830 bus = sd_bus_ref(m->system_bus);
831 else {
832 if (m->running_as == SYSTEMD_SYSTEM)
833 r = sd_bus_open_system(&bus);
834 else
835 r = sd_bus_open_user(&bus);
cbd37330 836
718db961
LP
837 if (r < 0) {
838 log_debug("Failed to connect to API bus, retrying later...");
839 return 0;
cbd37330
MS
840 }
841
718db961
LP
842 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
843 if (r < 0) {
844 log_error("Failed to attach API bus to event loop: %s", strerror(-r));
845 return 0;
cbd37330
MS
846 }
847
718db961
LP
848 r = bus_setup_disconnected_match(m, bus);
849 if (r < 0)
850 return 0;
cbd37330
MS
851 }
852
718db961 853 r = bus_setup_api(m, bus);
cbd37330 854 if (r < 0) {
718db961
LP
855 log_error("Failed to set up API bus: %s", strerror(-r));
856 return 0;
cbd37330 857 }
cbd37330 858
718db961
LP
859 m->api_bus = bus;
860 bus = NULL;
cbd37330
MS
861
862 return 0;
cbd37330
MS
863}
864
718db961
LP
865static int bus_setup_system(Manager *m, sd_bus *bus) {
866 int r;
cbd37330 867
718db961
LP
868 assert(m);
869 assert(bus);
cbd37330 870
718db961
LP
871 if (m->running_as == SYSTEMD_SYSTEM)
872 return 0;
cbd37330 873
718db961
LP
874 /* If we are a user instance we get the Released message via
875 * the system bus */
876 r = sd_bus_add_match(
877 bus,
878 "type='signal',"
879 "interface='org.freedesktop.systemd1.Agent',"
880 "member='Released',"
881 "path='/org/freedesktop/systemd1/agent'",
882 signal_agent_released, m);
4dd1de72 883
718db961
LP
884 if (r < 0)
885 log_warning("Failed to register Released match on system bus: %s", strerror(-r));
886
887 log_debug("Successfully connected to system bus.");
888 return 0;
cbd37330
MS
889}
890
891static int bus_init_system(Manager *m) {
718db961 892 _cleanup_bus_unref_ sd_bus *bus = NULL;
cbd37330
MS
893 int r;
894
895 if (m->system_bus)
896 return 0;
897
718db961
LP
898 /* The API and system bus is the same if we are running in system mode */
899 if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
900 m->system_bus = sd_bus_ref(m->api_bus);
901 return 0;
9014a8bd 902 }
8e274523 903
718db961
LP
904 r = sd_bus_open_system(&bus);
905 if (r < 0) {
906 log_debug("Failed to connect to system bus, retrying later...");
907 return 0;
908 }
cbd37330 909
718db961 910 r = bus_setup_disconnected_match(m, bus);
cbd37330 911 if (r < 0)
cbd37330
MS
912 return 0;
913
718db961
LP
914 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
915 if (r < 0) {
916 log_error("Failed to attach system bus to event loop: %s", strerror(-r));
cbd37330
MS
917 return 0;
918 }
919
718db961
LP
920 r = bus_setup_system(m, bus);
921 if (r < 0) {
922 log_error("Fauiled to set up system bus: %s", strerror(-r));
923 return 0;
cbd37330
MS
924 }
925
718db961
LP
926 m->system_bus = bus;
927 bus = NULL;
cbd37330
MS
928
929 return 0;
5e8d1c9a
LP
930}
931
932static int bus_init_private(Manager *m) {
718db961
LP
933 _cleanup_close_ int fd = -1;
934 union sockaddr_union sa = {
935 .un.sun_family = AF_UNIX
5e8d1c9a 936 };
718db961
LP
937 sd_event_source *s;
938 socklen_t salen;
939 int r;
5e8d1c9a
LP
940
941 assert(m);
942
718db961 943 if (m->private_listen_fd >= 0)
5e8d1c9a
LP
944 return 0;
945
a6aa8912
LP
946 /* We don't need the private socket if we have kdbus */
947 if (m->kdbus_fd >= 0)
948 return 0;
949
67445f4e 950 if (m->running_as == SYSTEMD_SYSTEM) {
be81bfc4
LP
951
952 /* We want the private bus only when running as init */
953 if (getpid() != 1)
954 return 0;
955
718db961
LP
956 strcpy(sa.un.sun_path, "/run/systemd/private");
957 salen = offsetof(union sockaddr_union, un.sun_path) + sizeof("/run/systemd/private") - 1;
be81bfc4 958 } else {
718db961
LP
959 size_t left = sizeof(sa.un.sun_path);
960 char *p = sa.un.sun_path;
be81bfc4 961 const char *e;
be81bfc4 962
4db17f29 963 e = secure_getenv("XDG_RUNTIME_DIR");
718db961
LP
964 if (!e) {
965 log_error("Failed to determine XDG_RUNTIME_DIR");
966 return -EHOSTDOWN;
be81bfc4
LP
967 }
968
718db961
LP
969 left = strpcpy(&p, left, e);
970 left = strpcpy(&p, left, "/systemd/private");
92f30349 971
718db961 972 salen = sizeof(sa.un) - left;
92f30349 973
718db961 974 mkdir_parents_label(sa.un.sun_path, 0755);
be81bfc4 975 }
5e8d1c9a 976
718db961
LP
977 unlink(sa.un.sun_path);
978
979 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
980 if (fd < 0) {
981 log_error("Failed to allocate private socket: %m");
982 return -errno;
5e8d1c9a
LP
983 }
984
718db961
LP
985 r = bind(fd, &sa.sa, salen);
986 if (r < 0) {
987 log_error("Failed to bind private socket: %m");
988 return -errno;
5e8d1c9a
LP
989 }
990
718db961
LP
991 r = listen(fd, SOMAXCONN);
992 if (r < 0) {
993 log_error("Failed to make private socket listening: %m");
994 return -errno;
995 }
5e8d1c9a 996
151b9b96 997 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
718db961
LP
998 if (r < 0) {
999 log_error("Failed to allocate event source: %s", strerror(-r));
1000 return r;
1001 }
5e8d1c9a 1002
718db961
LP
1003 m->private_listen_fd = fd;
1004 m->private_listen_event_source = s;
1005 fd = -1;
5e8d1c9a 1006
718db961 1007 log_debug("Successfully created private D-Bus server.");
5e8d1c9a 1008
718db961 1009 return 0;
5e8d1c9a
LP
1010}
1011
3996fbe2 1012int bus_init(Manager *m, bool try_bus_connect) {
5e8d1c9a
LP
1013 int r;
1014
3996fbe2 1015 if (try_bus_connect) {
718db961
LP
1016 r = bus_init_system(m);
1017 if (r < 0)
1018 return r;
1019
1020 r = bus_init_api(m);
1021 if (r < 0)
3996fbe2
LP
1022 return r;
1023 }
1024
6fa48533
LP
1025 r = bus_init_private(m);
1026 if (r < 0)
5e8d1c9a 1027 return r;
f278026d 1028
ea430986
LP
1029 return 0;
1030}
1031
718db961 1032static void destroy_bus(Manager *m, sd_bus **bus) {
a567261a 1033 Iterator i;
718db961 1034 Job *j;
a567261a 1035
718db961
LP
1036 assert(m);
1037 assert(bus);
5e8d1c9a 1038
718db961 1039 if (!*bus)
cbd37330 1040 return;
f278026d 1041
718db961
LP
1042 /* Get rid of tracked clients on this bus */
1043 bus_client_untrack_bus(m->subscribed, *bus);
1044 HASHMAP_FOREACH(j, m->jobs, i)
1045 bus_client_untrack_bus(j->subscribed, *bus);
c1e1601e 1046
718db961
LP
1047 /* Get rid of queued message on this bus */
1048 if (m->queued_message_bus == *bus) {
1049 m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
05e343b7 1050
718db961
LP
1051 if (m->queued_message)
1052 m->queued_message = sd_bus_message_unref(m->queued_message);
cbd37330 1053 }
f278026d 1054
718db961
LP
1055 /* Possibly flush unwritten data, but only if we are
1056 * unprivileged, since we don't want to sync here */
1057 if (m->running_as != SYSTEMD_SYSTEM)
1058 sd_bus_flush(*bus);
5e8d1c9a 1059
718db961
LP
1060 /* And destroy the object */
1061 sd_bus_close(*bus);
1062 *bus = sd_bus_unref(*bus);
5e8d1c9a
LP
1063}
1064
1065void bus_done(Manager *m) {
718db961 1066 sd_bus *b;
05e343b7
LP
1067
1068 assert(m);
05e343b7 1069
718db961
LP
1070 if (m->api_bus)
1071 destroy_bus(m, &m->api_bus);
1072 if (m->system_bus)
1073 destroy_bus(m, &m->system_bus);
1074 while ((b = set_steal_first(m->private_buses)))
1075 destroy_bus(m, &b);
05e343b7 1076
718db961
LP
1077 set_free(m->private_buses);
1078 set_free(m->subscribed);
05e343b7 1079
718db961
LP
1080 if (m->private_listen_event_source)
1081 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
05e343b7 1082
718db961
LP
1083 if (m->private_listen_fd >= 0) {
1084 close_nointr_nofail(m->private_listen_fd);
1085 m->private_listen_fd = -1;
05e343b7 1086 }
a567261a 1087}
b23de6af
LP
1088
1089int bus_fdset_add_all(Manager *m, FDSet *fds) {
1090 Iterator i;
718db961
LP
1091 sd_bus *b;
1092 int fd;
b23de6af
LP
1093
1094 assert(m);
1095 assert(fds);
1096
1097 /* When we are about to reexecute we add all D-Bus fds to the
1098 * set to pass over to the newly executed systemd. They won't
718db961 1099 * be used there however, except thatt they are closed at the
b23de6af 1100 * very end of deserialization, those making it possible for
44143309 1101 * clients to synchronously wait for systemd to reexec by
b23de6af
LP
1102 * simply waiting for disconnection */
1103
718db961
LP
1104 if (m->api_bus) {
1105 fd = sd_bus_get_fd(m->api_bus);
1106 if (fd >= 0) {
b23de6af 1107 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1108 if (fd < 0)
1109 return fd;
1110 }
1111 }
1112
718db961
LP
1113 SET_FOREACH(b, m->private_buses, i) {
1114 fd = sd_bus_get_fd(b);
1115 if (fd >= 0) {
b23de6af 1116 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1117 if (fd < 0)
1118 return fd;
1119 }
1120 }
1121
718db961
LP
1122 /* We don't offer any APIs on the system bus (well, unless it
1123 * is the same as the API bus) hence we don't bother with it
1124 * here */
6fa48533 1125
718db961 1126 return 0;
6fa48533
LP
1127}
1128
1129void bus_serialize(Manager *m, FILE *f) {
6fa48533
LP
1130 assert(m);
1131 assert(f);
1132
718db961 1133 bus_client_track_serialize(m, f, m->subscribed);
6fa48533
LP
1134}
1135
1136int bus_deserialize_item(Manager *m, const char *line) {
6fa48533
LP
1137 assert(m);
1138 assert(line);
1139
718db961 1140 return bus_client_track_deserialize_item(m, &m->subscribed, line);
6fa48533 1141}