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