chiark / gitweb /
sd-journal: do not require path to be absolute
[elogind.git] / src / core / dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
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
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
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
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <dbus/dbus.h>
27
28 #include "dbus.h"
29 #include "log.h"
30 #include "strv.h"
31 #include "cgroup.h"
32 #include "mkdir.h"
33 #include "missing.h"
34 #include "dbus-unit.h"
35 #include "dbus-job.h"
36 #include "dbus-manager.h"
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"
45 #include "dbus-timer.h"
46 #include "dbus-path.h"
47 #include "bus-errors.h"
48 #include "special.h"
49 #include "dbus-common.h"
50
51 #define CONNECTIONS_MAX 52
52
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
58 static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
59 static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
60
61 const 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,
75         "org.freedesktop.systemd1.Timer",      bus_timer_interface,
76         "org.freedesktop.systemd1.Path",       bus_path_interface,
77         NULL
78 };
79
80 static void bus_done_api(Manager *m);
81 static void bus_done_system(Manager *m);
82 static void bus_done_private(Manager *m);
83 static void shutdown_connection(Manager *m, DBusConnection *c);
84
85 static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data)  {
86         Manager *m = data;
87
88         assert(bus);
89         assert(m);
90
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. */
94
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);
99 }
100
101 void 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
108         if (!dbus_watch_get_enabled(w->data.bus_watch))
109                 return;
110
111         dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
112 }
113
114 static 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) {
151                         close_nointr_nofail(w->fd);
152                         free(w);
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
164 static 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
171         w = dbus_watch_get_data(bus_watch);
172         if (!w)
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
184 static 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
192         w = dbus_watch_get_data(bus_watch);
193         if (!w)
194                 return;
195
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
205 static 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);
215                 its.it_interval = its.it_value;
216         }
217
218         if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
219                 return -errno;
220
221         return 0;
222 }
223
224 void 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
237 static 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
248         if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
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
268 fail:
269         if (w->fd >= 0)
270                 close_nointr_nofail(w->fd);
271
272         free(w);
273         return FALSE;
274 }
275
276 static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
277         Manager *m = data;
278         Watch *w;
279
280         assert(timeout);
281         assert(m);
282
283         w = dbus_timeout_get_data(timeout);
284         if (!w)
285                 return;
286
287         assert(w->type == WATCH_DBUS_TIMEOUT);
288
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
294 static 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
302         w = dbus_timeout_get_data(timeout);
303         if (!w)
304                 return;
305
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
312 static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
313         Manager *m = data;
314         DBusError error;
315         DBusMessage *reply = NULL;
316
317         assert(connection);
318         assert(message);
319         assert(m);
320
321         dbus_error_init(&error);
322
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));
329
330         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
331                 log_debug("API D-Bus connection terminated.");
332                 bus_done_api(m);
333
334         } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
335                 const char *name, *old_owner, *new_owner;
336
337                 if (!dbus_message_get_args(message, &error,
338                                            DBUS_TYPE_STRING, &name,
339                                            DBUS_TYPE_STRING, &old_owner,
340                                            DBUS_TYPE_STRING, &new_owner,
341                                            DBUS_TYPE_INVALID))
342                         log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
343                 else  {
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)));
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);
354                 }
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))
361                         log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
362                 else  {
363                         int r;
364                         Unit *u;
365
366                         log_debug("Got D-Bus activation request for %s", name);
367
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);
374
375                                 if (r >= 0 && u->refuse_manual_start)
376                                         r = -EPERM;
377
378                                 if (r >= 0)
379                                         r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
380                         }
381
382                         if (r < 0) {
383                                 const char *id, *text;
384
385                                 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
386
387                                 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
388                                         goto oom;
389
390                                 id = error.name ? error.name : bus_errno_to_dbus(r);
391                                 text = bus_error(&error, r);
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
402                         /* On success we don't do anything, the service will be spawned now */
403                 }
404         }
405
406         dbus_error_free(&error);
407
408         if (reply) {
409                 if (!dbus_connection_send(connection, reply, NULL))
410                         goto oom;
411
412                 dbus_message_unref(reply);
413         }
414
415         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
416
417 oom:
418         if (reply)
419                 dbus_message_unref(reply);
420
421         dbus_error_free(&error);
422
423         return DBUS_HANDLER_RESULT_NEED_MEMORY;
424 }
425
426 static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
427         Manager *m = data;
428         DBusError error;
429
430         assert(connection);
431         assert(message);
432         assert(m);
433
434         dbus_error_init(&error);
435
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));
443
444         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
445                 log_debug("System D-Bus connection terminated.");
446                 bus_done_system(m);
447
448         } else if (m->running_as != SYSTEMD_SYSTEM &&
449                    dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
450
451                 const char *cgroup;
452
453                 if (!dbus_message_get_args(message, &error,
454                                            DBUS_TYPE_STRING, &cgroup,
455                                            DBUS_TYPE_INVALID))
456                         log_error("Failed to parse Released message: %s", bus_error_message(&error));
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
465 static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
466         Manager *m = data;
467         DBusError error;
468
469         assert(connection);
470         assert(message);
471         assert(m);
472
473         dbus_error_init(&error);
474
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));
481
482         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
483                 shutdown_connection(m, connection);
484         else if (m->running_as == SYSTEMD_SYSTEM &&
485                  dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
486
487                 const char *cgroup;
488
489                 if (!dbus_message_get_args(message, &error,
490                                            DBUS_TYPE_STRING, &cgroup,
491                                            DBUS_TYPE_INVALID))
492                         log_error("Failed to parse Released message: %s", bus_error_message(&error));
493                 else
494                         cgroup_notify_empty(m, cgroup);
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);
501         }
502
503         dbus_error_free(&error);
504
505         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
506 }
507
508 unsigned bus_dispatch(Manager *m) {
509         DBusConnection *c;
510
511         assert(m);
512
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
518                 if (m->queued_message_connection)
519                         if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
520                                 return 0;
521
522                 dbus_message_unref(m->queued_message);
523                 m->queued_message = NULL;
524                 m->queued_message_connection = NULL;
525         }
526
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);
530
531                 return 1;
532         }
533
534         return 0;
535 }
536
537 static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
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));
550                 log_warning("RequestName() failed: %s", bus_error_message(&error));
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)) {
560                         log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
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
580 static int request_name(Manager *m) {
581         const char *name = "org.freedesktop.systemd1";
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;
588         DBusMessage *message = NULL;
589         DBusPendingCall *pending = NULL;
590
591         if (!(message = dbus_message_new_method_call(
592                               DBUS_SERVICE_DBUS,
593                               DBUS_PATH_DBUS,
594                               DBUS_INTERFACE_DBUS,
595                               "RequestName")))
596                 goto oom;
597
598         if (!dbus_message_append_args(
599                             message,
600                             DBUS_TYPE_STRING, &name,
601                             DBUS_TYPE_UINT32, &flags,
602                             DBUS_TYPE_INVALID))
603                 goto oom;
604
605         if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
606                 goto oom;
607
608         if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
609                 goto oom;
610
611         dbus_message_unref(message);
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
617         return 0;
618
619 oom:
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;
629 }
630
631 static 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));
647                 log_warning("ListNames() failed: %s", bus_error_message(&error));
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
681 static 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
708 oom:
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
720 static int bus_setup_loop(Manager *m, DBusConnection *bus) {
721         assert(m);
722         assert(bus);
723
724         dbus_connection_set_exit_on_disconnect(bus, FALSE);
725
726         if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
727             !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
728                 return log_oom();
729
730         if (set_put(m->bus_connections_for_dispatch, bus) < 0)
731                 return log_oom();
732
733         dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
734         return 0;
735 }
736
737 static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
738         return uid == 0 || uid == geteuid();
739 }
740
741 static 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
755         dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
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)) {
764                 log_oom();
765                 return;
766         }
767
768         log_debug("Accepted connection on private bus.");
769
770         dbus_connection_ref(new_connection);
771 }
772
773 static int init_registered_system_bus(Manager *m) {
774         char *id;
775
776         if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
777                 return log_oom();
778
779         if (m->running_as != SYSTEMD_SYSTEM) {
780                 DBusError error;
781
782                 dbus_error_init(&error);
783
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)) {
792                         log_error("Failed to register match: %s", bus_error_message(&error));
793                         dbus_error_free(&error);
794                         return -1;
795                 }
796         }
797
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);
802
803         return 0;
804 }
805
806 static int init_registered_api_bus(Manager *m) {
807         int r;
808
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) ||
812             !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
813                 return log_oom();
814
815         /* Get NameOwnerChange messages */
816         dbus_bus_add_match(m->api_bus,
817                            "type='signal',"
818                            "sender='"DBUS_SERVICE_DBUS"',"
819                            "interface='"DBUS_INTERFACE_DBUS"',"
820                            "member='NameOwnerChanged',"
821                            "path='"DBUS_PATH_DBUS"'",
822                            NULL);
823
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',"
829                            "member='ActivationRequest',"
830                            "path='"DBUS_PATH_DBUS"'",
831                            NULL);
832
833         r = request_name(m);
834         if (r < 0)
835                 return r;
836
837         r = query_name_list(m);
838         if (r < 0)
839                 return r;
840
841         if (m->running_as == SYSTEMD_USER) {
842                 char *id;
843                 log_debug("Successfully connected to API D-Bus bus %s as %s",
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);
847         } else
848                 log_debug("Successfully initialized API on the system bus");
849
850         return 0;
851 }
852
853 static 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);
892                         if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
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
916 static 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;
940 oom:
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
952 static 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:
959                 address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
960                 if (!address || !address[0])
961                         address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
962                 break;
963         case DBUS_BUS_SESSION:
964                 address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
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;
981 fail:
982         if (connection)
983                 dbus_connection_close(connection);
984         dbus_error_free(&error);
985         return NULL;
986 }
987
988 static 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;
999         }
1000
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
1009         return 0;
1010 fail:
1011         bus_done_system(m);
1012
1013         return r;
1014 }
1015
1016 static int bus_init_api(Manager *m) {
1017         int r;
1018
1019         if (m->api_bus)
1020                 return 0;
1021
1022         if (m->running_as == SYSTEMD_SYSTEM) {
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;
1042
1043         r = manager_bus_async_register(m, &m->api_bus);
1044         if (r < 0)
1045                 goto fail;
1046
1047         return 0;
1048 fail:
1049         bus_done_api(m);
1050
1051         return r;
1052 }
1053
1054 static 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
1069         if (m->running_as == SYSTEMD_SYSTEM) {
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;
1080                 char *escaped;
1081
1082                 e = secure_getenv("XDG_RUNTIME_DIR");
1083                 if (!e)
1084                         return 0;
1085
1086                 if (asprintf(&p, "%s/systemd/private", e) < 0) {
1087                         r = log_oom();
1088                         goto fail;
1089                 }
1090
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
1107                 m->private_bus = dbus_server_listen(p, &error);
1108                 free(p);
1109         }
1110
1111         if (!m->private_bus) {
1112                 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
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)) {
1120                 r = log_oom();
1121                 goto fail;
1122         }
1123
1124         dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1125
1126         log_debug("Successfully created private D-Bus server.");
1127
1128         return 0;
1129
1130 fail:
1131         bus_done_private(m);
1132         dbus_error_free(&error);
1133
1134         return r;
1135 }
1136
1137 int bus_init(Manager *m, bool try_bus_connect) {
1138         int r;
1139
1140         if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1141             set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1142                 goto oom;
1143
1144         if (m->name_data_slot < 0)
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;
1151
1152         if (m->subscribed_data_slot < 0)
1153                 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1154                         goto oom;
1155
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)
1163                 return r;
1164
1165         return 0;
1166 oom:
1167         return log_oom();
1168 }
1169
1170 static void shutdown_connection(Manager *m, DBusConnection *c) {
1171         Set *s;
1172         Job *j;
1173         Iterator i;
1174
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                         }
1182                 }
1183         }
1184
1185         set_remove(m->bus_connections, c);
1186         set_remove(m->bus_connections_for_dispatch, c);
1187
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
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
1206         dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1207         /* system manager cannot afford to block on DBus */
1208         if (m->running_as != SYSTEMD_SYSTEM)
1209                 dbus_connection_flush(c);
1210         dbus_connection_close(c);
1211         dbus_connection_unref(c);
1212 }
1213
1214 static void bus_done_api(Manager *m) {
1215         if (!m->api_bus)
1216                 return;
1217
1218         if (m->running_as == SYSTEMD_USER)
1219                 shutdown_connection(m, m->api_bus);
1220
1221         m->api_bus = NULL;
1222
1223         if (m->queued_message) {
1224                 dbus_message_unref(m->queued_message);
1225                 m->queued_message = NULL;
1226         }
1227 }
1228
1229 static void bus_done_system(Manager *m) {
1230         if (!m->system_bus)
1231                 return;
1232
1233         if (m->running_as == SYSTEMD_SYSTEM)
1234                 bus_done_api(m);
1235
1236         shutdown_connection(m, m->system_bus);
1237         m->system_bus = NULL;
1238 }
1239
1240 static void bus_done_private(Manager *m) {
1241         if (!m->private_bus)
1242                 return;
1243
1244         dbus_server_disconnect(m->private_bus);
1245         dbus_server_unref(m->private_bus);
1246         m->private_bus = NULL;
1247 }
1248
1249 void 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)))
1257                 shutdown_connection(m, c);
1258
1259         while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1260                 shutdown_connection(m, c);
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);
1267
1268         if (m->conn_data_slot >= 0)
1269                dbus_pending_call_free_data_slot(&m->conn_data_slot);
1270
1271         if (m->subscribed_data_slot >= 0)
1272                 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1273 }
1274
1275 static 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
1283         assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
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));
1291                 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
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)) {
1301                         log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
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
1317 int 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
1357 oom:
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
1371 int 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)
1380                 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1381                         oom = !dbus_connection_send(c, message, NULL);
1382
1383         SET_FOREACH(c, m->bus_connections, i)
1384                 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1385                         oom = !dbus_connection_send(c, message, NULL);
1386
1387         return oom ? -ENOMEM : 0;
1388 }
1389
1390 bool 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
1407 bool 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 }
1413
1414 int 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
1425          * clients to synchronously wait for systemd to reexec by
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 }
1452
1453 void bus_broadcast_finished(
1454                 Manager *m,
1455                 usec_t firmware_usec,
1456                 usec_t loader_usec,
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) {
1468                 log_oom();
1469                 return;
1470         }
1471
1472         assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1473         if (!dbus_message_append_args(message,
1474                                       DBUS_TYPE_UINT64, &firmware_usec,
1475                                       DBUS_TYPE_UINT64, &loader_usec,
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)) {
1481                 log_oom();
1482                 goto finish;
1483         }
1484
1485
1486         if (bus_broadcast(m, message) < 0) {
1487                 log_oom();
1488                 goto finish;
1489         }
1490
1491 finish:
1492         if (message)
1493                 dbus_message_unref(message);
1494 }