chiark / gitweb /
log.h: new log_oom() -> int -ENOMEM, use it
[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 "dbus-unit.h"
34 #include "dbus-job.h"
35 #include "dbus-manager.h"
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"
44 #include "dbus-timer.h"
45 #include "dbus-path.h"
46 #include "bus-errors.h"
47 #include "special.h"
48 #include "dbus-common.h"
49
50 #define CONNECTIONS_MAX 52
51
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
57 static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
58 static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
59
60 const 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,
74         "org.freedesktop.systemd1.Timer",      bus_timer_interface,
75         "org.freedesktop.systemd1.Path",       bus_path_interface,
76         NULL
77 };
78
79 static void bus_done_api(Manager *m);
80 static void bus_done_system(Manager *m);
81 static void bus_done_private(Manager *m);
82 static void shutdown_connection(Manager *m, DBusConnection *c);
83
84 static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data)  {
85         Manager *m = data;
86
87         assert(bus);
88         assert(m);
89
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. */
93
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);
98 }
99
100 void 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
107         if (!dbus_watch_get_enabled(w->data.bus_watch))
108                 return;
109
110         dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
111 }
112
113 static 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) {
150                         close_nointr_nofail(w->fd);
151                         free(w);
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
163 static 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
170         w = dbus_watch_get_data(bus_watch);
171         if (!w)
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
183 static 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
191         w = dbus_watch_get_data(bus_watch);
192         if (!w)
193                 return;
194
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
204 static 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);
214                 its.it_interval = its.it_value;
215         }
216
217         if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
218                 return -errno;
219
220         return 0;
221 }
222
223 void 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
236 static 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
247         if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
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
267 fail:
268         if (w->fd >= 0)
269                 close_nointr_nofail(w->fd);
270
271         free(w);
272         return FALSE;
273 }
274
275 static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
276         Manager *m = data;
277         Watch *w;
278
279         assert(timeout);
280         assert(m);
281
282         w = dbus_timeout_get_data(timeout);
283         if (!w)
284                 return;
285
286         assert(w->type == WATCH_DBUS_TIMEOUT);
287
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
293 static 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
301         w = dbus_timeout_get_data(timeout);
302         if (!w)
303                 return;
304
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
311 static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
312         Manager *m = data;
313         DBusError error;
314         DBusMessage *reply = NULL;
315
316         assert(connection);
317         assert(message);
318         assert(m);
319
320         dbus_error_init(&error);
321
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));
328
329         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
330                 log_debug("API D-Bus connection terminated.");
331                 bus_done_api(m);
332
333         } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
334                 const char *name, *old_owner, *new_owner;
335
336                 if (!dbus_message_get_args(message, &error,
337                                            DBUS_TYPE_STRING, &name,
338                                            DBUS_TYPE_STRING, &old_owner,
339                                            DBUS_TYPE_STRING, &new_owner,
340                                            DBUS_TYPE_INVALID))
341                         log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
342                 else  {
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)));
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);
353                 }
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))
360                         log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
361                 else  {
362                         int r;
363                         Unit *u;
364
365                         log_debug("Got D-Bus activation request for %s", name);
366
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);
373
374                                 if (r >= 0 && u->refuse_manual_start)
375                                         r = -EPERM;
376
377                                 if (r >= 0)
378                                         r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
379                         }
380
381                         if (r < 0) {
382                                 const char *id, *text;
383
384                                 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
385
386                                 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
387                                         goto oom;
388
389                                 id = error.name ? error.name : bus_errno_to_dbus(r);
390                                 text = bus_error(&error, r);
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
401                         /* On success we don't do anything, the service will be spawned now */
402                 }
403         }
404
405         dbus_error_free(&error);
406
407         if (reply) {
408                 if (!dbus_connection_send(connection, reply, NULL))
409                         goto oom;
410
411                 dbus_message_unref(reply);
412         }
413
414         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
415
416 oom:
417         if (reply)
418                 dbus_message_unref(reply);
419
420         dbus_error_free(&error);
421
422         return DBUS_HANDLER_RESULT_NEED_MEMORY;
423 }
424
425 static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
426         Manager *m = data;
427         DBusError error;
428
429         assert(connection);
430         assert(message);
431         assert(m);
432
433         dbus_error_init(&error);
434
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));
442
443         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
444                 log_debug("System D-Bus connection terminated.");
445                 bus_done_system(m);
446
447         } else if (m->running_as != MANAGER_SYSTEM &&
448                    dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
449
450                 const char *cgroup;
451
452                 if (!dbus_message_get_args(message, &error,
453                                            DBUS_TYPE_STRING, &cgroup,
454                                            DBUS_TYPE_INVALID))
455                         log_error("Failed to parse Released message: %s", bus_error_message(&error));
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
464 static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
465         Manager *m = data;
466         DBusError error;
467
468         assert(connection);
469         assert(message);
470         assert(m);
471
472         dbus_error_init(&error);
473
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));
480
481         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
482                 shutdown_connection(m, connection);
483         else if (m->running_as == MANAGER_SYSTEM &&
484                  dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
485
486                 const char *cgroup;
487
488                 if (!dbus_message_get_args(message, &error,
489                                            DBUS_TYPE_STRING, &cgroup,
490                                            DBUS_TYPE_INVALID))
491                         log_error("Failed to parse Released message: %s", bus_error_message(&error));
492                 else
493                         cgroup_notify_empty(m, cgroup);
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);
500         }
501
502         dbus_error_free(&error);
503
504         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
505 }
506
507 unsigned bus_dispatch(Manager *m) {
508         DBusConnection *c;
509
510         assert(m);
511
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
517                 if (m->queued_message_connection)
518                         if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
519                                 return 0;
520
521                 dbus_message_unref(m->queued_message);
522                 m->queued_message = NULL;
523                 m->queued_message_connection = NULL;
524         }
525
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);
529
530                 return 1;
531         }
532
533         return 0;
534 }
535
536 static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
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));
549                 log_warning("RequestName() failed: %s", bus_error_message(&error));
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)) {
559                         log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
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
579 static int request_name(Manager *m) {
580         const char *name = "org.freedesktop.systemd1";
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;
587         DBusMessage *message = NULL;
588         DBusPendingCall *pending = NULL;
589
590         if (!(message = dbus_message_new_method_call(
591                               DBUS_SERVICE_DBUS,
592                               DBUS_PATH_DBUS,
593                               DBUS_INTERFACE_DBUS,
594                               "RequestName")))
595                 goto oom;
596
597         if (!dbus_message_append_args(
598                             message,
599                             DBUS_TYPE_STRING, &name,
600                             DBUS_TYPE_UINT32, &flags,
601                             DBUS_TYPE_INVALID))
602                 goto oom;
603
604         if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
605                 goto oom;
606
607         if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
608                 goto oom;
609
610         dbus_message_unref(message);
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
616         return 0;
617
618 oom:
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;
628 }
629
630 static 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));
646                 log_warning("ListNames() failed: %s", bus_error_message(&error));
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
680 static 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
707 oom:
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
719 static int bus_setup_loop(Manager *m, DBusConnection *bus) {
720         assert(m);
721         assert(bus);
722
723         dbus_connection_set_exit_on_disconnect(bus, FALSE);
724
725         if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
726             !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
727                 return log_oom();
728
729         if (set_put(m->bus_connections_for_dispatch, bus) < 0)
730                 return log_oom();
731
732         dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
733         return 0;
734 }
735
736 static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
737         return uid == 0 || uid == geteuid();
738 }
739
740 static void bus_new_connection(
741                 DBusServer *server,
742                 DBusConnection *new_connection,
743                 void *data) {
744
745         Manager *m = data;
746
747         assert(m);
748
749         if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
750                 log_error("Too many concurrent connections.");
751                 return;
752         }
753
754         dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
755
756         if (bus_setup_loop(m, new_connection) < 0)
757                 return;
758
759         if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
760             !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
761             !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
762             !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
763                 log_oom();
764                 return;
765         }
766
767         log_debug("Accepted connection on private bus.");
768
769         dbus_connection_ref(new_connection);
770 }
771
772 static int init_registered_system_bus(Manager *m) {
773         char *id;
774
775         if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
776                 return log_oom();
777
778         if (m->running_as != MANAGER_SYSTEM) {
779                 DBusError error;
780
781                 dbus_error_init(&error);
782
783                 dbus_bus_add_match(m->system_bus,
784                                    "type='signal',"
785                                    "interface='org.freedesktop.systemd1.Agent',"
786                                    "member='Released',"
787                                    "path='/org/freedesktop/systemd1/agent'",
788                                    &error);
789
790                 if (dbus_error_is_set(&error)) {
791                         log_error("Failed to register match: %s", bus_error_message(&error));
792                         dbus_error_free(&error);
793                         return -1;
794                 }
795         }
796
797         log_debug("Successfully connected to system D-Bus bus %s as %s",
798                  strnull((id = dbus_connection_get_server_id(m->system_bus))),
799                  strnull(dbus_bus_get_unique_name(m->system_bus)));
800         dbus_free(id);
801
802         return 0;
803 }
804
805 static int init_registered_api_bus(Manager *m) {
806         int r;
807
808         if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
809             !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
810             !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
811             !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
812                 return log_oom();
813
814         /* Get NameOwnerChange messages */
815         dbus_bus_add_match(m->api_bus,
816                            "type='signal',"
817                            "sender='"DBUS_SERVICE_DBUS"',"
818                            "interface='"DBUS_INTERFACE_DBUS"',"
819                            "member='NameOwnerChanged',"
820                            "path='"DBUS_PATH_DBUS"'",
821                            NULL);
822
823         /* Get activation requests */
824         dbus_bus_add_match(m->api_bus,
825                            "type='signal',"
826                            "sender='"DBUS_SERVICE_DBUS"',"
827                            "interface='org.freedesktop.systemd1.Activator',"
828                            "member='ActivationRequest',"
829                            "path='"DBUS_PATH_DBUS"'",
830                            NULL);
831
832         r = request_name(m);
833         if (r < 0)
834                 return r;
835
836         r = query_name_list(m);
837         if (r < 0)
838                 return r;
839
840         if (m->running_as == MANAGER_USER) {
841                 char *id;
842                 log_debug("Successfully connected to API D-Bus bus %s as %s",
843                          strnull((id = dbus_connection_get_server_id(m->api_bus))),
844                          strnull(dbus_bus_get_unique_name(m->api_bus)));
845                 dbus_free(id);
846         } else
847                 log_debug("Successfully initialized API on the system bus");
848
849         return 0;
850 }
851
852 static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
853         Manager *m = userdata;
854         DBusConnection **conn;
855         DBusMessage *reply;
856         DBusError error;
857         const char *name;
858         int r = 0;
859
860         dbus_error_init(&error);
861
862         conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
863         assert(conn == &m->system_bus || conn == &m->api_bus);
864
865         reply = dbus_pending_call_steal_reply(pending);
866
867         switch (dbus_message_get_type(reply)) {
868         case DBUS_MESSAGE_TYPE_ERROR:
869                 assert_se(dbus_set_error_from_message(&error, reply));
870                 log_warning("Failed to register to bus: %s", bus_error_message(&error));
871                 r = -1;
872                 break;
873         case DBUS_MESSAGE_TYPE_METHOD_RETURN:
874                 if (!dbus_message_get_args(reply, &error,
875                                            DBUS_TYPE_STRING, &name,
876                                            DBUS_TYPE_INVALID)) {
877                         log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
878                         r = -1;
879                         break;
880                 }
881
882                 log_debug("Received name %s in reply to Hello", name);
883                 if (!dbus_bus_set_unique_name(*conn, name)) {
884                         log_error("Failed to set unique name");
885                         r = -1;
886                         break;
887                 }
888
889                 if (conn == &m->system_bus) {
890                         r = init_registered_system_bus(m);
891                         if (r == 0 && m->running_as == MANAGER_SYSTEM)
892                                 r = init_registered_api_bus(m);
893                 } else
894                         r = init_registered_api_bus(m);
895
896                 break;
897         default:
898                 assert_not_reached("Invalid reply message");
899         }
900
901         dbus_message_unref(reply);
902         dbus_error_free(&error);
903
904         if (r < 0) {
905                 if (conn == &m->system_bus) {
906                         log_debug("Failed setting up the system bus");
907                         bus_done_system(m);
908                 } else {
909                         log_debug("Failed setting up the API bus");
910                         bus_done_api(m);
911                 }
912         }
913 }
914
915 static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
916         DBusMessage *message = NULL;
917         DBusPendingCall *pending = NULL;
918
919         message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
920                                                DBUS_PATH_DBUS,
921                                                DBUS_INTERFACE_DBUS,
922                                                "Hello");
923         if (!message)
924                 goto oom;
925
926         if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
927                 goto oom;
928
929         if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
930                 goto oom;
931
932         if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
933                 goto oom;
934
935         dbus_message_unref(message);
936         dbus_pending_call_unref(pending);
937
938         return 0;
939 oom:
940         if (pending) {
941                 dbus_pending_call_cancel(pending);
942                 dbus_pending_call_unref(pending);
943         }
944
945         if (message)
946                 dbus_message_unref(message);
947
948         return -ENOMEM;
949 }
950
951 static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
952         const char *address;
953         DBusConnection *connection;
954         DBusError error;
955
956         switch (type) {
957         case DBUS_BUS_SYSTEM:
958                 address = getenv("DBUS_SYSTEM_BUS_ADDRESS");
959                 if (!address || !address[0])
960                         address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
961                 break;
962         case DBUS_BUS_SESSION:
963                 address = getenv("DBUS_SESSION_BUS_ADDRESS");
964                 if (!address || !address[0])
965                         address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
966                 break;
967         default:
968                 assert_not_reached("Invalid bus type");
969         }
970
971         dbus_error_init(&error);
972
973         connection = dbus_connection_open_private(address, &error);
974         if (!connection) {
975                 log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
976                 goto fail;
977         }
978
979         return connection;
980 fail:
981         if (connection)
982                 dbus_connection_close(connection);
983         dbus_error_free(&error);
984         return NULL;
985 }
986
987 static int bus_init_system(Manager *m) {
988         int r;
989
990         if (m->system_bus)
991                 return 0;
992
993         m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
994         if (!m->system_bus) {
995                 log_debug("Failed to connect to system D-Bus, retrying later");
996                 r = 0;
997                 goto fail;
998         }
999
1000         r = bus_setup_loop(m, m->system_bus);
1001         if (r < 0)
1002                 goto fail;
1003
1004         r = manager_bus_async_register(m, &m->system_bus);
1005         if (r < 0)
1006                 goto fail;
1007
1008         return 0;
1009 fail:
1010         bus_done_system(m);
1011
1012         return r;
1013 }
1014
1015 static int bus_init_api(Manager *m) {
1016         int r;
1017
1018         if (m->api_bus)
1019                 return 0;
1020
1021         if (m->running_as == MANAGER_SYSTEM) {
1022                 m->api_bus = m->system_bus;
1023                 /* In this mode there is no distinct connection to the API bus,
1024                  * the API is published on the system bus.
1025                  * bus_register_cb() is aware of that and will init the API
1026                  * when the system bus gets registered.
1027                  * No need to setup anything here. */
1028                 return 0;
1029         }
1030
1031         m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
1032         if (!m->api_bus) {
1033                 log_debug("Failed to connect to API D-Bus, retrying later");
1034                 r = 0;
1035                 goto fail;
1036         }
1037
1038         r = bus_setup_loop(m, m->api_bus);
1039         if (r < 0)
1040                 goto fail;
1041
1042         r = manager_bus_async_register(m, &m->api_bus);
1043         if (r < 0)
1044                 goto fail;
1045
1046         return 0;
1047 fail:
1048         bus_done_api(m);
1049
1050         return r;
1051 }
1052
1053 static int bus_init_private(Manager *m) {
1054         DBusError error;
1055         int r;
1056         const char *const external_only[] = {
1057                 "EXTERNAL",
1058                 NULL
1059         };
1060
1061         assert(m);
1062
1063         dbus_error_init(&error);
1064
1065         if (m->private_bus)
1066                 return 0;
1067
1068         if (m->running_as == MANAGER_SYSTEM) {
1069
1070                 /* We want the private bus only when running as init */
1071                 if (getpid() != 1)
1072                         return 0;
1073
1074                 unlink("/run/systemd/private");
1075                 m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
1076         } else {
1077                 const char *e;
1078                 char *p;
1079
1080                 e = getenv("XDG_RUNTIME_DIR");
1081                 if (!e)
1082                         return 0;
1083
1084                 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) {
1085                         r = log_oom();
1086                         goto fail;
1087                 }
1088
1089                 mkdir_parents_label(p+10, 0755);
1090                 unlink(p+10);
1091                 m->private_bus = dbus_server_listen(p, &error);
1092                 free(p);
1093         }
1094
1095         if (!m->private_bus) {
1096                 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
1097                 r = -EIO;
1098                 goto fail;
1099         }
1100
1101         if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1102             !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1103             !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
1104                 r = log_oom();
1105                 goto fail;
1106         }
1107
1108         dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1109
1110         log_debug("Successfully created private D-Bus server.");
1111
1112         return 0;
1113
1114 fail:
1115         bus_done_private(m);
1116         dbus_error_free(&error);
1117
1118         return r;
1119 }
1120
1121 int bus_init(Manager *m, bool try_bus_connect) {
1122         int r;
1123
1124         if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1125             set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1126                 goto oom;
1127
1128         if (m->name_data_slot < 0)
1129                 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1130                         goto oom;
1131
1132         if (m->conn_data_slot < 0)
1133                 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1134                         goto oom;
1135
1136         if (m->subscribed_data_slot < 0)
1137                 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1138                         goto oom;
1139
1140         if (try_bus_connect) {
1141                 if ((r = bus_init_system(m)) < 0 ||
1142                     (r = bus_init_api(m)) < 0)
1143                         return r;
1144         }
1145
1146         if ((r = bus_init_private(m)) < 0)
1147                 return r;
1148
1149         return 0;
1150 oom:
1151         return log_oom();
1152 }
1153
1154 static void shutdown_connection(Manager *m, DBusConnection *c) {
1155         Set *s;
1156         Job *j;
1157         Iterator i;
1158
1159         HASHMAP_FOREACH(j, m->jobs, i) {
1160                 JobBusClient *cl, *nextcl;
1161                 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1162                         if (cl->bus == c) {
1163                                 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
1164                                 free(cl);
1165                         }
1166                 }
1167         }
1168
1169         set_remove(m->bus_connections, c);
1170         set_remove(m->bus_connections_for_dispatch, c);
1171
1172         if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
1173                 char *t;
1174
1175                 while ((t = set_steal_first(s)))
1176                         free(t);
1177
1178                 set_free(s);
1179         }
1180
1181         if (m->queued_message_connection == c) {
1182                 m->queued_message_connection = NULL;
1183
1184                 if (m->queued_message) {
1185                         dbus_message_unref(m->queued_message);
1186                         m->queued_message = NULL;
1187                 }
1188         }
1189
1190         dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1191         /* system manager cannot afford to block on DBus */
1192         if (m->running_as != MANAGER_SYSTEM)
1193                 dbus_connection_flush(c);
1194         dbus_connection_close(c);
1195         dbus_connection_unref(c);
1196 }
1197
1198 static void bus_done_api(Manager *m) {
1199         if (!m->api_bus)
1200                 return;
1201
1202         if (m->running_as == MANAGER_USER)
1203                 shutdown_connection(m, m->api_bus);
1204
1205         m->api_bus = NULL;
1206
1207         if (m->queued_message) {
1208                 dbus_message_unref(m->queued_message);
1209                 m->queued_message = NULL;
1210         }
1211 }
1212
1213 static void bus_done_system(Manager *m) {
1214         if (!m->system_bus)
1215                 return;
1216
1217         if (m->running_as == MANAGER_SYSTEM)
1218                 bus_done_api(m);
1219
1220         shutdown_connection(m, m->system_bus);
1221         m->system_bus = NULL;
1222 }
1223
1224 static void bus_done_private(Manager *m) {
1225         if (!m->private_bus)
1226                 return;
1227
1228         dbus_server_disconnect(m->private_bus);
1229         dbus_server_unref(m->private_bus);
1230         m->private_bus = NULL;
1231 }
1232
1233 void bus_done(Manager *m) {
1234         DBusConnection *c;
1235
1236         bus_done_api(m);
1237         bus_done_system(m);
1238         bus_done_private(m);
1239
1240         while ((c = set_steal_first(m->bus_connections)))
1241                 shutdown_connection(m, c);
1242
1243         while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1244                 shutdown_connection(m, c);
1245
1246         set_free(m->bus_connections);
1247         set_free(m->bus_connections_for_dispatch);
1248
1249         if (m->name_data_slot >= 0)
1250                dbus_pending_call_free_data_slot(&m->name_data_slot);
1251
1252         if (m->conn_data_slot >= 0)
1253                dbus_pending_call_free_data_slot(&m->conn_data_slot);
1254
1255         if (m->subscribed_data_slot >= 0)
1256                 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1257 }
1258
1259 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1260         Manager *m = userdata;
1261         DBusMessage *reply;
1262         DBusError error;
1263         const char *name;
1264
1265         dbus_error_init(&error);
1266
1267         assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1268         assert_se(reply = dbus_pending_call_steal_reply(pending));
1269
1270         switch (dbus_message_get_type(reply)) {
1271
1272         case DBUS_MESSAGE_TYPE_ERROR:
1273
1274                 assert_se(dbus_set_error_from_message(&error, reply));
1275                 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1276                 break;
1277
1278         case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1279                 uint32_t r;
1280
1281                 if (!dbus_message_get_args(reply,
1282                                            &error,
1283                                            DBUS_TYPE_UINT32, &r,
1284                                            DBUS_TYPE_INVALID)) {
1285                         log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1286                         break;
1287                 }
1288
1289                 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1290                 break;
1291         }
1292
1293         default:
1294                 assert_not_reached("Invalid reply message");
1295         }
1296
1297         dbus_message_unref(reply);
1298         dbus_error_free(&error);
1299 }
1300
1301 int bus_query_pid(Manager *m, const char *name) {
1302         DBusMessage *message = NULL;
1303         DBusPendingCall *pending = NULL;
1304         char *n = NULL;
1305
1306         assert(m);
1307         assert(name);
1308
1309         if (!(message = dbus_message_new_method_call(
1310                               DBUS_SERVICE_DBUS,
1311                               DBUS_PATH_DBUS,
1312                               DBUS_INTERFACE_DBUS,
1313                               "GetConnectionUnixProcessID")))
1314                 goto oom;
1315
1316         if (!(dbus_message_append_args(
1317                               message,
1318                               DBUS_TYPE_STRING, &name,
1319                               DBUS_TYPE_INVALID)))
1320                 goto oom;
1321
1322         if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1323                 goto oom;
1324
1325         if (!(n = strdup(name)))
1326                 goto oom;
1327
1328         if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1329                 goto oom;
1330
1331         n = NULL;
1332
1333         if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1334                 goto oom;
1335
1336         dbus_message_unref(message);
1337         dbus_pending_call_unref(pending);
1338
1339         return 0;
1340
1341 oom:
1342         free(n);
1343
1344         if (pending) {
1345                 dbus_pending_call_cancel(pending);
1346                 dbus_pending_call_unref(pending);
1347         }
1348
1349         if (message)
1350                 dbus_message_unref(message);
1351
1352         return -ENOMEM;
1353 }
1354
1355 int bus_broadcast(Manager *m, DBusMessage *message) {
1356         bool oom = false;
1357         Iterator i;
1358         DBusConnection *c;
1359
1360         assert(m);
1361         assert(message);
1362
1363         SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1364                 if (c != m->system_bus || m->running_as == MANAGER_SYSTEM)
1365                         oom = !dbus_connection_send(c, message, NULL);
1366
1367         SET_FOREACH(c, m->bus_connections, i)
1368                 if (c != m->system_bus || m->running_as == MANAGER_SYSTEM)
1369                         oom = !dbus_connection_send(c, message, NULL);
1370
1371         return oom ? -ENOMEM : 0;
1372 }
1373
1374 bool bus_has_subscriber(Manager *m) {
1375         Iterator i;
1376         DBusConnection *c;
1377
1378         assert(m);
1379
1380         SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1381                 if (bus_connection_has_subscriber(m, c))
1382                         return true;
1383
1384         SET_FOREACH(c, m->bus_connections, i)
1385                 if (bus_connection_has_subscriber(m, c))
1386                         return true;
1387
1388         return false;
1389 }
1390
1391 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1392         assert(m);
1393         assert(c);
1394
1395         return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1396 }
1397
1398 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1399         Iterator i;
1400         DBusConnection *c;
1401
1402         assert(m);
1403         assert(fds);
1404
1405         /* When we are about to reexecute we add all D-Bus fds to the
1406          * set to pass over to the newly executed systemd. They won't
1407          * be used there however, except that they are closed at the
1408          * very end of deserialization, those making it possible for
1409          * clients to synchronously wait for systemd to reexec by
1410          * simply waiting for disconnection */
1411
1412         SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1413                 int fd;
1414
1415                 if (dbus_connection_get_unix_fd(c, &fd)) {
1416                         fd = fdset_put_dup(fds, fd);
1417
1418                         if (fd < 0)
1419                                 return fd;
1420                 }
1421         }
1422
1423         SET_FOREACH(c, m->bus_connections, 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         return 0;
1435 }
1436
1437 void bus_broadcast_finished(
1438                 Manager *m,
1439                 usec_t kernel_usec,
1440                 usec_t initrd_usec,
1441                 usec_t userspace_usec,
1442                 usec_t total_usec) {
1443
1444         DBusMessage *message;
1445
1446         assert(m);
1447
1448         message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1449         if (!message) {
1450                 log_oom();
1451                 return;
1452         }
1453
1454         assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1455         if (!dbus_message_append_args(message,
1456                                       DBUS_TYPE_UINT64, &kernel_usec,
1457                                       DBUS_TYPE_UINT64, &initrd_usec,
1458                                       DBUS_TYPE_UINT64, &userspace_usec,
1459                                       DBUS_TYPE_UINT64, &total_usec,
1460                                       DBUS_TYPE_INVALID)) {
1461                 log_oom();
1462                 goto finish;
1463         }
1464
1465
1466         if (bus_broadcast(m, message) < 0) {
1467                 log_oom();
1468                 goto finish;
1469         }
1470
1471 finish:
1472         if (message)
1473                 dbus_message_unref(message);
1474 }