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