chiark / gitweb /
Merge nss-myhostname
[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
1081                 e = secure_getenv("XDG_RUNTIME_DIR");
1082                 if (!e)
1083                         return 0;
1084
1085                 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) {
1086                         r = log_oom();
1087                         goto fail;
1088                 }
1089
1090                 mkdir_parents_label(p+10, 0755);
1091                 unlink(p+10);
1092                 m->private_bus = dbus_server_listen(p, &error);
1093                 free(p);
1094         }
1095
1096         if (!m->private_bus) {
1097                 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
1098                 r = -EIO;
1099                 goto fail;
1100         }
1101
1102         if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1103             !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1104             !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
1105                 r = log_oom();
1106                 goto fail;
1107         }
1108
1109         dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1110
1111         log_debug("Successfully created private D-Bus server.");
1112
1113         return 0;
1114
1115 fail:
1116         bus_done_private(m);
1117         dbus_error_free(&error);
1118
1119         return r;
1120 }
1121
1122 int bus_init(Manager *m, bool try_bus_connect) {
1123         int r;
1124
1125         if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1126             set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1127                 goto oom;
1128
1129         if (m->name_data_slot < 0)
1130                 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1131                         goto oom;
1132
1133         if (m->conn_data_slot < 0)
1134                 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1135                         goto oom;
1136
1137         if (m->subscribed_data_slot < 0)
1138                 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1139                         goto oom;
1140
1141         if (try_bus_connect) {
1142                 if ((r = bus_init_system(m)) < 0 ||
1143                     (r = bus_init_api(m)) < 0)
1144                         return r;
1145         }
1146
1147         if ((r = bus_init_private(m)) < 0)
1148                 return r;
1149
1150         return 0;
1151 oom:
1152         return log_oom();
1153 }
1154
1155 static void shutdown_connection(Manager *m, DBusConnection *c) {
1156         Set *s;
1157         Job *j;
1158         Iterator i;
1159
1160         HASHMAP_FOREACH(j, m->jobs, i) {
1161                 JobBusClient *cl, *nextcl;
1162                 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1163                         if (cl->bus == c) {
1164                                 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
1165                                 free(cl);
1166                         }
1167                 }
1168         }
1169
1170         set_remove(m->bus_connections, c);
1171         set_remove(m->bus_connections_for_dispatch, c);
1172
1173         if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) {
1174                 char *t;
1175
1176                 while ((t = set_steal_first(s)))
1177                         free(t);
1178
1179                 set_free(s);
1180         }
1181
1182         if (m->queued_message_connection == c) {
1183                 m->queued_message_connection = NULL;
1184
1185                 if (m->queued_message) {
1186                         dbus_message_unref(m->queued_message);
1187                         m->queued_message = NULL;
1188                 }
1189         }
1190
1191         dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1192         /* system manager cannot afford to block on DBus */
1193         if (m->running_as != SYSTEMD_SYSTEM)
1194                 dbus_connection_flush(c);
1195         dbus_connection_close(c);
1196         dbus_connection_unref(c);
1197 }
1198
1199 static void bus_done_api(Manager *m) {
1200         if (!m->api_bus)
1201                 return;
1202
1203         if (m->running_as == SYSTEMD_USER)
1204                 shutdown_connection(m, m->api_bus);
1205
1206         m->api_bus = NULL;
1207
1208         if (m->queued_message) {
1209                 dbus_message_unref(m->queued_message);
1210                 m->queued_message = NULL;
1211         }
1212 }
1213
1214 static void bus_done_system(Manager *m) {
1215         if (!m->system_bus)
1216                 return;
1217
1218         if (m->running_as == SYSTEMD_SYSTEM)
1219                 bus_done_api(m);
1220
1221         shutdown_connection(m, m->system_bus);
1222         m->system_bus = NULL;
1223 }
1224
1225 static void bus_done_private(Manager *m) {
1226         if (!m->private_bus)
1227                 return;
1228
1229         dbus_server_disconnect(m->private_bus);
1230         dbus_server_unref(m->private_bus);
1231         m->private_bus = NULL;
1232 }
1233
1234 void bus_done(Manager *m) {
1235         DBusConnection *c;
1236
1237         bus_done_api(m);
1238         bus_done_system(m);
1239         bus_done_private(m);
1240
1241         while ((c = set_steal_first(m->bus_connections)))
1242                 shutdown_connection(m, c);
1243
1244         while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1245                 shutdown_connection(m, c);
1246
1247         set_free(m->bus_connections);
1248         set_free(m->bus_connections_for_dispatch);
1249
1250         if (m->name_data_slot >= 0)
1251                dbus_pending_call_free_data_slot(&m->name_data_slot);
1252
1253         if (m->conn_data_slot >= 0)
1254                dbus_pending_call_free_data_slot(&m->conn_data_slot);
1255
1256         if (m->subscribed_data_slot >= 0)
1257                 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1258 }
1259
1260 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1261         Manager *m = userdata;
1262         DBusMessage *reply;
1263         DBusError error;
1264         const char *name;
1265
1266         dbus_error_init(&error);
1267
1268         assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1269         assert_se(reply = dbus_pending_call_steal_reply(pending));
1270
1271         switch (dbus_message_get_type(reply)) {
1272
1273         case DBUS_MESSAGE_TYPE_ERROR:
1274
1275                 assert_se(dbus_set_error_from_message(&error, reply));
1276                 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1277                 break;
1278
1279         case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1280                 uint32_t r;
1281
1282                 if (!dbus_message_get_args(reply,
1283                                            &error,
1284                                            DBUS_TYPE_UINT32, &r,
1285                                            DBUS_TYPE_INVALID)) {
1286                         log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1287                         break;
1288                 }
1289
1290                 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1291                 break;
1292         }
1293
1294         default:
1295                 assert_not_reached("Invalid reply message");
1296         }
1297
1298         dbus_message_unref(reply);
1299         dbus_error_free(&error);
1300 }
1301
1302 int bus_query_pid(Manager *m, const char *name) {
1303         DBusMessage *message = NULL;
1304         DBusPendingCall *pending = NULL;
1305         char *n = NULL;
1306
1307         assert(m);
1308         assert(name);
1309
1310         if (!(message = dbus_message_new_method_call(
1311                               DBUS_SERVICE_DBUS,
1312                               DBUS_PATH_DBUS,
1313                               DBUS_INTERFACE_DBUS,
1314                               "GetConnectionUnixProcessID")))
1315                 goto oom;
1316
1317         if (!(dbus_message_append_args(
1318                               message,
1319                               DBUS_TYPE_STRING, &name,
1320                               DBUS_TYPE_INVALID)))
1321                 goto oom;
1322
1323         if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1324                 goto oom;
1325
1326         if (!(n = strdup(name)))
1327                 goto oom;
1328
1329         if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1330                 goto oom;
1331
1332         n = NULL;
1333
1334         if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1335                 goto oom;
1336
1337         dbus_message_unref(message);
1338         dbus_pending_call_unref(pending);
1339
1340         return 0;
1341
1342 oom:
1343         free(n);
1344
1345         if (pending) {
1346                 dbus_pending_call_cancel(pending);
1347                 dbus_pending_call_unref(pending);
1348         }
1349
1350         if (message)
1351                 dbus_message_unref(message);
1352
1353         return -ENOMEM;
1354 }
1355
1356 int bus_broadcast(Manager *m, DBusMessage *message) {
1357         bool oom = false;
1358         Iterator i;
1359         DBusConnection *c;
1360
1361         assert(m);
1362         assert(message);
1363
1364         SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1365                 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1366                         oom = !dbus_connection_send(c, message, NULL);
1367
1368         SET_FOREACH(c, m->bus_connections, i)
1369                 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1370                         oom = !dbus_connection_send(c, message, NULL);
1371
1372         return oom ? -ENOMEM : 0;
1373 }
1374
1375 bool bus_has_subscriber(Manager *m) {
1376         Iterator i;
1377         DBusConnection *c;
1378
1379         assert(m);
1380
1381         SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1382                 if (bus_connection_has_subscriber(m, c))
1383                         return true;
1384
1385         SET_FOREACH(c, m->bus_connections, i)
1386                 if (bus_connection_has_subscriber(m, c))
1387                         return true;
1388
1389         return false;
1390 }
1391
1392 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1393         assert(m);
1394         assert(c);
1395
1396         return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1397 }
1398
1399 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1400         Iterator i;
1401         DBusConnection *c;
1402
1403         assert(m);
1404         assert(fds);
1405
1406         /* When we are about to reexecute we add all D-Bus fds to the
1407          * set to pass over to the newly executed systemd. They won't
1408          * be used there however, except that they are closed at the
1409          * very end of deserialization, those making it possible for
1410          * clients to synchronously wait for systemd to reexec by
1411          * simply waiting for disconnection */
1412
1413         SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1414                 int fd;
1415
1416                 if (dbus_connection_get_unix_fd(c, &fd)) {
1417                         fd = fdset_put_dup(fds, fd);
1418
1419                         if (fd < 0)
1420                                 return fd;
1421                 }
1422         }
1423
1424         SET_FOREACH(c, m->bus_connections, i) {
1425                 int fd;
1426
1427                 if (dbus_connection_get_unix_fd(c, &fd)) {
1428                         fd = fdset_put_dup(fds, fd);
1429
1430                         if (fd < 0)
1431                                 return fd;
1432                 }
1433         }
1434
1435         return 0;
1436 }
1437
1438 void bus_broadcast_finished(
1439                 Manager *m,
1440                 usec_t firmware_usec,
1441                 usec_t loader_usec,
1442                 usec_t kernel_usec,
1443                 usec_t initrd_usec,
1444                 usec_t userspace_usec,
1445                 usec_t total_usec) {
1446
1447         DBusMessage *message;
1448
1449         assert(m);
1450
1451         message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1452         if (!message) {
1453                 log_oom();
1454                 return;
1455         }
1456
1457         assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1458         if (!dbus_message_append_args(message,
1459                                       DBUS_TYPE_UINT64, &firmware_usec,
1460                                       DBUS_TYPE_UINT64, &loader_usec,
1461                                       DBUS_TYPE_UINT64, &kernel_usec,
1462                                       DBUS_TYPE_UINT64, &initrd_usec,
1463                                       DBUS_TYPE_UINT64, &userspace_usec,
1464                                       DBUS_TYPE_UINT64, &total_usec,
1465                                       DBUS_TYPE_INVALID)) {
1466                 log_oom();
1467                 goto finish;
1468         }
1469
1470
1471         if (bus_broadcast(m, message) < 0) {
1472                 log_oom();
1473                 goto finish;
1474         }
1475
1476 finish:
1477         if (message)
1478                 dbus_message_unref(message);
1479 }