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