]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus.c
cryptsetup: downgrade world-writable warning again
[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>
4139c1b2 26#include <dbus/dbus.h>
ea430986
LP
27
28#include "dbus.h"
29#include "log.h"
30#include "strv.h"
8e274523 31#include "cgroup.h"
49e942b2 32#include "mkdir.h"
4db17f29 33#include "missing.h"
4139c1b2
LP
34#include "dbus-unit.h"
35#include "dbus-job.h"
36#include "dbus-manager.h"
4288f619
LP
37#include "dbus-service.h"
38#include "dbus-socket.h"
39#include "dbus-target.h"
40#include "dbus-device.h"
41#include "dbus-mount.h"
42#include "dbus-automount.h"
43#include "dbus-snapshot.h"
44#include "dbus-swap.h"
871d7de4 45#include "dbus-timer.h"
01f78473 46#include "dbus-path.h"
398ef8ba 47#include "bus-errors.h"
8f6df3fa 48#include "special.h"
bfebab7f 49#include "dbus-common.h"
4288f619 50
5e8d1c9a
LP
51#define CONNECTIONS_MAX 52
52
cbd37330
MS
53/* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
54#define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
55/* Only used as a fallback */
56#define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
57
4288f619
LP
58static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
59static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
60
61const char *const bus_interface_table[] = {
62 "org.freedesktop.DBus.Properties", bus_properties_interface,
63 "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
64 "org.freedesktop.systemd1.Manager", bus_manager_interface,
65 "org.freedesktop.systemd1.Job", bus_job_interface,
66 "org.freedesktop.systemd1.Unit", bus_unit_interface,
67 "org.freedesktop.systemd1.Service", bus_service_interface,
68 "org.freedesktop.systemd1.Socket", bus_socket_interface,
69 "org.freedesktop.systemd1.Target", bus_target_interface,
70 "org.freedesktop.systemd1.Device", bus_device_interface,
71 "org.freedesktop.systemd1.Mount", bus_mount_interface,
72 "org.freedesktop.systemd1.Automount", bus_automount_interface,
73 "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface,
74 "org.freedesktop.systemd1.Swap", bus_swap_interface,
871d7de4 75 "org.freedesktop.systemd1.Timer", bus_timer_interface,
01f78473 76 "org.freedesktop.systemd1.Path", bus_path_interface,
4288f619
LP
77 NULL
78};
ea430986 79
5e8d1c9a
LP
80static void bus_done_api(Manager *m);
81static void bus_done_system(Manager *m);
82static void bus_done_private(Manager *m);
923f8d76 83static void shutdown_connection(Manager *m, DBusConnection *c);
0034c15c 84
5e8d1c9a 85static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data) {
8e274523
LP
86 Manager *m = data;
87
88 assert(bus);
89 assert(m);
2e317f52 90
5e8d1c9a
LP
91 /* We maintain two sets, one for those connections where we
92 * requested a dispatch, and another where we didn't. And then,
93 * we move the connections between the two sets. */
8e274523 94
5e8d1c9a
LP
95 if (status == DBUS_DISPATCH_COMPLETE)
96 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
97 else
98 set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
8e274523
LP
99}
100
ea430986
LP
101void bus_watch_event(Manager *m, Watch *w, int events) {
102 assert(m);
103 assert(w);
104
105 /* This is called by the event loop whenever there is
106 * something happening on D-Bus' file handles. */
107
8e274523 108 if (!dbus_watch_get_enabled(w->data.bus_watch))
ea430986
LP
109 return;
110
3df5bf61 111 dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
ea430986
LP
112}
113
114static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
115 Manager *m = data;
116 Watch *w;
117 struct epoll_event ev;
118
119 assert(bus_watch);
120 assert(m);
121
122 if (!(w = new0(Watch, 1)))
123 return FALSE;
124
125 w->fd = dbus_watch_get_unix_fd(bus_watch);
126 w->type = WATCH_DBUS_WATCH;
127 w->data.bus_watch = bus_watch;
128
129 zero(ev);
130 ev.events = bus_flags_to_events(bus_watch);
131 ev.data.ptr = w;
132
133 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
134
135 if (errno != EEXIST) {
136 free(w);
137 return FALSE;
138 }
139
140 /* Hmm, bloody D-Bus creates multiple watches on the
141 * same fd. epoll() does not like that. As a dirty
142 * hack we simply dup() the fd and hence get a second
143 * one we can safely add to the epoll(). */
144
145 if ((w->fd = dup(w->fd)) < 0) {
146 free(w);
147 return FALSE;
148 }
149
150 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
ea430986 151 close_nointr_nofail(w->fd);
da19d5c1 152 free(w);
ea430986
LP
153 return FALSE;
154 }
155
156 w->fd_is_dupped = true;
157 }
158
159 dbus_watch_set_data(bus_watch, w, NULL);
160
161 return TRUE;
162}
163
164static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
165 Manager *m = data;
166 Watch *w;
167
168 assert(bus_watch);
169 assert(m);
170
3df5bf61
LP
171 w = dbus_watch_get_data(bus_watch);
172 if (!w)
ea430986
LP
173 return;
174
175 assert(w->type == WATCH_DBUS_WATCH);
176 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
177
178 if (w->fd_is_dupped)
179 close_nointr_nofail(w->fd);
180
181 free(w);
182}
183
184static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
185 Manager *m = data;
186 Watch *w;
187 struct epoll_event ev;
188
189 assert(bus_watch);
190 assert(m);
191
3df5bf61
LP
192 w = dbus_watch_get_data(bus_watch);
193 if (!w)
194 return;
195
ea430986
LP
196 assert(w->type == WATCH_DBUS_WATCH);
197
198 zero(ev);
199 ev.events = bus_flags_to_events(bus_watch);
200 ev.data.ptr = w;
201
202 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
203}
204
205static int bus_timeout_arm(Manager *m, Watch *w) {
b92bea5d 206 struct itimerspec its = {};
ea430986
LP
207
208 assert(m);
209 assert(w);
210
ea430986
LP
211 if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
212 timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
da19d5c1 213 its.it_interval = its.it_value;
ea430986
LP
214 }
215
216 if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
217 return -errno;
218
219 return 0;
220}
221
222void bus_timeout_event(Manager *m, Watch *w, int events) {
223 assert(m);
224 assert(w);
225
226 /* This is called by the event loop whenever there is
227 * something happening on D-Bus' file handles. */
228
229 if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
230 return;
231
232 dbus_timeout_handle(w->data.bus_timeout);
233}
234
235static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
236 Manager *m = data;
237 Watch *w;
238 struct epoll_event ev;
239
240 assert(timeout);
241 assert(m);
242
243 if (!(w = new0(Watch, 1)))
244 return FALSE;
245
da19d5c1 246 if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
ea430986
LP
247 goto fail;
248
249 w->type = WATCH_DBUS_TIMEOUT;
250 w->data.bus_timeout = timeout;
251
252 if (bus_timeout_arm(m, w) < 0)
253 goto fail;
254
255 zero(ev);
256 ev.events = EPOLLIN;
257 ev.data.ptr = w;
258
259 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
260 goto fail;
261
262 dbus_timeout_set_data(timeout, w, NULL);
263
264 return TRUE;
265
266fail:
267 if (w->fd >= 0)
268 close_nointr_nofail(w->fd);
269
270 free(w);
271 return FALSE;
272}
273
274static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
275 Manager *m = data;
276 Watch *w;
277
278 assert(timeout);
279 assert(m);
280
3df5bf61
LP
281 w = dbus_timeout_get_data(timeout);
282 if (!w)
ea430986
LP
283 return;
284
285 assert(w->type == WATCH_DBUS_TIMEOUT);
3df5bf61 286
ea430986
LP
287 assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
288 close_nointr_nofail(w->fd);
289 free(w);
290}
291
292static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
293 Manager *m = data;
294 Watch *w;
295 int r;
296
297 assert(timeout);
298 assert(m);
299
3df5bf61
LP
300 w = dbus_timeout_get_data(timeout);
301 if (!w)
302 return;
303
ea430986
LP
304 assert(w->type == WATCH_DBUS_TIMEOUT);
305
306 if ((r = bus_timeout_arm(m, w)) < 0)
307 log_error("Failed to rearm timer: %s", strerror(-r));
308}
309
cf3e2471 310static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
c1e1601e
LP
311 Manager *m = data;
312 DBusError error;
0034c15c 313 DBusMessage *reply = NULL;
c1e1601e
LP
314
315 assert(connection);
316 assert(message);
317 assert(m);
318
319 dbus_error_init(&error);
320
1e001f52
LP
321 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
322 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
323 log_debug("Got D-Bus request: %s.%s() on %s",
324 dbus_message_get_interface(message),
325 dbus_message_get_member(message),
326 dbus_message_get_path(message));
c1e1601e
LP
327
328 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
9028d0ec 329 log_debug("API D-Bus connection terminated.");
f278026d 330 bus_done_api(m);
c1e1601e
LP
331
332 } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
05e343b7 333 const char *name, *old_owner, *new_owner;
c1e1601e
LP
334
335 if (!dbus_message_get_args(message, &error,
336 DBUS_TYPE_STRING, &name,
05e343b7
LP
337 DBUS_TYPE_STRING, &old_owner,
338 DBUS_TYPE_STRING, &new_owner,
c1e1601e 339 DBUS_TYPE_INVALID))
a2e52832 340 log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
c1e1601e 341 else {
a567261a
LP
342 if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
343 log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
05e343b7
LP
344
345 if (old_owner[0] == 0)
346 old_owner = NULL;
347
348 if (new_owner[0] == 0)
349 new_owner = NULL;
350
351 manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
c1e1601e 352 }
0034c15c
LP
353 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
354 const char *name;
355
356 if (!dbus_message_get_args(message, &error,
357 DBUS_TYPE_STRING, &name,
358 DBUS_TYPE_INVALID))
a2e52832 359 log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
0034c15c
LP
360 else {
361 int r;
362 Unit *u;
363
46018844
LP
364 log_debug("Got D-Bus activation request for %s", name);
365
31afa0a4
LP
366 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
367 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
8f6df3fa
LP
368 r = -EADDRNOTAVAIL;
369 dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
370 } else {
371 r = manager_load_unit(m, name, NULL, &error, &u);
0034c15c 372
ac155bb8 373 if (r >= 0 && u->refuse_manual_start)
8f6df3fa 374 r = -EPERM;
0034c15c 375
8f6df3fa
LP
376 if (r >= 0)
377 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
378 }
0034c15c
LP
379
380 if (r < 0) {
381 const char *id, *text;
382
2a8cd298 383 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
af25ec12 384
0034c15c
LP
385 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
386 goto oom;
387
bfebab7f 388 id = error.name ? error.name : bus_errno_to_dbus(r);
398ef8ba 389 text = bus_error(&error, r);
0034c15c
LP
390
391 if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
392 !dbus_message_append_args(reply,
393 DBUS_TYPE_STRING, &name,
394 DBUS_TYPE_STRING, &id,
395 DBUS_TYPE_STRING, &text,
396 DBUS_TYPE_INVALID))
397 goto oom;
398 }
399
35b8ca3a 400 /* On success we don't do anything, the service will be spawned now */
0034c15c 401 }
c1e1601e
LP
402 }
403
404 dbus_error_free(&error);
0034c15c
LP
405
406 if (reply) {
c6a818c8 407 if (!bus_maybe_send_reply(connection, message, reply))
0034c15c
LP
408 goto oom;
409
410 dbus_message_unref(reply);
411 }
412
c1e1601e 413 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
0034c15c
LP
414
415oom:
416 if (reply)
417 dbus_message_unref(reply);
418
419 dbus_error_free(&error);
420
421 return DBUS_HANDLER_RESULT_NEED_MEMORY;
c1e1601e
LP
422}
423
cf3e2471 424static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
8e274523
LP
425 Manager *m = data;
426 DBusError error;
427
428 assert(connection);
429 assert(message);
430 assert(m);
431
432 dbus_error_init(&error);
433
1e001f52
LP
434 if (m->api_bus != m->system_bus &&
435 (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
436 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
437 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
438 dbus_message_get_interface(message),
439 dbus_message_get_member(message),
440 dbus_message_get_path(message));
8e274523
LP
441
442 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
91805b3b 443 log_debug("System D-Bus connection terminated.");
f278026d 444 bus_done_system(m);
8e274523 445
67445f4e 446 } else if (m->running_as != SYSTEMD_SYSTEM &&
53c6a358
LP
447 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
448
8e274523
LP
449 const char *cgroup;
450
451 if (!dbus_message_get_args(message, &error,
452 DBUS_TYPE_STRING, &cgroup,
453 DBUS_TYPE_INVALID))
19bc719e 454 log_error("Failed to parse Released message: %s", bus_error_message(&error));
8e274523
LP
455 else
456 cgroup_notify_empty(m, cgroup);
457 }
458
459 dbus_error_free(&error);
460 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
461}
462
5e8d1c9a
LP
463static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
464 Manager *m = data;
3c661fad 465 DBusError error;
5e8d1c9a
LP
466
467 assert(connection);
468 assert(message);
469 assert(m);
470
3c661fad
LP
471 dbus_error_init(&error);
472
1e001f52
LP
473 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
474 dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
475 log_debug("Got D-Bus request: %s.%s() on %s",
476 dbus_message_get_interface(message),
477 dbus_message_get_member(message),
478 dbus_message_get_path(message));
5e8d1c9a 479
923f8d76
LP
480 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
481 shutdown_connection(m, connection);
67445f4e 482 else if (m->running_as == SYSTEMD_SYSTEM &&
53c6a358
LP
483 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
484
3c661fad
LP
485 const char *cgroup;
486
487 if (!dbus_message_get_args(message, &error,
488 DBUS_TYPE_STRING, &cgroup,
489 DBUS_TYPE_INVALID))
a2e52832 490 log_error("Failed to parse Released message: %s", bus_error_message(&error));
3c661fad
LP
491 else
492 cgroup_notify_empty(m, cgroup);
53c6a358
LP
493
494 /* Forward the message to the system bus, so that user
495 * instances are notified as well */
496
497 if (m->system_bus)
498 dbus_connection_send(m->system_bus, message, NULL);
3c661fad
LP
499 }
500
501 dbus_error_free(&error);
5e8d1c9a
LP
502
503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
504}
505
c1e1601e 506unsigned bus_dispatch(Manager *m) {
5e8d1c9a
LP
507 DBusConnection *c;
508
ea430986
LP
509 assert(m);
510
a16e1123
LP
511 if (m->queued_message) {
512 /* If we cannot get rid of this message we won't
513 * dispatch any D-Bus messages, so that we won't end
514 * up wanting to queue another message. */
515
7b97f477
LP
516 if (m->queued_message_connection)
517 if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
5e8d1c9a 518 return 0;
a16e1123
LP
519
520 dbus_message_unref(m->queued_message);
521 m->queued_message = NULL;
7b97f477 522 m->queued_message_connection = NULL;
a16e1123
LP
523 }
524
5e8d1c9a
LP
525 if ((c = set_first(m->bus_connections_for_dispatch))) {
526 if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
527 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
fd18e1f4
LP
528
529 return 1;
530 }
c1e1601e 531
8e274523 532 return 0;
ea430986
LP
533}
534
05e343b7 535static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
61902ea3
LP
536 DBusMessage *reply;
537 DBusError error;
538
539 dbus_error_init(&error);
540
541 assert_se(reply = dbus_pending_call_steal_reply(pending));
542
543 switch (dbus_message_get_type(reply)) {
544
545 case DBUS_MESSAGE_TYPE_ERROR:
546
547 assert_se(dbus_set_error_from_message(&error, reply));
a2e52832 548 log_warning("RequestName() failed: %s", bus_error_message(&error));
61902ea3
LP
549 break;
550
551 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
552 uint32_t r;
553
554 if (!dbus_message_get_args(reply,
555 &error,
556 DBUS_TYPE_UINT32, &r,
557 DBUS_TYPE_INVALID)) {
a2e52832 558 log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
61902ea3
LP
559 break;
560 }
561
562 if (r == 1)
563 log_debug("Successfully acquired name.");
564 else
565 log_error("Name already owned.");
566
567 break;
568 }
569
570 default:
571 assert_not_reached("Invalid reply message");
572 }
573
574 dbus_message_unref(reply);
575 dbus_error_free(&error);
576}
577
ea430986 578static int request_name(Manager *m) {
ea430986 579 const char *name = "org.freedesktop.systemd1";
b23de6af
LP
580 /* Allow replacing of our name, to ease implementation of
581 * reexecution, where we keep the old connection open until
582 * after the new connection is set up and the name installed
583 * to allow clients to synchronously wait for reexecution to
584 * finish */
585 uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
05e343b7
LP
586 DBusMessage *message = NULL;
587 DBusPendingCall *pending = NULL;
ea430986
LP
588
589 if (!(message = dbus_message_new_method_call(
590 DBUS_SERVICE_DBUS,
591 DBUS_PATH_DBUS,
592 DBUS_INTERFACE_DBUS,
593 "RequestName")))
05e343b7 594 goto oom;
ea430986
LP
595
596 if (!dbus_message_append_args(
597 message,
598 DBUS_TYPE_STRING, &name,
599 DBUS_TYPE_UINT32, &flags,
05e343b7
LP
600 DBUS_TYPE_INVALID))
601 goto oom;
ea430986 602
05e343b7
LP
603 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
604 goto oom;
ea430986 605
05e343b7
LP
606 if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
607 goto oom;
ea430986
LP
608
609 dbus_message_unref(message);
61902ea3
LP
610 dbus_pending_call_unref(pending);
611
612 /* We simple ask for the name and don't wait for it. Sooner or
613 * later we'll have it. */
614
ea430986 615 return 0;
05e343b7
LP
616
617oom:
618 if (pending) {
619 dbus_pending_call_cancel(pending);
620 dbus_pending_call_unref(pending);
621 }
622
623 if (message)
624 dbus_message_unref(message);
625
626 return -ENOMEM;
ea430986
LP
627}
628
6dded4c7
LP
629static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
630 DBusMessage *reply;
631 DBusError error;
632 Manager *m = userdata;
633
634 assert(m);
635
636 dbus_error_init(&error);
637
638 assert_se(reply = dbus_pending_call_steal_reply(pending));
639
640 switch (dbus_message_get_type(reply)) {
641
642 case DBUS_MESSAGE_TYPE_ERROR:
643
644 assert_se(dbus_set_error_from_message(&error, reply));
a2e52832 645 log_warning("ListNames() failed: %s", bus_error_message(&error));
6dded4c7
LP
646 break;
647
648 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
649 int r;
650 char **l;
651
652 if ((r = bus_parse_strv(reply, &l)) < 0)
653 log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
654 else {
655 char **t;
656
657 STRV_FOREACH(t, l)
658 /* This is a bit hacky, we say the
659 * owner of the name is the name
660 * itself, because we don't want the
661 * extra traffic to figure out the
662 * real owner. */
663 manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
664
665 strv_free(l);
666 }
667
668 break;
669 }
670
671 default:
672 assert_not_reached("Invalid reply message");
673 }
674
675 dbus_message_unref(reply);
676 dbus_error_free(&error);
677}
678
679static int query_name_list(Manager *m) {
680 DBusMessage *message = NULL;
681 DBusPendingCall *pending = NULL;
682
683 /* Asks for the currently installed bus names */
684
685 if (!(message = dbus_message_new_method_call(
686 DBUS_SERVICE_DBUS,
687 DBUS_PATH_DBUS,
688 DBUS_INTERFACE_DBUS,
689 "ListNames")))
690 goto oom;
691
692 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
693 goto oom;
694
695 if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
696 goto oom;
697
698 dbus_message_unref(message);
699 dbus_pending_call_unref(pending);
700
701 /* We simple ask for the list and don't wait for it. Sooner or
702 * later we'll get it. */
703
704 return 0;
705
706oom:
707 if (pending) {
708 dbus_pending_call_cancel(pending);
709 dbus_pending_call_unref(pending);
710 }
711
712 if (message)
713 dbus_message_unref(message);
714
715 return -ENOMEM;
716}
717
8e274523
LP
718static int bus_setup_loop(Manager *m, DBusConnection *bus) {
719 assert(m);
720 assert(bus);
721
722 dbus_connection_set_exit_on_disconnect(bus, FALSE);
fd18e1f4 723
8e274523 724 if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
0d0f0c50
SL
725 !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
726 return log_oom();
8e274523 727
0d0f0c50
SL
728 if (set_put(m->bus_connections_for_dispatch, bus) < 0)
729 return log_oom();
5e8d1c9a
LP
730
731 dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
8e274523
LP
732 return 0;
733}
734
be81bfc4
LP
735static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
736 return uid == 0 || uid == geteuid();
5e8d1c9a
LP
737}
738
739static void bus_new_connection(
740 DBusServer *server,
741 DBusConnection *new_connection,
742 void *data) {
743
744 Manager *m = data;
745
746 assert(m);
747
748 if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
749 log_error("Too many concurrent connections.");
750 return;
751 }
752
be81bfc4 753 dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
5e8d1c9a
LP
754
755 if (bus_setup_loop(m, new_connection) < 0)
756 return;
757
758 if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
759 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
760 !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
761 !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
0d0f0c50 762 log_oom();
5e8d1c9a
LP
763 return;
764 }
765
766 log_debug("Accepted connection on private bus.");
767
768 dbus_connection_ref(new_connection);
769}
770
cbd37330
MS
771static int init_registered_system_bus(Manager *m) {
772 char *id;
f278026d 773
0d0f0c50
SL
774 if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
775 return log_oom();
c1e1601e 776
67445f4e 777 if (m->running_as != SYSTEMD_SYSTEM) {
cbd37330
MS
778 DBusError error;
779
780 dbus_error_init(&error);
781
53c6a358
LP
782 dbus_bus_add_match(m->system_bus,
783 "type='signal',"
784 "interface='org.freedesktop.systemd1.Agent',"
785 "member='Released',"
786 "path='/org/freedesktop/systemd1/agent'",
787 &error);
788
789 if (dbus_error_is_set(&error)) {
a2e52832 790 log_error("Failed to register match: %s", bus_error_message(&error));
cbd37330
MS
791 dbus_error_free(&error);
792 return -1;
53c6a358 793 }
ea430986
LP
794 }
795
cbd37330
MS
796 log_debug("Successfully connected to system D-Bus bus %s as %s",
797 strnull((id = dbus_connection_get_server_id(m->system_bus))),
798 strnull(dbus_bus_get_unique_name(m->system_bus)));
799 dbus_free(id);
f278026d 800
f278026d
LP
801 return 0;
802}
803
cbd37330 804static int init_registered_api_bus(Manager *m) {
f278026d
LP
805 int r;
806
f278026d
LP
807 if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
808 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
809 !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
0d0f0c50
SL
810 !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
811 return log_oom();
f278026d 812
0034c15c 813 /* Get NameOwnerChange messages */
f278026d 814 dbus_bus_add_match(m->api_bus,
8e274523 815 "type='signal',"
f278026d
LP
816 "sender='"DBUS_SERVICE_DBUS"',"
817 "interface='"DBUS_INTERFACE_DBUS"',"
fd0d7f7a 818 "member='NameOwnerChanged',"
f278026d 819 "path='"DBUS_PATH_DBUS"'",
cbd37330 820 NULL);
8e274523 821
0034c15c
LP
822 /* Get activation requests */
823 dbus_bus_add_match(m->api_bus,
824 "type='signal',"
825 "sender='"DBUS_SERVICE_DBUS"',"
826 "interface='org.freedesktop.systemd1.Activator',"
cf3e2471 827 "member='ActivationRequest',"
0034c15c 828 "path='"DBUS_PATH_DBUS"'",
cbd37330 829 NULL);
0034c15c 830
cbd37330
MS
831 r = request_name(m);
832 if (r < 0)
833 return r;
ea430986 834
cbd37330
MS
835 r = query_name_list(m);
836 if (r < 0)
837 return r;
6dded4c7 838
67445f4e 839 if (m->running_as == SYSTEMD_USER) {
9014a8bd 840 char *id;
91805b3b 841 log_debug("Successfully connected to API D-Bus bus %s as %s",
9014a8bd
LP
842 strnull((id = dbus_connection_get_server_id(m->api_bus))),
843 strnull(dbus_bus_get_unique_name(m->api_bus)));
844 dbus_free(id);
cbd37330
MS
845 } else
846 log_debug("Successfully initialized API on the system bus");
847
848 return 0;
849}
850
851static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
852 Manager *m = userdata;
853 DBusConnection **conn;
854 DBusMessage *reply;
855 DBusError error;
856 const char *name;
857 int r = 0;
858
859 dbus_error_init(&error);
860
861 conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
862 assert(conn == &m->system_bus || conn == &m->api_bus);
863
864 reply = dbus_pending_call_steal_reply(pending);
865
866 switch (dbus_message_get_type(reply)) {
867 case DBUS_MESSAGE_TYPE_ERROR:
868 assert_se(dbus_set_error_from_message(&error, reply));
869 log_warning("Failed to register to bus: %s", bus_error_message(&error));
870 r = -1;
871 break;
872 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
873 if (!dbus_message_get_args(reply, &error,
874 DBUS_TYPE_STRING, &name,
875 DBUS_TYPE_INVALID)) {
876 log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
877 r = -1;
878 break;
879 }
880
881 log_debug("Received name %s in reply to Hello", name);
882 if (!dbus_bus_set_unique_name(*conn, name)) {
883 log_error("Failed to set unique name");
884 r = -1;
885 break;
886 }
887
888 if (conn == &m->system_bus) {
889 r = init_registered_system_bus(m);
67445f4e 890 if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
cbd37330
MS
891 r = init_registered_api_bus(m);
892 } else
893 r = init_registered_api_bus(m);
894
895 break;
896 default:
897 assert_not_reached("Invalid reply message");
898 }
899
900 dbus_message_unref(reply);
901 dbus_error_free(&error);
902
903 if (r < 0) {
904 if (conn == &m->system_bus) {
905 log_debug("Failed setting up the system bus");
906 bus_done_system(m);
907 } else {
908 log_debug("Failed setting up the API bus");
909 bus_done_api(m);
910 }
911 }
912}
913
914static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
915 DBusMessage *message = NULL;
916 DBusPendingCall *pending = NULL;
917
918 message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
919 DBUS_PATH_DBUS,
920 DBUS_INTERFACE_DBUS,
921 "Hello");
922 if (!message)
923 goto oom;
924
925 if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
926 goto oom;
927
928 if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
929 goto oom;
930
931 if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
932 goto oom;
933
934 dbus_message_unref(message);
935 dbus_pending_call_unref(pending);
936
937 return 0;
938oom:
939 if (pending) {
940 dbus_pending_call_cancel(pending);
941 dbus_pending_call_unref(pending);
942 }
943
944 if (message)
945 dbus_message_unref(message);
946
947 return -ENOMEM;
948}
949
950static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
951 const char *address;
952 DBusConnection *connection;
953 DBusError error;
954
955 switch (type) {
956 case DBUS_BUS_SYSTEM:
4db17f29 957 address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
cbd37330
MS
958 if (!address || !address[0])
959 address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
960 break;
961 case DBUS_BUS_SESSION:
4db17f29 962 address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
cbd37330
MS
963 if (!address || !address[0])
964 address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
965 break;
966 default:
967 assert_not_reached("Invalid bus type");
968 }
969
970 dbus_error_init(&error);
971
972 connection = dbus_connection_open_private(address, &error);
973 if (!connection) {
974 log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
975 goto fail;
976 }
977
978 return connection;
4dd1de72 979
cbd37330 980fail:
cbd37330
MS
981 dbus_error_free(&error);
982 return NULL;
983}
984
985static int bus_init_system(Manager *m) {
986 int r;
987
988 if (m->system_bus)
989 return 0;
990
991 m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
992 if (!m->system_bus) {
993 log_debug("Failed to connect to system D-Bus, retrying later");
994 r = 0;
995 goto fail;
9014a8bd 996 }
8e274523 997
cbd37330
MS
998 r = bus_setup_loop(m, m->system_bus);
999 if (r < 0)
1000 goto fail;
1001
1002 r = manager_bus_async_register(m, &m->system_bus);
1003 if (r < 0)
1004 goto fail;
1005
5e8d1c9a 1006 return 0;
cbd37330
MS
1007fail:
1008 bus_done_system(m);
1009
1010 return r;
1011}
1012
1013static int bus_init_api(Manager *m) {
1014 int r;
1015
1016 if (m->api_bus)
1017 return 0;
1018
67445f4e 1019 if (m->running_as == SYSTEMD_SYSTEM) {
cbd37330
MS
1020 m->api_bus = m->system_bus;
1021 /* In this mode there is no distinct connection to the API bus,
1022 * the API is published on the system bus.
1023 * bus_register_cb() is aware of that and will init the API
1024 * when the system bus gets registered.
1025 * No need to setup anything here. */
1026 return 0;
1027 }
1028
1029 m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
1030 if (!m->api_bus) {
1031 log_debug("Failed to connect to API D-Bus, retrying later");
1032 r = 0;
1033 goto fail;
1034 }
1035
1036 r = bus_setup_loop(m, m->api_bus);
1037 if (r < 0)
1038 goto fail;
5e8d1c9a 1039
cbd37330
MS
1040 r = manager_bus_async_register(m, &m->api_bus);
1041 if (r < 0)
1042 goto fail;
1043
1044 return 0;
5e8d1c9a
LP
1045fail:
1046 bus_done_api(m);
5e8d1c9a
LP
1047
1048 return r;
1049}
1050
1051static int bus_init_private(Manager *m) {
1052 DBusError error;
1053 int r;
166de425 1054 static const char *const external_only[] = {
5e8d1c9a
LP
1055 "EXTERNAL",
1056 NULL
1057 };
1058
1059 assert(m);
1060
1061 dbus_error_init(&error);
1062
1063 if (m->private_bus)
1064 return 0;
1065
67445f4e 1066 if (m->running_as == SYSTEMD_SYSTEM) {
be81bfc4
LP
1067
1068 /* We want the private bus only when running as init */
1069 if (getpid() != 1)
1070 return 0;
1071
1072 unlink("/run/systemd/private");
1073 m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
1074 } else {
1075 const char *e;
1076 char *p;
92f30349 1077 char *escaped;
be81bfc4 1078
4db17f29 1079 e = secure_getenv("XDG_RUNTIME_DIR");
be81bfc4
LP
1080 if (!e)
1081 return 0;
1082
92f30349 1083 if (asprintf(&p, "%s/systemd/private", e) < 0) {
0d0f0c50 1084 r = log_oom();
be81bfc4
LP
1085 goto fail;
1086 }
1087
92f30349
SM
1088 mkdir_parents_label(p, 0755);
1089 unlink(p);
1090 free(p);
1091
1092 escaped = dbus_address_escape_value(e);
1093 if (!escaped) {
1094 r = log_oom();
1095 goto fail;
1096 }
1097 if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) {
1098 dbus_free(escaped);
1099 r = log_oom();
1100 goto fail;
1101 }
1102 dbus_free(escaped);
1103
be81bfc4
LP
1104 m->private_bus = dbus_server_listen(p, &error);
1105 free(p);
1106 }
5e8d1c9a 1107
be81bfc4 1108 if (!m->private_bus) {
a2e52832 1109 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
5e8d1c9a
LP
1110 r = -EIO;
1111 goto fail;
1112 }
1113
1114 if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1115 !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1116 !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
0d0f0c50 1117 r = log_oom();
5e8d1c9a
LP
1118 goto fail;
1119 }
1120
1121 dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1122
54165a39 1123 log_debug("Successfully created private D-Bus server.");
5e8d1c9a
LP
1124
1125 return 0;
1126
1127fail:
1128 bus_done_private(m);
1129 dbus_error_free(&error);
1130
1131 return r;
1132}
1133
3996fbe2 1134int bus_init(Manager *m, bool try_bus_connect) {
5e8d1c9a
LP
1135 int r;
1136
1137 if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
cbd37330
MS
1138 set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1139 goto oom;
5e8d1c9a
LP
1140
1141 if (m->name_data_slot < 0)
cbd37330
MS
1142 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1143 goto oom;
1144
1145 if (m->conn_data_slot < 0)
1146 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1147 goto oom;
5e8d1c9a 1148
a567261a 1149 if (m->subscribed_data_slot < 0)
cbd37330
MS
1150 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1151 goto oom;
a567261a 1152
3996fbe2
LP
1153 if (try_bus_connect) {
1154 if ((r = bus_init_system(m)) < 0 ||
1155 (r = bus_init_api(m)) < 0)
1156 return r;
1157 }
1158
1159 if ((r = bus_init_private(m)) < 0)
5e8d1c9a 1160 return r;
f278026d 1161
ea430986 1162 return 0;
cbd37330 1163oom:
0d0f0c50 1164 return log_oom();
ea430986
LP
1165}
1166
fae20b11 1167static void shutdown_connection(Manager *m, DBusConnection *c) {
a567261a
LP
1168 Set *s;
1169 Job *j;
1170 Iterator i;
1171
97e6a119
MS
1172 HASHMAP_FOREACH(j, m->jobs, i) {
1173 JobBusClient *cl, *nextcl;
1174 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1175 if (cl->bus == c) {
1176 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
1177 free(cl);
1178 }
a567261a 1179 }
97e6a119 1180 }
a567261a 1181
fae20b11
LP
1182 set_remove(m->bus_connections, c);
1183 set_remove(m->bus_connections_for_dispatch, c);
1184
a567261a
LP
1185 if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
1186 char *t;
1187
1188 while ((t = set_steal_first(s)))
1189 free(t);
1190
1191 set_free(s);
1192 }
1193
7b97f477
LP
1194 if (m->queued_message_connection == c) {
1195 m->queued_message_connection = NULL;
1196
1197 if (m->queued_message) {
1198 dbus_message_unref(m->queued_message);
1199 m->queued_message = NULL;
1200 }
1201 }
1202
5e8d1c9a 1203 dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
9721b199 1204 /* system manager cannot afford to block on DBus */
67445f4e 1205 if (m->running_as != SYSTEMD_SYSTEM)
9721b199 1206 dbus_connection_flush(c);
5e8d1c9a
LP
1207 dbus_connection_close(c);
1208 dbus_connection_unref(c);
1209}
1210
1211static void bus_done_api(Manager *m) {
cbd37330
MS
1212 if (!m->api_bus)
1213 return;
f278026d 1214
67445f4e 1215 if (m->running_as == SYSTEMD_USER)
fae20b11 1216 shutdown_connection(m, m->api_bus);
c1e1601e 1217
cbd37330 1218 m->api_bus = NULL;
05e343b7 1219
cbd37330
MS
1220 if (m->queued_message) {
1221 dbus_message_unref(m->queued_message);
1222 m->queued_message = NULL;
1223 }
ea430986
LP
1224}
1225
5e8d1c9a 1226static void bus_done_system(Manager *m) {
cbd37330
MS
1227 if (!m->system_bus)
1228 return;
f278026d 1229
67445f4e 1230 if (m->running_as == SYSTEMD_SYSTEM)
f278026d
LP
1231 bus_done_api(m);
1232
cbd37330
MS
1233 shutdown_connection(m, m->system_bus);
1234 m->system_bus = NULL;
f278026d
LP
1235}
1236
5e8d1c9a 1237static void bus_done_private(Manager *m) {
cbd37330
MS
1238 if (!m->private_bus)
1239 return;
5e8d1c9a 1240
cbd37330
MS
1241 dbus_server_disconnect(m->private_bus);
1242 dbus_server_unref(m->private_bus);
1243 m->private_bus = NULL;
5e8d1c9a
LP
1244}
1245
1246void bus_done(Manager *m) {
1247 DBusConnection *c;
1248
1249 bus_done_api(m);
1250 bus_done_system(m);
1251 bus_done_private(m);
1252
1253 while ((c = set_steal_first(m->bus_connections)))
fae20b11 1254 shutdown_connection(m, c);
5e8d1c9a
LP
1255
1256 while ((c = set_steal_first(m->bus_connections_for_dispatch)))
fae20b11 1257 shutdown_connection(m, c);
5e8d1c9a
LP
1258
1259 set_free(m->bus_connections);
1260 set_free(m->bus_connections_for_dispatch);
1261
1262 if (m->name_data_slot >= 0)
1263 dbus_pending_call_free_data_slot(&m->name_data_slot);
a567261a 1264
cbd37330
MS
1265 if (m->conn_data_slot >= 0)
1266 dbus_pending_call_free_data_slot(&m->conn_data_slot);
1267
a567261a 1268 if (m->subscribed_data_slot >= 0)
d83685ac 1269 dbus_connection_free_data_slot(&m->subscribed_data_slot);
5e8d1c9a
LP
1270}
1271
05e343b7
LP
1272static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1273 Manager *m = userdata;
1274 DBusMessage *reply;
1275 DBusError error;
1276 const char *name;
1277
1278 dbus_error_init(&error);
1279
a567261a 1280 assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
05e343b7
LP
1281 assert_se(reply = dbus_pending_call_steal_reply(pending));
1282
1283 switch (dbus_message_get_type(reply)) {
1284
1285 case DBUS_MESSAGE_TYPE_ERROR:
1286
1287 assert_se(dbus_set_error_from_message(&error, reply));
a2e52832 1288 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
05e343b7
LP
1289 break;
1290
1291 case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1292 uint32_t r;
1293
1294 if (!dbus_message_get_args(reply,
1295 &error,
1296 DBUS_TYPE_UINT32, &r,
1297 DBUS_TYPE_INVALID)) {
a2e52832 1298 log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
05e343b7
LP
1299 break;
1300 }
1301
1302 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1303 break;
1304 }
1305
1306 default:
1307 assert_not_reached("Invalid reply message");
1308 }
1309
1310 dbus_message_unref(reply);
1311 dbus_error_free(&error);
1312}
1313
1314int bus_query_pid(Manager *m, const char *name) {
1315 DBusMessage *message = NULL;
1316 DBusPendingCall *pending = NULL;
1317 char *n = NULL;
1318
1319 assert(m);
1320 assert(name);
1321
1322 if (!(message = dbus_message_new_method_call(
1323 DBUS_SERVICE_DBUS,
1324 DBUS_PATH_DBUS,
1325 DBUS_INTERFACE_DBUS,
1326 "GetConnectionUnixProcessID")))
1327 goto oom;
1328
1329 if (!(dbus_message_append_args(
1330 message,
1331 DBUS_TYPE_STRING, &name,
1332 DBUS_TYPE_INVALID)))
1333 goto oom;
1334
1335 if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1336 goto oom;
1337
1338 if (!(n = strdup(name)))
1339 goto oom;
1340
1341 if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1342 goto oom;
1343
1344 n = NULL;
1345
1346 if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1347 goto oom;
1348
1349 dbus_message_unref(message);
1350 dbus_pending_call_unref(pending);
1351
1352 return 0;
1353
1354oom:
1355 free(n);
1356
1357 if (pending) {
1358 dbus_pending_call_cancel(pending);
1359 dbus_pending_call_unref(pending);
1360 }
1361
1362 if (message)
1363 dbus_message_unref(message);
1364
1365 return -ENOMEM;
1366}
1367
5e8d1c9a
LP
1368int bus_broadcast(Manager *m, DBusMessage *message) {
1369 bool oom = false;
1370 Iterator i;
1371 DBusConnection *c;
1372
1373 assert(m);
1374 assert(message);
1375
1376 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
67445f4e 1377 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
5e8d1c9a
LP
1378 oom = !dbus_connection_send(c, message, NULL);
1379
1380 SET_FOREACH(c, m->bus_connections, i)
67445f4e 1381 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
5e8d1c9a
LP
1382 oom = !dbus_connection_send(c, message, NULL);
1383
1384 return oom ? -ENOMEM : 0;
1385}
1386
a567261a
LP
1387bool bus_has_subscriber(Manager *m) {
1388 Iterator i;
1389 DBusConnection *c;
1390
1391 assert(m);
1392
1393 SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1394 if (bus_connection_has_subscriber(m, c))
1395 return true;
1396
1397 SET_FOREACH(c, m->bus_connections, i)
1398 if (bus_connection_has_subscriber(m, c))
1399 return true;
1400
1401 return false;
1402}
1403
1404bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1405 assert(m);
1406 assert(c);
1407
1408 return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1409}
b23de6af
LP
1410
1411int bus_fdset_add_all(Manager *m, FDSet *fds) {
1412 Iterator i;
1413 DBusConnection *c;
1414
1415 assert(m);
1416 assert(fds);
1417
1418 /* When we are about to reexecute we add all D-Bus fds to the
1419 * set to pass over to the newly executed systemd. They won't
1420 * be used there however, except that they are closed at the
1421 * very end of deserialization, those making it possible for
44143309 1422 * clients to synchronously wait for systemd to reexec by
b23de6af
LP
1423 * simply waiting for disconnection */
1424
1425 SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1426 int fd;
1427
1428 if (dbus_connection_get_unix_fd(c, &fd)) {
1429 fd = fdset_put_dup(fds, fd);
1430
1431 if (fd < 0)
1432 return fd;
1433 }
1434 }
1435
1436 SET_FOREACH(c, m->bus_connections, i) {
1437 int fd;
1438
1439 if (dbus_connection_get_unix_fd(c, &fd)) {
1440 fd = fdset_put_dup(fds, fd);
1441
1442 if (fd < 0)
1443 return fd;
1444 }
1445 }
1446
1447 return 0;
1448}
18fa6b27
LP
1449
1450void bus_broadcast_finished(
1451 Manager *m,
915b3753
LP
1452 usec_t firmware_usec,
1453 usec_t loader_usec,
18fa6b27
LP
1454 usec_t kernel_usec,
1455 usec_t initrd_usec,
1456 usec_t userspace_usec,
1457 usec_t total_usec) {
1458
1459 DBusMessage *message;
1460
1461 assert(m);
1462
1463 message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1464 if (!message) {
0d0f0c50 1465 log_oom();
18fa6b27
LP
1466 return;
1467 }
1468
1469 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1470 if (!dbus_message_append_args(message,
915b3753
LP
1471 DBUS_TYPE_UINT64, &firmware_usec,
1472 DBUS_TYPE_UINT64, &loader_usec,
18fa6b27
LP
1473 DBUS_TYPE_UINT64, &kernel_usec,
1474 DBUS_TYPE_UINT64, &initrd_usec,
1475 DBUS_TYPE_UINT64, &userspace_usec,
1476 DBUS_TYPE_UINT64, &total_usec,
1477 DBUS_TYPE_INVALID)) {
0d0f0c50 1478 log_oom();
18fa6b27
LP
1479 goto finish;
1480 }
1481
1482
1483 if (bus_broadcast(m, message) < 0) {
0d0f0c50 1484 log_oom();
18fa6b27
LP
1485 goto finish;
1486 }
1487
1488finish:
c99ddfaa 1489 if (message)
18fa6b27
LP
1490 dbus_message_unref(message);
1491}