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