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