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