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