]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-bus.c
journald: do not free space when disk space runs low
[thirdparty/systemd.git] / src / libsystemd-bus / sd-bus.c
CommitLineData
de1c301e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 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 <endian.h>
23#include <assert.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <netdb.h>
27#include <sys/poll.h>
28#include <byteswap.h>
63edf05e 29#include <sys/mman.h>
45fbe937 30#include <pthread.h>
de1c301e
LP
31
32#include "util.h"
33#include "macro.h"
2fd9ae2e 34#include "strv.h"
0a72c2bd 35#include "set.h"
6c03089c 36#include "missing.h"
ab9001a1 37#include "def.h"
de1c301e
LP
38
39#include "sd-bus.h"
40#include "bus-internal.h"
41#include "bus-message.h"
42#include "bus-type.h"
a7e3212d 43#include "bus-socket.h"
6629161f 44#include "bus-kernel.h"
392d5b37 45#include "bus-control.h"
29ddb38f
LP
46#include "bus-introspect.h"
47#include "bus-signature.h"
992c052c 48#include "bus-objects.h"
40ca29a1 49#include "bus-util.h"
a7893c6b 50#include "bus-container.h"
0461f8cd 51#include "bus-protocol.h"
de1c301e 52
e3017af9 53static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
1e05d493
LP
54static int attach_io_events(sd_bus *b);
55static void detach_io_events(sd_bus *b);
e3017af9 56
f54514f3
LP
57static void bus_close_fds(sd_bus *b) {
58 assert(b);
59
1e05d493
LP
60 detach_io_events(b);
61
f54514f3
LP
62 if (b->input_fd >= 0)
63 close_nointr_nofail(b->input_fd);
64
65 if (b->output_fd >= 0 && b->output_fd != b->input_fd)
66 close_nointr_nofail(b->output_fd);
67
68 b->input_fd = b->output_fd = -1;
69}
70
29ddb38f
LP
71static void bus_node_destroy(sd_bus *b, struct node *n) {
72 struct node_callback *c;
73 struct node_vtable *v;
74 struct node_enumerator *e;
75
76 assert(b);
77
78 if (!n)
79 return;
80
81 while (n->child)
82 bus_node_destroy(b, n->child);
83
84 while ((c = n->callbacks)) {
71fda00f 85 LIST_REMOVE(callbacks, n->callbacks, c);
29ddb38f
LP
86 free(c);
87 }
88
89 while ((v = n->vtables)) {
71fda00f 90 LIST_REMOVE(vtables, n->vtables, v);
29ddb38f
LP
91 free(v->interface);
92 free(v);
93 }
94
95 while ((e = n->enumerators)) {
71fda00f 96 LIST_REMOVE(enumerators, n->enumerators, e);
29ddb38f
LP
97 free(e);
98 }
99
100 if (n->parent)
71fda00f 101 LIST_REMOVE(siblings, n->parent->child, n);
29ddb38f
LP
102
103 assert_se(hashmap_remove(b->nodes, n->path) == n);
104 free(n->path);
105 free(n);
106}
107
0e586eae
LP
108static void bus_reset_queues(sd_bus *b) {
109 unsigned i;
110
111 assert(b);
112
113 for (i = 0; i < b->rqueue_size; i++)
114 sd_bus_message_unref(b->rqueue[i]);
115 free(b->rqueue);
116
117 for (i = 0; i < b->wqueue_size; i++)
118 sd_bus_message_unref(b->wqueue[i]);
119 free(b->wqueue);
120
121 b->rqueue = b->wqueue = NULL;
821e0756 122 b->rqueue_allocated = b->wqueue_allocated = 0;
0e586eae
LP
123 b->rqueue_size = b->wqueue_size = 0;
124}
125
de1c301e
LP
126static void bus_free(sd_bus *b) {
127 struct filter_callback *f;
29ddb38f 128 struct node *n;
de1c301e
LP
129
130 assert(b);
131
40ca29a1
LP
132 sd_bus_detach_event(b);
133
f54514f3 134 bus_close_fds(b);
de1c301e 135
63edf05e
LP
136 if (b->kdbus_buffer)
137 munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
138
de1c301e 139 free(b->rbuffer);
89ffcd2a 140 free(b->unique_name);
2181a7f5 141 free(b->auth_buffer);
89ffcd2a 142 free(b->address);
e9a967f9 143 free(b->kernel);
a7893c6b 144 free(b->machine);
8a0e0ed9 145 free(b->fake_label);
751bc6ac 146 free(b->cgroup_root);
89ffcd2a 147
2fd9ae2e
LP
148 free(b->exec_path);
149 strv_free(b->exec_argv);
150
2c93b4ef
LP
151 close_many(b->fds, b->n_fds);
152 free(b->fds);
153
0e586eae 154 bus_reset_queues(b);
de1c301e
LP
155
156 hashmap_free_free(b->reply_callbacks);
e3017af9 157 prioq_free(b->reply_callbacks_prioq);
de1c301e
LP
158
159 while ((f = b->filter_callbacks)) {
71fda00f 160 LIST_REMOVE(callbacks, b->filter_callbacks, f);
de1c301e
LP
161 free(f);
162 }
163
392d5b37
LP
164 bus_match_free(&b->match_callbacks);
165
29ddb38f
LP
166 hashmap_free_free(b->vtable_methods);
167 hashmap_free_free(b->vtable_properties);
168
169 while ((n = hashmap_first(b->nodes)))
170 bus_node_destroy(b, n);
171
172 hashmap_free(b->nodes);
173
bc7fd8cd
LP
174 bus_kernel_flush_memfd(b);
175
45fbe937
LP
176 assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
177
de1c301e
LP
178 free(b);
179}
180
d9f644e2 181_public_ int sd_bus_new(sd_bus **ret) {
de1c301e
LP
182 sd_bus *r;
183
d6888822 184 assert_return(ret, -EINVAL);
021a1e78 185
de1c301e
LP
186 r = new0(sd_bus, 1);
187 if (!r)
021a1e78 188 return -ENOMEM;
de1c301e 189
e4ee6e5c 190 r->n_ref = REFCNT_INIT;
e82c9509 191 r->input_fd = r->output_fd = -1;
de1c301e 192 r->message_version = 1;
3310dfd5 193 r->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
d21a7bb1
DM
194 r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
195 r->attach_flags |= KDBUS_ATTACH_NAMES;
d5a2b9a6 196 r->original_pid = getpid();
de1c301e 197
45fbe937
LP
198 assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
199
de1c301e
LP
200 /* We guarantee that wqueue always has space for at least one
201 * entry */
821e0756 202 if (!GREEDY_REALLOC(r->wqueue, r->wqueue_allocated, 1)) {
de1c301e 203 free(r);
021a1e78 204 return -ENOMEM;
de1c301e
LP
205 }
206
021a1e78
LP
207 *ret = r;
208 return 0;
209}
210
d9f644e2 211_public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
021a1e78
LP
212 char *a;
213
d6888822
LP
214 assert_return(bus, -EINVAL);
215 assert_return(bus->state == BUS_UNSET, -EPERM);
216 assert_return(address, -EINVAL);
217 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78
LP
218
219 a = strdup(address);
220 if (!a)
221 return -ENOMEM;
222
223 free(bus->address);
224 bus->address = a;
225
226 return 0;
227}
228
d9f644e2 229_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
d6888822
LP
230 assert_return(bus, -EINVAL);
231 assert_return(bus->state == BUS_UNSET, -EPERM);
232 assert_return(input_fd >= 0, -EINVAL);
233 assert_return(output_fd >= 0, -EINVAL);
234 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78 235
e82c9509
LP
236 bus->input_fd = input_fd;
237 bus->output_fd = output_fd;
021a1e78
LP
238 return 0;
239}
240
d9f644e2 241_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
2fd9ae2e
LP
242 char *p, **a;
243
d6888822
LP
244 assert_return(bus, -EINVAL);
245 assert_return(bus->state == BUS_UNSET, -EPERM);
246 assert_return(path, -EINVAL);
247 assert_return(!strv_isempty(argv), -EINVAL);
248 assert_return(!bus_pid_changed(bus), -ECHILD);
2fd9ae2e
LP
249
250 p = strdup(path);
251 if (!p)
252 return -ENOMEM;
253
254 a = strv_copy(argv);
255 if (!a) {
256 free(p);
257 return -ENOMEM;
258 }
259
260 free(bus->exec_path);
261 strv_free(bus->exec_argv);
262
263 bus->exec_path = p;
264 bus->exec_argv = a;
265
266 return 0;
267}
268
d9f644e2 269_public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
d6888822
LP
270 assert_return(bus, -EINVAL);
271 assert_return(bus->state == BUS_UNSET, -EPERM);
272 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78 273
94bbf1ba 274 bus->bus_client = !!b;
021a1e78
LP
275 return 0;
276}
277
d9f644e2 278_public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) {
d6888822
LP
279 assert_return(bus, -EINVAL);
280 assert_return(bus->state == BUS_UNSET, -EPERM);
281 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78 282
264ad849
LP
283 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b);
284 return 0;
285}
286
f21326e6 287_public_ int sd_bus_negotiate_attach_timestamp(sd_bus *bus, int b) {
16be4368
KS
288 assert_return(bus, -EINVAL);
289 assert_return(bus->state == BUS_UNSET, -EPERM);
290 assert_return(!bus_pid_changed(bus), -ECHILD);
291
d21a7bb1 292 SET_FLAG(bus->attach_flags, KDBUS_ATTACH_TIMESTAMP, b);
16be4368
KS
293 return 0;
294}
295
5b12334d 296_public_ int sd_bus_negotiate_attach_creds(sd_bus *bus, uint64_t mask) {
16be4368 297 assert_return(bus, -EINVAL);
95c4fe82 298 assert_return(mask <= _SD_BUS_CREDS_ALL, -EINVAL);
16be4368
KS
299 assert_return(bus->state == BUS_UNSET, -EPERM);
300 assert_return(!bus_pid_changed(bus), -ECHILD);
301
49b832c5 302 /* The well knowns we need unconditionally, so that matches can work */
3310dfd5 303 bus->creds_mask = mask | SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
49b832c5 304
3310dfd5 305 return kdbus_translate_attach_flags(bus->creds_mask, &bus->creds_mask);
021a1e78 306}
de1c301e 307
d9f644e2 308_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
d6888822
LP
309 assert_return(bus, -EINVAL);
310 assert_return(b || sd_id128_equal(server_id, SD_ID128_NULL), -EINVAL);
311 assert_return(bus->state == BUS_UNSET, -EPERM);
312 assert_return(!bus_pid_changed(bus), -ECHILD);
2181a7f5
LP
313
314 bus->is_server = !!b;
98178d39 315 bus->server_id = server_id;
2181a7f5
LP
316 return 0;
317}
318
d9f644e2 319_public_ int sd_bus_set_anonymous(sd_bus *bus, int b) {
d6888822
LP
320 assert_return(bus, -EINVAL);
321 assert_return(bus->state == BUS_UNSET, -EPERM);
322 assert_return(!bus_pid_changed(bus), -ECHILD);
2181a7f5
LP
323
324 bus->anonymous_auth = !!b;
325 return 0;
326}
327
adacb957
LP
328_public_ int sd_bus_set_trusted(sd_bus *bus, int b) {
329 assert_return(bus, -EINVAL);
330 assert_return(bus->state == BUS_UNSET, -EPERM);
331 assert_return(!bus_pid_changed(bus), -ECHILD);
332
333 bus->trusted = !!b;
334 return 0;
335}
336
ebcf1f97 337static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
de1c301e
LP
338 const char *s;
339 int r;
340
341 assert(bus);
c99c09a2 342 assert(bus->state == BUS_HELLO || bus->state == BUS_CLOSING);
de1c301e
LP
343 assert(reply);
344
40ca29a1 345 r = sd_bus_message_get_errno(reply);
eb01ba5d
LP
346 if (r < 0)
347 return r;
40ca29a1
LP
348 if (r > 0)
349 return -r;
eb01ba5d 350
de1c301e
LP
351 r = sd_bus_message_read(reply, "s", &s);
352 if (r < 0)
353 return r;
354
dafb7591
LP
355 if (!service_name_is_valid(s) || s[0] != ':')
356 return -EBADMSG;
357
de1c301e
LP
358 bus->unique_name = strdup(s);
359 if (!bus->unique_name)
360 return -ENOMEM;
361
c99c09a2
LP
362 if (bus->state == BUS_HELLO)
363 bus->state = BUS_RUNNING;
dafb7591 364
de1c301e
LP
365 return 1;
366}
367
368static int bus_send_hello(sd_bus *bus) {
369 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
370 int r;
371
372 assert(bus);
373
6629161f 374 if (!bus->bus_client || bus->is_kernel)
021a1e78
LP
375 return 0;
376
de1c301e
LP
377 r = sd_bus_message_new_method_call(
378 bus,
379 "org.freedesktop.DBus",
a7639e37 380 "/org/freedesktop/DBus",
de1c301e
LP
381 "org.freedesktop.DBus",
382 "Hello",
383 &m);
384 if (r < 0)
385 return r;
386
693eb9a2 387 return sd_bus_call_async(bus, m, hello_callback, NULL, 0, &bus->hello_cookie);
de1c301e
LP
388}
389
a7e3212d 390int bus_start_running(sd_bus *bus) {
de1c301e
LP
391 assert(bus);
392
f08838da 393 if (bus->bus_client && !bus->is_kernel) {
de1c301e 394 bus->state = BUS_HELLO;
e3017af9 395 return 1;
de1c301e
LP
396 }
397
398 bus->state = BUS_RUNNING;
e3017af9 399 return 1;
de1c301e
LP
400}
401
402static int parse_address_key(const char **p, const char *key, char **value) {
821e0756 403 size_t l, n = 0, allocated = 0;
de1c301e
LP
404 const char *a;
405 char *r = NULL;
406
407 assert(p);
408 assert(*p);
de1c301e
LP
409 assert(value);
410
2fd9ae2e
LP
411 if (key) {
412 l = strlen(key);
413 if (strncmp(*p, key, l) != 0)
414 return 0;
de1c301e 415
2fd9ae2e
LP
416 if ((*p)[l] != '=')
417 return 0;
de1c301e 418
2fd9ae2e
LP
419 if (*value)
420 return -EINVAL;
de1c301e 421
2fd9ae2e
LP
422 a = *p + l + 1;
423 } else
424 a = *p;
425
426 while (*a != ';' && *a != ',' && *a != 0) {
821e0756 427 char c;
de1c301e
LP
428
429 if (*a == '%') {
430 int x, y;
431
432 x = unhexchar(a[1]);
433 if (x < 0) {
434 free(r);
435 return x;
436 }
437
438 y = unhexchar(a[2]);
439 if (y < 0) {
440 free(r);
441 return y;
442 }
443
de1c301e 444 c = (char) ((x << 4) | y);
89ffcd2a
LP
445 a += 3;
446 } else {
de1c301e 447 c = *a;
89ffcd2a
LP
448 a++;
449 }
de1c301e 450
821e0756 451 if (!GREEDY_REALLOC(r, allocated, n + 2))
de1c301e 452 return -ENOMEM;
de1c301e 453
de1c301e
LP
454 r[n++] = c;
455 }
456
89ffcd2a
LP
457 if (!r) {
458 r = strdup("");
459 if (!r)
460 return -ENOMEM;
461 } else
462 r[n] = 0;
463
464 if (*a == ',')
465 a++;
466
de1c301e 467 *p = a;
2fd9ae2e
LP
468
469 free(*value);
de1c301e 470 *value = r;
2fd9ae2e 471
de1c301e
LP
472 return 1;
473}
474
475static void skip_address_key(const char **p) {
476 assert(p);
477 assert(*p);
478
89ffcd2a
LP
479 *p += strcspn(*p, ",");
480
481 if (**p == ',')
482 (*p) ++;
de1c301e
LP
483}
484
2fd9ae2e
LP
485static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
486 _cleanup_free_ char *path = NULL, *abstract = NULL;
487 size_t l;
de1c301e
LP
488 int r;
489
490 assert(b);
2fd9ae2e
LP
491 assert(p);
492 assert(*p);
493 assert(guid);
de1c301e 494
2fd9ae2e
LP
495 while (**p != 0 && **p != ';') {
496 r = parse_address_key(p, "guid", guid);
497 if (r < 0)
498 return r;
499 else if (r > 0)
500 continue;
de1c301e 501
2fd9ae2e
LP
502 r = parse_address_key(p, "path", &path);
503 if (r < 0)
504 return r;
505 else if (r > 0)
506 continue;
de1c301e 507
2fd9ae2e
LP
508 r = parse_address_key(p, "abstract", &abstract);
509 if (r < 0)
510 return r;
511 else if (r > 0)
512 continue;
de1c301e 513
2fd9ae2e
LP
514 skip_address_key(p);
515 }
de1c301e 516
2fd9ae2e
LP
517 if (!path && !abstract)
518 return -EINVAL;
de1c301e 519
2fd9ae2e
LP
520 if (path && abstract)
521 return -EINVAL;
522
523 if (path) {
524 l = strlen(path);
525 if (l > sizeof(b->sockaddr.un.sun_path))
526 return -E2BIG;
de1c301e 527
2fd9ae2e
LP
528 b->sockaddr.un.sun_family = AF_UNIX;
529 strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
530 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
531 } else if (abstract) {
532 l = strlen(abstract);
533 if (l > sizeof(b->sockaddr.un.sun_path) - 1)
534 return -E2BIG;
535
536 b->sockaddr.un.sun_family = AF_UNIX;
537 b->sockaddr.un.sun_path[0] = 0;
538 strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
539 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
540 }
541
542 return 0;
543}
544
545static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
546 _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
2fd9ae2e 547 int r;
b92bea5d
ZJS
548 struct addrinfo *result, hints = {
549 .ai_socktype = SOCK_STREAM,
550 .ai_flags = AI_ADDRCONFIG,
551 };
2fd9ae2e
LP
552
553 assert(b);
554 assert(p);
555 assert(*p);
556 assert(guid);
557
558 while (**p != 0 && **p != ';') {
559 r = parse_address_key(p, "guid", guid);
560 if (r < 0)
561 return r;
562 else if (r > 0)
563 continue;
564
565 r = parse_address_key(p, "host", &host);
566 if (r < 0)
567 return r;
568 else if (r > 0)
569 continue;
570
571 r = parse_address_key(p, "port", &port);
572 if (r < 0)
573 return r;
574 else if (r > 0)
575 continue;
576
577 r = parse_address_key(p, "family", &family);
578 if (r < 0)
579 return r;
580 else if (r > 0)
581 continue;
582
583 skip_address_key(p);
584 }
585
586 if (!host || !port)
587 return -EINVAL;
588
2fd9ae2e
LP
589 if (family) {
590 if (streq(family, "ipv4"))
591 hints.ai_family = AF_INET;
592 else if (streq(family, "ipv6"))
593 hints.ai_family = AF_INET6;
594 else
595 return -EINVAL;
596 }
597
598 r = getaddrinfo(host, port, &hints, &result);
599 if (r == EAI_SYSTEM)
600 return -errno;
601 else if (r != 0)
602 return -EADDRNOTAVAIL;
603
604 memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
605 b->sockaddr_size = result->ai_addrlen;
606
607 freeaddrinfo(result);
608
609 return 0;
610}
611
612static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
613 char *path = NULL;
614 unsigned n_argv = 0, j;
615 char **argv = NULL;
821e0756 616 size_t allocated = 0;
2fd9ae2e
LP
617 int r;
618
619 assert(b);
620 assert(p);
621 assert(*p);
622 assert(guid);
623
624 while (**p != 0 && **p != ';') {
625 r = parse_address_key(p, "guid", guid);
626 if (r < 0)
627 goto fail;
628 else if (r > 0)
629 continue;
630
631 r = parse_address_key(p, "path", &path);
632 if (r < 0)
633 goto fail;
634 else if (r > 0)
635 continue;
636
637 if (startswith(*p, "argv")) {
638 unsigned ul;
639
640 errno = 0;
641 ul = strtoul(*p + 4, (char**) p, 10);
8333c77e 642 if (errno > 0 || **p != '=' || ul > 256) {
2fd9ae2e
LP
643 r = -EINVAL;
644 goto fail;
645 }
646
647 (*p) ++;
648
649 if (ul >= n_argv) {
821e0756 650 if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) {
2fd9ae2e
LP
651 r = -ENOMEM;
652 goto fail;
653 }
654
2fd9ae2e
LP
655 n_argv = ul + 1;
656 }
657
658 r = parse_address_key(p, NULL, argv + ul);
de1c301e 659 if (r < 0)
2fd9ae2e 660 goto fail;
de1c301e 661
2fd9ae2e 662 continue;
de1c301e
LP
663 }
664
2fd9ae2e
LP
665 skip_address_key(p);
666 }
de1c301e 667
5a0f6033
LP
668 if (!path) {
669 r = -EINVAL;
2fd9ae2e 670 goto fail;
5a0f6033 671 }
de1c301e 672
2fd9ae2e
LP
673 /* Make sure there are no holes in the array, with the
674 * exception of argv[0] */
675 for (j = 1; j < n_argv; j++)
676 if (!argv[j]) {
677 r = -EINVAL;
678 goto fail;
679 }
680
681 if (argv && argv[0] == NULL) {
682 argv[0] = strdup(path);
683 if (!argv[0]) {
684 r = -ENOMEM;
685 goto fail;
686 }
687 }
de1c301e 688
2fd9ae2e
LP
689 b->exec_path = path;
690 b->exec_argv = argv;
691 return 0;
de1c301e 692
2fd9ae2e
LP
693fail:
694 for (j = 0; j < n_argv; j++)
695 free(argv[j]);
696
697 free(argv);
698 free(path);
699 return r;
700}
701
6629161f
LP
702static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
703 _cleanup_free_ char *path = NULL;
704 int r;
705
706 assert(b);
707 assert(p);
708 assert(*p);
709 assert(guid);
710
711 while (**p != 0 && **p != ';') {
712 r = parse_address_key(p, "guid", guid);
713 if (r < 0)
714 return r;
715 else if (r > 0)
716 continue;
717
718 r = parse_address_key(p, "path", &path);
719 if (r < 0)
720 return r;
721 else if (r > 0)
722 continue;
723
724 skip_address_key(p);
725 }
726
727 if (!path)
728 return -EINVAL;
729
730 free(b->kernel);
731 b->kernel = path;
732 path = NULL;
733
734 return 0;
735}
736
bc9fd78c 737static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) {
a7893c6b
LP
738 _cleanup_free_ char *machine = NULL;
739 int r;
740
741 assert(b);
742 assert(p);
743 assert(*p);
744 assert(guid);
745
746 while (**p != 0 && **p != ';') {
747 r = parse_address_key(p, "guid", guid);
748 if (r < 0)
749 return r;
750 else if (r > 0)
751 continue;
752
753 r = parse_address_key(p, "machine", &machine);
754 if (r < 0)
755 return r;
756 else if (r > 0)
757 continue;
758
759 skip_address_key(p);
760 }
761
762 if (!machine)
763 return -EINVAL;
764
b6741478
LP
765 if (!filename_is_safe(machine))
766 return -EINVAL;
767
a7893c6b
LP
768 free(b->machine);
769 b->machine = machine;
770 machine = NULL;
771
772 b->sockaddr.un.sun_family = AF_UNIX;
773 strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
774 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/var/run/dbus/system_bus_socket") - 1;
775
776 return 0;
777}
778
bc9fd78c
LP
779static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid) {
780 _cleanup_free_ char *machine = NULL;
781 int r;
782
783 assert(b);
784 assert(p);
785 assert(*p);
786 assert(guid);
787
788 while (**p != 0 && **p != ';') {
789 r = parse_address_key(p, "guid", guid);
790 if (r < 0)
791 return r;
792 else if (r > 0)
793 continue;
794
795 r = parse_address_key(p, "machine", &machine);
796 if (r < 0)
797 return r;
798 else if (r > 0)
799 continue;
800
801 skip_address_key(p);
802 }
803
804 if (!machine)
805 return -EINVAL;
806
807 if (!filename_is_safe(machine))
808 return -EINVAL;
809
810 free(b->machine);
811 b->machine = machine;
812 machine = NULL;
813
814 free(b->kernel);
815 b->kernel = strdup("/dev/kdbus/0-system/bus");
816 if (!b->kernel)
817 return -ENOMEM;
818
819 return 0;
820}
821
2fd9ae2e
LP
822static void bus_reset_parsed_address(sd_bus *b) {
823 assert(b);
824
825 zero(b->sockaddr);
826 b->sockaddr_size = 0;
827 strv_free(b->exec_argv);
828 free(b->exec_path);
829 b->exec_path = NULL;
830 b->exec_argv = NULL;
98178d39 831 b->server_id = SD_ID128_NULL;
6629161f
LP
832 free(b->kernel);
833 b->kernel = NULL;
a7893c6b
LP
834 free(b->machine);
835 b->machine = NULL;
2fd9ae2e
LP
836}
837
838static int bus_parse_next_address(sd_bus *b) {
839 _cleanup_free_ char *guid = NULL;
840 const char *a;
841 int r;
842
843 assert(b);
844
845 if (!b->address)
846 return 0;
847 if (b->address[b->address_index] == 0)
848 return 0;
849
850 bus_reset_parsed_address(b);
851
852 a = b->address + b->address_index;
de1c301e 853
2fd9ae2e 854 while (*a != 0) {
de1c301e 855
2fd9ae2e
LP
856 if (*a == ';') {
857 a++;
858 continue;
de1c301e
LP
859 }
860
2fd9ae2e
LP
861 if (startswith(a, "unix:")) {
862 a += 5;
de1c301e 863
2fd9ae2e 864 r = parse_unix_address(b, &a, &guid);
de1c301e
LP
865 if (r < 0)
866 return r;
2fd9ae2e 867 break;
de1c301e 868
2fd9ae2e 869 } else if (startswith(a, "tcp:")) {
de1c301e 870
2fd9ae2e
LP
871 a += 4;
872 r = parse_tcp_address(b, &a, &guid);
de1c301e
LP
873 if (r < 0)
874 return r;
de1c301e 875
2fd9ae2e
LP
876 break;
877
878 } else if (startswith(a, "unixexec:")) {
879
880 a += 9;
881 r = parse_exec_address(b, &a, &guid);
de1c301e
LP
882 if (r < 0)
883 return r;
de1c301e 884
2fd9ae2e 885 break;
de1c301e 886
6629161f
LP
887 } else if (startswith(a, "kernel:")) {
888
889 a += 7;
890 r = parse_kernel_address(b, &a, &guid);
891 if (r < 0)
892 return r;
893
a7893c6b 894 break;
bc9fd78c
LP
895 } else if (startswith(a, "x-container-unix:")) {
896
897 a += 17;
898 r = parse_container_unix_address(b, &a, &guid);
899 if (r < 0)
900 return r;
901
902 break;
903 } else if (startswith(a, "x-container-kernel:")) {
a7893c6b 904
bc9fd78c
LP
905 a += 19;
906 r = parse_container_kernel_address(b, &a, &guid);
a7893c6b
LP
907 if (r < 0)
908 return r;
909
6629161f 910 break;
de1c301e
LP
911 }
912
2fd9ae2e
LP
913 a = strchr(a, ';');
914 if (!a)
915 return 0;
de1c301e
LP
916 }
917
918 if (guid) {
98178d39 919 r = sd_id128_from_string(guid, &b->server_id);
de1c301e
LP
920 if (r < 0)
921 return r;
922 }
923
2fd9ae2e 924 b->address_index = a - b->address;
de1c301e
LP
925 return 1;
926}
927
a7e3212d 928static int bus_start_address(sd_bus *b) {
2fd9ae2e
LP
929 int r;
930
931 assert(b);
932
933 for (;;) {
1e05d493 934 bool skipped = false;
2fd9ae2e 935
1e05d493 936 bus_close_fds(b);
a7e3212d 937
1e05d493 938 if (b->exec_path)
a7893c6b 939 r = bus_socket_exec(b);
bc9fd78c
LP
940 else if (b->machine && b->kernel)
941 r = bus_container_connect_kernel(b);
942 else if (b->machine && b->sockaddr.sa.sa_family != AF_UNSPEC)
943 r = bus_container_connect_socket(b);
1e05d493 944 else if (b->kernel)
a7893c6b 945 r = bus_kernel_connect(b);
1e05d493 946 else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
a7893c6b 947 r = bus_socket_connect(b);
1e05d493
LP
948 else
949 skipped = true;
950
951 if (!skipped) {
952 if (r >= 0) {
953 r = attach_io_events(b);
954 if (r >= 0)
955 return r;
956 }
6629161f 957
2fd9ae2e
LP
958 b->last_connect_error = -r;
959 }
960
961 r = bus_parse_next_address(b);
962 if (r < 0)
963 return r;
964 if (r == 0)
965 return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
de1c301e
LP
966 }
967}
968
a7e3212d
LP
969int bus_next_address(sd_bus *b) {
970 assert(b);
971
972 bus_reset_parsed_address(b);
973 return bus_start_address(b);
974}
975
021a1e78 976static int bus_start_fd(sd_bus *b) {
6629161f 977 struct stat st;
021a1e78
LP
978 int r;
979
980 assert(b);
e82c9509
LP
981 assert(b->input_fd >= 0);
982 assert(b->output_fd >= 0);
021a1e78 983
e82c9509 984 r = fd_nonblock(b->input_fd, true);
021a1e78
LP
985 if (r < 0)
986 return r;
987
e82c9509 988 r = fd_cloexec(b->input_fd, true);
021a1e78
LP
989 if (r < 0)
990 return r;
991
e82c9509
LP
992 if (b->input_fd != b->output_fd) {
993 r = fd_nonblock(b->output_fd, true);
994 if (r < 0)
995 return r;
996
997 r = fd_cloexec(b->output_fd, true);
998 if (r < 0)
999 return r;
1000 }
1001
6629161f
LP
1002 if (fstat(b->input_fd, &st) < 0)
1003 return -errno;
1004
1005 if (S_ISCHR(b->input_fd))
1006 return bus_kernel_take_fd(b);
1007 else
1008 return bus_socket_take_fd(b);
021a1e78
LP
1009}
1010
d9f644e2 1011_public_ int sd_bus_start(sd_bus *bus) {
021a1e78
LP
1012 int r;
1013
d6888822
LP
1014 assert_return(bus, -EINVAL);
1015 assert_return(bus->state == BUS_UNSET, -EPERM);
1016 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78
LP
1017
1018 bus->state = BUS_OPENING;
1019
2181a7f5
LP
1020 if (bus->is_server && bus->bus_client)
1021 return -EINVAL;
1022
e82c9509 1023 if (bus->input_fd >= 0)
021a1e78 1024 r = bus_start_fd(bus);
a7893c6b 1025 else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine)
a7e3212d 1026 r = bus_start_address(bus);
021a1e78
LP
1027 else
1028 return -EINVAL;
1029
1030 if (r < 0)
1031 return r;
1032
1033 return bus_send_hello(bus);
1034}
1035
d9f644e2 1036_public_ int sd_bus_open_system(sd_bus **ret) {
de1c301e
LP
1037 const char *e;
1038 sd_bus *b;
1039 int r;
1040
d6888822 1041 assert_return(ret, -EINVAL);
de1c301e 1042
021a1e78
LP
1043 r = sd_bus_new(&b);
1044 if (r < 0)
1045 return r;
1046
6c03089c 1047 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
e3dd987c 1048 if (e)
021a1e78 1049 r = sd_bus_set_address(b, e);
e3dd987c 1050 else
ab9001a1 1051 r = sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_PATH);
e3dd987c
LP
1052 if (r < 0)
1053 goto fail;
de1c301e 1054
94bbf1ba 1055 b->bus_client = true;
021a1e78 1056
adacb957
LP
1057 /* Let's do per-method access control on the system bus. We
1058 * need the caller's UID and capability set for that. */
1059 b->trusted = false;
1060 b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
1061
021a1e78
LP
1062 r = sd_bus_start(b);
1063 if (r < 0)
1064 goto fail;
de1c301e
LP
1065
1066 *ret = b;
1067 return 0;
021a1e78
LP
1068
1069fail:
1070 bus_free(b);
1071 return r;
de1c301e
LP
1072}
1073
d9f644e2 1074_public_ int sd_bus_open_user(sd_bus **ret) {
de1c301e
LP
1075 const char *e;
1076 sd_bus *b;
de1c301e
LP
1077 int r;
1078
d6888822 1079 assert_return(ret, -EINVAL);
de1c301e 1080
021a1e78
LP
1081 r = sd_bus_new(&b);
1082 if (r < 0)
1083 return r;
1084
6c03089c 1085 e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
de1c301e 1086 if (e) {
021a1e78 1087 r = sd_bus_set_address(b, e);
de1c301e 1088 if (r < 0)
021a1e78 1089 goto fail;
89ffcd2a 1090 } else {
6c03089c 1091 e = secure_getenv("XDG_RUNTIME_DIR");
e3dd987c
LP
1092 if (e) {
1093 _cleanup_free_ char *ee = NULL;
1094
1095 ee = bus_address_escape(e);
1096 if (!ee) {
626851be 1097 r = -ENOMEM;
e3dd987c
LP
1098 goto fail;
1099 }
1100
626851be 1101#ifdef ENABLE_KDBUS
ab9001a1 1102 asprintf(&b->address, KERNEL_USER_BUS_FMT ";" UNIX_USER_BUS_FMT, (unsigned long) getuid(), ee);
626851be 1103#else
2047a15a 1104 asprintf(&b->address, UNIX_USER_BUS_FMT, ee);
626851be
LP
1105#endif
1106 } else {
1107#ifdef ENABLE_KDBUS
ab9001a1 1108 asprintf(&b->address, KERNEL_USER_BUS_FMT, (unsigned long) getuid());
626851be
LP
1109#else
1110 return -ECONNREFUSED;
1111#endif
1112 }
de1c301e 1113
e3dd987c
LP
1114 if (!b->address) {
1115 r = -ENOMEM;
021a1e78
LP
1116 goto fail;
1117 }
de1c301e
LP
1118 }
1119
94bbf1ba 1120 b->bus_client = true;
de1c301e 1121
adacb957
LP
1122 /* We don't do any per-method access control on the user
1123 * bus. */
1124 b->trusted = true;
1125
021a1e78 1126 r = sd_bus_start(b);
2571ead1
LP
1127 if (r < 0)
1128 goto fail;
de1c301e
LP
1129
1130 *ret = b;
1131 return 0;
2571ead1
LP
1132
1133fail:
021a1e78 1134 bus_free(b);
2571ead1 1135 return r;
de1c301e
LP
1136}
1137
d9f644e2 1138_public_ int sd_bus_open_system_remote(const char *host, sd_bus **ret) {
0f8bd8de
LP
1139 _cleanup_free_ char *e = NULL;
1140 char *p = NULL;
1141 sd_bus *bus;
1142 int r;
1143
1144 assert_return(host, -EINVAL);
1145 assert_return(ret, -EINVAL);
1146
1147 e = bus_address_escape(host);
1148 if (!e)
1149 return -ENOMEM;
1150
1151 p = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL);
1152 if (!p)
1153 return -ENOMEM;
a7893c6b
LP
1154
1155 r = sd_bus_new(&bus);
1156 if (r < 0) {
1157 free(p);
1158 return r;
1159 }
1160
1161 bus->address = p;
1162 bus->bus_client = true;
1163
1164 r = sd_bus_start(bus);
1165 if (r < 0) {
1166 bus_free(bus);
1167 return r;
1168 }
1169
1170 *ret = bus;
1171 return 0;
1172}
1173
d9f644e2 1174_public_ int sd_bus_open_system_container(const char *machine, sd_bus **ret) {
a7893c6b
LP
1175 _cleanup_free_ char *e = NULL;
1176 sd_bus *bus;
1177 char *p;
1178 int r;
1179
1180 assert_return(machine, -EINVAL);
1181 assert_return(ret, -EINVAL);
9e554864 1182 assert_return(filename_is_safe(machine), -EINVAL);
a7893c6b
LP
1183
1184 e = bus_address_escape(machine);
1185 if (!e)
1186 return -ENOMEM;
1187
9e554864 1188#ifdef ENABLE_KDBUS
bc9fd78c 1189 p = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
9e554864 1190#else
bc9fd78c 1191 p = strjoin("x-container-unix:machine=", e, NULL);
9e554864 1192#endif
a7893c6b
LP
1193 if (!p)
1194 return -ENOMEM;
0f8bd8de
LP
1195
1196 r = sd_bus_new(&bus);
1197 if (r < 0) {
1198 free(p);
1199 return r;
1200 }
1201
1202 bus->address = p;
1203 bus->bus_client = true;
1204
1205 r = sd_bus_start(bus);
1206 if (r < 0) {
1207 bus_free(bus);
1208 return r;
1209 }
1210
1211 *ret = bus;
1212 return 0;
1213}
1214
d9f644e2 1215_public_ void sd_bus_close(sd_bus *bus) {
0e586eae 1216
de1c301e
LP
1217 if (!bus)
1218 return;
d5a2b9a6
LP
1219 if (bus->state == BUS_CLOSED)
1220 return;
1221 if (bus_pid_changed(bus))
f54514f3
LP
1222 return;
1223
1224 bus->state = BUS_CLOSED;
e82c9509 1225
40ca29a1
LP
1226 sd_bus_detach_event(bus);
1227
0e586eae
LP
1228 /* Drop all queued messages so that they drop references to
1229 * the bus object and the bus may be freed */
1230 bus_reset_queues(bus);
1231
f54514f3
LP
1232 if (!bus->is_kernel)
1233 bus_close_fds(bus);
1234
1235 /* We'll leave the fd open in case this is a kernel bus, since
1236 * there might still be memblocks around that reference this
cd6d5e1c 1237 * bus, and they might need to invoke the KDBUS_CMD_FREE
1d0e3c98 1238 * ioctl on the fd when they are freed. */
de1c301e
LP
1239}
1240
718db961
LP
1241static void bus_enter_closing(sd_bus *bus) {
1242 assert(bus);
1243
1244 if (bus->state != BUS_OPENING &&
1245 bus->state != BUS_AUTHENTICATING &&
1246 bus->state != BUS_HELLO &&
1247 bus->state != BUS_RUNNING)
1248 return;
1249
1250 bus->state = BUS_CLOSING;
1251}
1252
d9f644e2 1253_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
9d6c7c82 1254 assert_return(bus, NULL);
de1c301e 1255
e4ee6e5c 1256 assert_se(REFCNT_INC(bus->n_ref) >= 2);
de1c301e 1257
de1c301e
LP
1258 return bus;
1259}
1260
d9f644e2 1261_public_ sd_bus *sd_bus_unref(sd_bus *bus) {
5b1bc83f
LP
1262
1263 if (!bus)
1264 return NULL;
de1c301e 1265
e4ee6e5c 1266 if (REFCNT_DEC(bus->n_ref) <= 0)
de1c301e
LP
1267 bus_free(bus);
1268
1269 return NULL;
1270}
1271
d9f644e2 1272_public_ int sd_bus_is_open(sd_bus *bus) {
d6888822
LP
1273
1274 assert_return(bus, -EINVAL);
1275 assert_return(!bus_pid_changed(bus), -ECHILD);
e3017af9 1276
f54514f3 1277 return BUS_IS_OPEN(bus->state);
e3017af9
LP
1278}
1279
d9f644e2 1280_public_ int sd_bus_can_send(sd_bus *bus, char type) {
d728d708
LP
1281 int r;
1282
d6888822
LP
1283 assert_return(bus, -EINVAL);
1284 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
1285 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 1286
d728d708 1287 if (type == SD_BUS_TYPE_UNIX_FD) {
264ad849 1288 if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
021a1e78
LP
1289 return 0;
1290
20902f3e 1291 r = bus_ensure_running(bus);
d728d708
LP
1292 if (r < 0)
1293 return r;
de1c301e 1294
d728d708
LP
1295 return bus->can_fds;
1296 }
1297
1298 return bus_type_is_valid(type);
de1c301e
LP
1299}
1300
d9f644e2 1301_public_ int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
d728d708 1302 int r;
de1c301e 1303
d6888822
LP
1304 assert_return(bus, -EINVAL);
1305 assert_return(server_id, -EINVAL);
1306 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 1307
20902f3e 1308 r = bus_ensure_running(bus);
d728d708
LP
1309 if (r < 0)
1310 return r;
de1c301e 1311
98178d39 1312 *server_id = bus->server_id;
d728d708 1313 return 0;
de1c301e
LP
1314}
1315
3df7a7e6 1316static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
7adc46fc 1317 assert(b);
de1c301e
LP
1318 assert(m);
1319
aea93deb
LP
1320 if (m->sealed) {
1321 /* If we copy the same message to multiple
693eb9a2 1322 * destinations, avoid using the same cookie
aea93deb 1323 * numbers. */
693eb9a2 1324 b->cookie = MAX(b->cookie, BUS_MESSAGE_COOKIE(m));
de1c301e 1325 return 0;
aea93deb 1326 }
de1c301e 1327
3df7a7e6
LP
1328 if (timeout == 0)
1329 timeout = BUS_DEFAULT_TIMEOUT;
1330
693eb9a2 1331 return bus_message_seal(m, ++b->cookie, timeout);
de1c301e
LP
1332}
1333
e1c433c6
LP
1334static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
1335 assert(b);
1336
1337 /* Do packet version and endianess already match? */
1338 if ((b->message_version == 0 || b->message_version == (*m)->header->version) &&
1339 (b->message_endian == 0 || b->message_endian == (*m)->header->endian))
1340 return 0;
1341
1342 /* No? Then remarshal! */
1343 return bus_message_remarshal(b, m);
1344}
1345
7adc46fc
LP
1346int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
1347 assert(b);
1348 assert(m);
1349
7adc46fc
LP
1350 /* The bus specification says the serial number cannot be 0,
1351 * hence let's fill something in for synthetic messages. Since
1352 * synthetic messages might have a fake sender and we don't
1353 * want to interfere with the real sender's serial numbers we
1354 * pick a fixed, artifical one. We use (uint32_t) -1 rather
1355 * than (uint64_t) -1 since dbus1 only had 32bit identifiers,
1356 * even though kdbus can do 64bit. */
1357
3df7a7e6 1358 return bus_message_seal(m, 0xFFFFFFFFULL, 0);
7adc46fc
LP
1359}
1360
2e3db52d
LP
1361static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
1362 int r;
1363
718db961 1364 assert(bus);
2e3db52d 1365 assert(m);
718db961
LP
1366
1367 if (bus->is_kernel)
2e3db52d 1368 r = bus_kernel_write_message(bus, m);
718db961 1369 else
2e3db52d
LP
1370 r = bus_socket_write_message(bus, m, idx);
1371
1372 if (r <= 0)
1373 return r;
1374
90911bb6 1375 if (bus->is_kernel || *idx >= BUS_MESSAGE_SIZE(m))
693eb9a2 1376 log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%lu reply_cookie=%lu error=%s",
2e3db52d
LP
1377 bus_message_type_to_string(m->header->type),
1378 strna(sd_bus_message_get_sender(m)),
1379 strna(sd_bus_message_get_destination(m)),
1380 strna(sd_bus_message_get_path(m)),
1381 strna(sd_bus_message_get_interface(m)),
1382 strna(sd_bus_message_get_member(m)),
693eb9a2
LP
1383 (unsigned long) BUS_MESSAGE_COOKIE(m),
1384 (unsigned long) m->reply_cookie,
2e3db52d
LP
1385 strna(m->error.message));
1386
1387 return r;
718db961
LP
1388}
1389
de1c301e 1390static int dispatch_wqueue(sd_bus *bus) {
e3017af9 1391 int r, ret = 0;
de1c301e
LP
1392
1393 assert(bus);
89ffcd2a 1394 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1395
de1c301e
LP
1396 while (bus->wqueue_size > 0) {
1397
718db961
LP
1398 r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
1399 if (r < 0)
de1c301e 1400 return r;
718db961 1401 else if (r == 0)
e3017af9
LP
1402 /* Didn't do anything this time */
1403 return ret;
6629161f 1404 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
de1c301e
LP
1405 /* Fully written. Let's drop the entry from
1406 * the queue.
1407 *
1408 * This isn't particularly optimized, but
1409 * well, this is supposed to be our worst-case
1410 * buffer only, and the socket buffer is
1411 * supposed to be our primary buffer, and if
1412 * it got full, then all bets are off
1413 * anyway. */
1414
1415 sd_bus_message_unref(bus->wqueue[0]);
1416 bus->wqueue_size --;
1417 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1418 bus->windex = 0;
1419
e3017af9 1420 ret = 1;
de1c301e
LP
1421 }
1422 }
1423
e3017af9 1424 return ret;
de1c301e
LP
1425}
1426
7d22c717
LP
1427static int bus_read_message(sd_bus *bus) {
1428 assert(bus);
1429
1430 if (bus->is_kernel)
1431 return bus_kernel_read_message(bus);
1432 else
1433 return bus_socket_read_message(bus);
1434}
1435
7adc46fc 1436int bus_rqueue_make_room(sd_bus *bus) {
821e0756 1437 assert(bus);
7d22c717 1438
821e0756 1439 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
7d22c717
LP
1440 return -ENOBUFS;
1441
821e0756 1442 if (!GREEDY_REALLOC(bus->rqueue, bus->rqueue_allocated, bus->rqueue_size + 1))
7d22c717
LP
1443 return -ENOMEM;
1444
7d22c717
LP
1445 return 0;
1446}
1447
de1c301e 1448static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
e3017af9 1449 int r, ret = 0;
de1c301e
LP
1450
1451 assert(bus);
1452 assert(m);
89ffcd2a 1453 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1454
7d22c717
LP
1455 for (;;) {
1456 if (bus->rqueue_size > 0) {
1457 /* Dispatch a queued message */
de1c301e 1458
7d22c717
LP
1459 *m = bus->rqueue[0];
1460 bus->rqueue_size --;
1461 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1462 return 1;
1463 }
de1c301e 1464
7d22c717
LP
1465 /* Try to read a new message */
1466 r = bus_read_message(bus);
718db961 1467 if (r < 0)
e3017af9 1468 return r;
e3017af9
LP
1469 if (r == 0)
1470 return ret;
de1c301e 1471
2e8d788c 1472 ret = 1;
7d22c717 1473 }
de1c301e
LP
1474}
1475
693eb9a2 1476_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
e1c433c6 1477 _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
de1c301e
LP
1478 int r;
1479
d6888822
LP
1480 assert_return(bus, -EINVAL);
1481 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1482 assert_return(m, -EINVAL);
1483 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78
LP
1484
1485 if (m->n_fds > 0) {
1486 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1487 if (r < 0)
1488 return r;
1489 if (r == 0)
1490 return -ENOTSUP;
1491 }
de1c301e 1492
693eb9a2 1493 /* If the cookie number isn't kept, then we know that no reply
29f6aadd 1494 * is expected */
693eb9a2 1495 if (!cookie && !m->sealed)
0461f8cd 1496 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
29f6aadd 1497
3df7a7e6 1498 r = bus_seal_message(bus, m, 0);
de1c301e
LP
1499 if (r < 0)
1500 return r;
1501
e1c433c6
LP
1502 /* Remarshall if we have to. This will possible unref the
1503 * message and place a replacement in m */
1504 r = bus_remarshal_message(bus, &m);
1505 if (r < 0)
1506 return r;
1507
5407f2de
LP
1508 /* If this is a reply and no reply was requested, then let's
1509 * suppress this, if we can */
693eb9a2 1510 if (m->dont_send && !cookie)
7a37d625 1511 return 1;
5407f2de 1512
89ffcd2a 1513 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
de1c301e
LP
1514 size_t idx = 0;
1515
718db961 1516 r = bus_write_message(bus, m, &idx);
32f46480
LP
1517 if (r < 0) {
1518 if (r == -EPIPE || r == -ENOTCONN || r == -ESHUTDOWN)
1519 bus_enter_closing(bus);
1520
de1c301e 1521 return r;
32f46480 1522 } else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
de1c301e
LP
1523 /* Wasn't fully written. So let's remember how
1524 * much was written. Note that the first entry
1525 * of the wqueue array is always allocated so
1526 * that we always can remember how much was
1527 * written. */
1528 bus->wqueue[0] = sd_bus_message_ref(m);
1529 bus->wqueue_size = 1;
1530 bus->windex = idx;
1531 }
1532 } else {
de1c301e
LP
1533 /* Just append it to the queue. */
1534
25220239 1535 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
de1c301e
LP
1536 return -ENOBUFS;
1537
821e0756 1538 if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
de1c301e
LP
1539 return -ENOMEM;
1540
821e0756 1541 bus->wqueue[bus->wqueue_size ++] = sd_bus_message_ref(m);
de1c301e
LP
1542 }
1543
693eb9a2
LP
1544 if (cookie)
1545 *cookie = BUS_MESSAGE_COOKIE(m);
de1c301e 1546
7a37d625 1547 return 1;
de1c301e
LP
1548}
1549
693eb9a2 1550_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) {
911121a7
LP
1551 int r;
1552
1553 assert_return(bus, -EINVAL);
1554 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1555 assert_return(m, -EINVAL);
1556 assert_return(!bus_pid_changed(bus), -ECHILD);
1557
1558 if (!streq_ptr(m->destination, destination)) {
1559
1560 if (!destination)
1561 return -EEXIST;
1562
1563 r = sd_bus_message_set_destination(m, destination);
1564 if (r < 0)
1565 return r;
1566 }
1567
693eb9a2 1568 return sd_bus_send(bus, m, cookie);
911121a7
LP
1569}
1570
de1c301e
LP
1571static usec_t calc_elapse(uint64_t usec) {
1572 if (usec == (uint64_t) -1)
1573 return 0;
1574
de1c301e
LP
1575 return now(CLOCK_MONOTONIC) + usec;
1576}
1577
e3017af9
LP
1578static int timeout_compare(const void *a, const void *b) {
1579 const struct reply_callback *x = a, *y = b;
1580
1581 if (x->timeout != 0 && y->timeout == 0)
1582 return -1;
1583
1584 if (x->timeout == 0 && y->timeout != 0)
1585 return 1;
1586
1587 if (x->timeout < y->timeout)
1588 return -1;
1589
1590 if (x->timeout > y->timeout)
1591 return 1;
1592
1593 return 0;
1594}
1595
c49b30a2 1596_public_ int sd_bus_call_async(
de1c301e 1597 sd_bus *bus,
e1c433c6 1598 sd_bus_message *_m,
52f3ba91 1599 sd_bus_message_handler_t callback,
de1c301e
LP
1600 void *userdata,
1601 uint64_t usec,
693eb9a2 1602 uint64_t *cookie) {
de1c301e 1603
e1c433c6 1604 _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
de1c301e
LP
1605 struct reply_callback *c;
1606 int r;
1607
d6888822
LP
1608 assert_return(bus, -EINVAL);
1609 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1610 assert_return(m, -EINVAL);
40ca29a1 1611 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
0461f8cd 1612 assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
d6888822
LP
1613 assert_return(callback, -EINVAL);
1614 assert_return(!bus_pid_changed(bus), -ECHILD);
89ffcd2a
LP
1615
1616 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1617 if (r < 0)
1618 return r;
de1c301e 1619
3df7a7e6
LP
1620 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1621 if (r < 0)
1622 return r;
e3017af9 1623
3df7a7e6 1624 r = bus_seal_message(bus, m, usec);
de1c301e
LP
1625 if (r < 0)
1626 return r;
1627
e1c433c6
LP
1628 r = bus_remarshal_message(bus, &m);
1629 if (r < 0)
1630 return r;
1631
eba8617e 1632 c = new0(struct reply_callback, 1);
de1c301e
LP
1633 if (!c)
1634 return -ENOMEM;
1635
1636 c->callback = callback;
1637 c->userdata = userdata;
693eb9a2 1638 c->cookie = BUS_MESSAGE_COOKIE(m);
3df7a7e6 1639 c->timeout = calc_elapse(m->timeout);
de1c301e 1640
693eb9a2 1641 r = hashmap_put(bus->reply_callbacks, &c->cookie, c);
de1c301e
LP
1642 if (r < 0) {
1643 free(c);
1644 return r;
1645 }
1646
e3017af9
LP
1647 if (c->timeout != 0) {
1648 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1649 if (r < 0) {
1650 c->timeout = 0;
693eb9a2 1651 sd_bus_call_async_cancel(bus, c->cookie);
e3017af9
LP
1652 return r;
1653 }
1654 }
1655
693eb9a2 1656 r = sd_bus_send(bus, m, cookie);
de1c301e 1657 if (r < 0) {
693eb9a2 1658 sd_bus_call_async_cancel(bus, c->cookie);
de1c301e
LP
1659 return r;
1660 }
1661
1662 return r;
1663}
1664
693eb9a2 1665_public_ int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie) {
e3017af9 1666 struct reply_callback *c;
de1c301e 1667
d6888822 1668 assert_return(bus, -EINVAL);
693eb9a2 1669 assert_return(cookie != 0, -EINVAL);
d6888822 1670 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 1671
693eb9a2 1672 c = hashmap_remove(bus->reply_callbacks, &cookie);
de1c301e
LP
1673 if (!c)
1674 return 0;
1675
e3017af9
LP
1676 if (c->timeout != 0)
1677 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1678
de1c301e
LP
1679 free(c);
1680 return 1;
1681}
1682
20902f3e 1683int bus_ensure_running(sd_bus *bus) {
89ffcd2a
LP
1684 int r;
1685
1686 assert(bus);
1687
718db961 1688 if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING)
021a1e78 1689 return -ENOTCONN;
d728d708
LP
1690 if (bus->state == BUS_RUNNING)
1691 return 1;
89ffcd2a
LP
1692
1693 for (;;) {
1694 r = sd_bus_process(bus, NULL);
1695 if (r < 0)
1696 return r;
d728d708
LP
1697 if (bus->state == BUS_RUNNING)
1698 return 1;
e3017af9
LP
1699 if (r > 0)
1700 continue;
89ffcd2a
LP
1701
1702 r = sd_bus_wait(bus, (uint64_t) -1);
1703 if (r < 0)
1704 return r;
1705 }
1706}
1707
c49b30a2 1708_public_ int sd_bus_call(
de1c301e 1709 sd_bus *bus,
e1c433c6 1710 sd_bus_message *_m,
de1c301e
LP
1711 uint64_t usec,
1712 sd_bus_error *error,
1713 sd_bus_message **reply) {
1714
e1c433c6 1715 _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
de1c301e 1716 usec_t timeout;
693eb9a2 1717 uint64_t cookie;
7d22c717
LP
1718 unsigned i;
1719 int r;
de1c301e 1720
d6888822
LP
1721 assert_return(bus, -EINVAL);
1722 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1723 assert_return(m, -EINVAL);
40ca29a1 1724 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
0461f8cd 1725 assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
d6888822
LP
1726 assert_return(!bus_error_is_dirty(error), -EINVAL);
1727 assert_return(!bus_pid_changed(bus), -ECHILD);
89ffcd2a 1728
20902f3e 1729 r = bus_ensure_running(bus);
89ffcd2a
LP
1730 if (r < 0)
1731 return r;
de1c301e 1732
a43b9ca3
LP
1733 i = bus->rqueue_size;
1734
3df7a7e6
LP
1735 r = bus_seal_message(bus, m, usec);
1736 if (r < 0)
1737 return r;
1738
e1c433c6
LP
1739 r = bus_remarshal_message(bus, &m);
1740 if (r < 0)
1741 return r;
1742
693eb9a2 1743 r = sd_bus_send(bus, m, &cookie);
de1c301e
LP
1744 if (r < 0)
1745 return r;
1746
3df7a7e6 1747 timeout = calc_elapse(m->timeout);
de1c301e
LP
1748
1749 for (;;) {
1750 usec_t left;
de1c301e 1751
7d22c717
LP
1752 while (i < bus->rqueue_size) {
1753 sd_bus_message *incoming = NULL;
1754
1755 incoming = bus->rqueue[i];
89ffcd2a 1756
693eb9a2 1757 if (incoming->reply_cookie == cookie) {
de1c301e
LP
1758 /* Found a match! */
1759
7d22c717
LP
1760 memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
1761 bus->rqueue_size--;
1762
40ca29a1 1763 if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
b7f247e0
LP
1764
1765 if (reply)
1766 *reply = incoming;
1767 else
1768 sd_bus_message_unref(incoming);
1769
7a37d625 1770 return 1;
a43b9ca3 1771 } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
de1c301e 1772 r = sd_bus_error_copy(error, &incoming->error);
a43b9ca3
LP
1773 else
1774 r = -EIO;
de1c301e
LP
1775
1776 sd_bus_message_unref(incoming);
a43b9ca3 1777 return r;
a8a07f89 1778
693eb9a2 1779 } else if (BUS_MESSAGE_COOKIE(incoming) == cookie &&
a8a07f89
LP
1780 bus->unique_name &&
1781 incoming->sender &&
1782 streq(bus->unique_name, incoming->sender)) {
1783
7d22c717
LP
1784 memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
1785 bus->rqueue_size--;
1786
a8a07f89
LP
1787 /* Our own message? Somebody is trying
1788 * to send its own client a message,
1789 * let's not dead-lock, let's fail
1790 * immediately. */
1791
1792 sd_bus_message_unref(incoming);
1793 return -ELOOP;
de1c301e
LP
1794 }
1795
de1c301e 1796 /* Try to read more, right-away */
7d22c717 1797 i++;
de1c301e 1798 }
7d22c717 1799
a43b9ca3 1800 r = bus_read_message(bus);
32f46480
LP
1801 if (r < 0) {
1802 if (r == -EPIPE || r == -ENOTCONN || r == -ESHUTDOWN)
1803 bus_enter_closing(bus);
1804
a43b9ca3 1805 return r;
32f46480 1806 }
7d22c717 1807 if (r > 0)
e3017af9 1808 continue;
de1c301e
LP
1809
1810 if (timeout > 0) {
1811 usec_t n;
1812
1813 n = now(CLOCK_MONOTONIC);
1814 if (n >= timeout)
1815 return -ETIMEDOUT;
1816
1817 left = timeout - n;
1818 } else
1819 left = (uint64_t) -1;
1820
e3017af9 1821 r = bus_poll(bus, true, left);
de1c301e
LP
1822 if (r < 0)
1823 return r;
f8e11cda
LP
1824 if (r == 0)
1825 return -ETIMEDOUT;
de1c301e
LP
1826
1827 r = dispatch_wqueue(bus);
32f46480
LP
1828 if (r < 0) {
1829 if (r == -EPIPE || r == -ENOTCONN || r == -ESHUTDOWN)
1830 bus_enter_closing(bus);
1831
de1c301e 1832 return r;
32f46480 1833 }
de1c301e
LP
1834 }
1835}
1836
d9f644e2 1837_public_ int sd_bus_get_fd(sd_bus *bus) {
d6888822
LP
1838
1839 assert_return(bus, -EINVAL);
d6888822
LP
1840 assert_return(bus->input_fd == bus->output_fd, -EPERM);
1841 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 1842
e82c9509 1843 return bus->input_fd;
de1c301e
LP
1844}
1845
d9f644e2 1846_public_ int sd_bus_get_events(sd_bus *bus) {
de1c301e
LP
1847 int flags = 0;
1848
d6888822 1849 assert_return(bus, -EINVAL);
718db961 1850 assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
d6888822 1851 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e
LP
1852
1853 if (bus->state == BUS_OPENING)
1854 flags |= POLLOUT;
89ffcd2a
LP
1855 else if (bus->state == BUS_AUTHENTICATING) {
1856
2181a7f5 1857 if (bus_socket_auth_needs_write(bus))
89ffcd2a
LP
1858 flags |= POLLOUT;
1859
1860 flags |= POLLIN;
1861
1862 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
de1c301e
LP
1863 if (bus->rqueue_size <= 0)
1864 flags |= POLLIN;
1865 if (bus->wqueue_size > 0)
1866 flags |= POLLOUT;
1867 }
1868
1869 return flags;
1870}
1871
d9f644e2 1872_public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
e3017af9
LP
1873 struct reply_callback *c;
1874
d6888822
LP
1875 assert_return(bus, -EINVAL);
1876 assert_return(timeout_usec, -EINVAL);
718db961 1877 assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
d6888822 1878 assert_return(!bus_pid_changed(bus), -ECHILD);
e3017af9 1879
718db961
LP
1880 if (bus->state == BUS_CLOSING) {
1881 *timeout_usec = 0;
1882 return 1;
1883 }
1884
e3017af9
LP
1885 if (bus->state == BUS_AUTHENTICATING) {
1886 *timeout_usec = bus->auth_timeout;
1887 return 1;
1888 }
1889
adee69fa
LP
1890 if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
1891 *timeout_usec = (uint64_t) -1;
e3017af9 1892 return 0;
adee69fa 1893 }
e3017af9 1894
8efd6381
LP
1895 if (bus->rqueue_size > 0) {
1896 *timeout_usec = 0;
1897 return 1;
1898 }
1899
e3017af9 1900 c = prioq_peek(bus->reply_callbacks_prioq);
adee69fa
LP
1901 if (!c) {
1902 *timeout_usec = (uint64_t) -1;
e3017af9 1903 return 0;
adee69fa 1904 }
e3017af9
LP
1905
1906 *timeout_usec = c->timeout;
1907 return 1;
1908}
1909
1910static int process_timeout(sd_bus *bus) {
ebcf1f97 1911 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
eb01ba5d 1912 _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
e3017af9
LP
1913 struct reply_callback *c;
1914 usec_t n;
1915 int r;
1916
1917 assert(bus);
1918
1919 c = prioq_peek(bus->reply_callbacks_prioq);
1920 if (!c)
1921 return 0;
1922
1923 n = now(CLOCK_MONOTONIC);
1924 if (c->timeout > n)
1925 return 0;
1926
eb01ba5d
LP
1927 r = bus_message_new_synthetic_error(
1928 bus,
693eb9a2 1929 c->cookie,
14c24659 1930 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out"),
eb01ba5d
LP
1931 &m);
1932 if (r < 0)
1933 return r;
1934
34a2c9e8
LP
1935 m->sender = "org.freedesktop.DBus";
1936
7adc46fc 1937 r = bus_seal_synthetic_message(bus, m);
718db961
LP
1938 if (r < 0)
1939 return r;
1940
e3017af9 1941 assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
693eb9a2 1942 hashmap_remove(bus->reply_callbacks, &c->cookie);
e3017af9 1943
718db961
LP
1944 bus->current = m;
1945 bus->iteration_counter ++;
1946
ebcf1f97
LP
1947 r = c->callback(bus, m, c->userdata, &error_buffer);
1948 r = bus_maybe_reply_error(m, r, &error_buffer);
e3017af9
LP
1949 free(c);
1950
718db961
LP
1951 bus->current = NULL;
1952
ebcf1f97 1953 return r;
e3017af9
LP
1954}
1955
9d373862
LP
1956static int process_hello(sd_bus *bus, sd_bus_message *m) {
1957 assert(bus);
1958 assert(m);
1959
1960 if (bus->state != BUS_HELLO)
1961 return 0;
1962
1963 /* Let's make sure the first message on the bus is the HELLO
1964 * reply. But note that we don't actually parse the message
2181a7f5
LP
1965 * here (we leave that to the usual handling), we just verify
1966 * we don't let any earlier msg through. */
9d373862 1967
40ca29a1
LP
1968 if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
1969 m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
9d373862
LP
1970 return -EIO;
1971
693eb9a2 1972 if (m->reply_cookie != bus->hello_cookie)
9d373862
LP
1973 return -EIO;
1974
1975 return 0;
1976}
1977
a652755d 1978static int process_reply(sd_bus *bus, sd_bus_message *m) {
ebcf1f97 1979 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
a652755d
LP
1980 struct reply_callback *c;
1981 int r;
1982
1983 assert(bus);
1984 assert(m);
1985
40ca29a1
LP
1986 if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
1987 m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
a652755d
LP
1988 return 0;
1989
693eb9a2 1990 c = hashmap_remove(bus->reply_callbacks, &m->reply_cookie);
a652755d
LP
1991 if (!c)
1992 return 0;
1993
1994 if (c->timeout != 0)
1995 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1996
88fe224c
LP
1997 r = sd_bus_message_rewind(m, true);
1998 if (r < 0)
1999 return r;
2000
ebcf1f97
LP
2001 r = c->callback(bus, m, c->userdata, &error_buffer);
2002 r = bus_maybe_reply_error(m, r, &error_buffer);
a652755d
LP
2003 free(c);
2004
ebcf1f97 2005 return r;
a652755d
LP
2006}
2007
2008static int process_filter(sd_bus *bus, sd_bus_message *m) {
ebcf1f97 2009 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
a652755d
LP
2010 struct filter_callback *l;
2011 int r;
2012
392d5b37
LP
2013 assert(bus);
2014 assert(m);
2015
7286037f
LP
2016 do {
2017 bus->filter_callbacks_modified = false;
2018
2019 LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
2020
2021 if (bus->filter_callbacks_modified)
2022 break;
2023
2024 /* Don't run this more than once per iteration */
2025 if (l->last_iteration == bus->iteration_counter)
2026 continue;
2027
2028 l->last_iteration = bus->iteration_counter;
2029
88fe224c
LP
2030 r = sd_bus_message_rewind(m, true);
2031 if (r < 0)
2032 return r;
2033
969987ea 2034 r = l->callback(bus, m, l->userdata, &error_buffer);
ebcf1f97 2035 r = bus_maybe_reply_error(m, r, &error_buffer);
7286037f
LP
2036 if (r != 0)
2037 return r;
2038
2039 }
2040
2041 } while (bus->filter_callbacks_modified);
a652755d
LP
2042
2043 return 0;
2044}
2045
392d5b37 2046static int process_match(sd_bus *bus, sd_bus_message *m) {
7286037f
LP
2047 int r;
2048
392d5b37
LP
2049 assert(bus);
2050 assert(m);
2051
7286037f
LP
2052 do {
2053 bus->match_callbacks_modified = false;
2054
eb01ba5d 2055 r = bus_match_run(bus, &bus->match_callbacks, m);
7286037f
LP
2056 if (r != 0)
2057 return r;
2058
2059 } while (bus->match_callbacks_modified);
2060
2061 return 0;
392d5b37
LP
2062}
2063
b9bf7e2b
LP
2064static int process_builtin(sd_bus *bus, sd_bus_message *m) {
2065 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2066 int r;
2067
2068 assert(bus);
2069 assert(m);
2070
758bf0c7
LP
2071 if (bus->manual_peer_interface)
2072 return 0;
2073
40ca29a1 2074 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
b9bf7e2b
LP
2075 return 0;
2076
2077 if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
2078 return 0;
2079
0461f8cd 2080 if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
b9bf7e2b
LP
2081 return 1;
2082
2083 if (streq_ptr(m->member, "Ping"))
df2d202e 2084 r = sd_bus_message_new_method_return(m, &reply);
b9bf7e2b
LP
2085 else if (streq_ptr(m->member, "GetMachineId")) {
2086 sd_id128_t id;
2087 char sid[33];
2088
2089 r = sd_id128_get_machine(&id);
2090 if (r < 0)
2091 return r;
2092
df2d202e 2093 r = sd_bus_message_new_method_return(m, &reply);
b9bf7e2b
LP
2094 if (r < 0)
2095 return r;
2096
2097 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
2098 } else {
29ddb38f 2099 r = sd_bus_message_new_method_errorf(
df2d202e 2100 m, &reply,
40ca29a1 2101 SD_BUS_ERROR_UNKNOWN_METHOD,
b9bf7e2b 2102 "Unknown method '%s' on interface '%s'.", m->member, m->interface);
b9bf7e2b
LP
2103 }
2104
2105 if (r < 0)
2106 return r;
2107
2108 r = sd_bus_send(bus, reply, NULL);
2109 if (r < 0)
2110 return r;
2111
2112 return 1;
2113}
2114
992c052c 2115static int process_message(sd_bus *bus, sd_bus_message *m) {
e3017af9
LP
2116 int r;
2117
2118 assert(bus);
992c052c 2119 assert(m);
e3017af9 2120
affff0b6 2121 bus->current = m;
992c052c 2122 bus->iteration_counter++;
e3017af9 2123
693eb9a2 2124 log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%lu reply_cookie=%lu error=%s",
4cdf0751 2125 bus_message_type_to_string(m->header->type),
40ca29a1 2126 strna(sd_bus_message_get_sender(m)),
4cdf0751 2127 strna(sd_bus_message_get_destination(m)),
40ca29a1
LP
2128 strna(sd_bus_message_get_path(m)),
2129 strna(sd_bus_message_get_interface(m)),
4cdf0751 2130 strna(sd_bus_message_get_member(m)),
693eb9a2
LP
2131 (unsigned long) BUS_MESSAGE_COOKIE(m),
2132 (unsigned long) m->reply_cookie,
4cdf0751 2133 strna(m->error.message));
40ca29a1 2134
992c052c
LP
2135 r = process_hello(bus, m);
2136 if (r != 0)
affff0b6 2137 goto finish;
a652755d 2138
992c052c
LP
2139 r = process_reply(bus, m);
2140 if (r != 0)
affff0b6 2141 goto finish;
e3017af9 2142
992c052c
LP
2143 r = process_filter(bus, m);
2144 if (r != 0)
affff0b6 2145 goto finish;
a652755d 2146
992c052c
LP
2147 r = process_match(bus, m);
2148 if (r != 0)
affff0b6 2149 goto finish;
a652755d 2150
992c052c
LP
2151 r = process_builtin(bus, m);
2152 if (r != 0)
affff0b6
LP
2153 goto finish;
2154
2155 r = bus_process_object(bus, m);
a652755d 2156
affff0b6
LP
2157finish:
2158 bus->current = NULL;
2159 return r;
29ddb38f 2160}
88fe224c 2161
992c052c
LP
2162static int process_running(sd_bus *bus, sd_bus_message **ret) {
2163 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
29ddb38f 2164 int r;
a652755d 2165
29ddb38f 2166 assert(bus);
992c052c 2167 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
7286037f 2168
992c052c
LP
2169 r = process_timeout(bus);
2170 if (r != 0)
2171 goto null_message;
7286037f 2172
992c052c
LP
2173 r = dispatch_wqueue(bus);
2174 if (r != 0)
2175 goto null_message;
7286037f 2176
992c052c
LP
2177 r = dispatch_rqueue(bus, &m);
2178 if (r < 0)
2179 return r;
2180 if (!m)
2181 goto null_message;
7286037f 2182
992c052c
LP
2183 r = process_message(bus, m);
2184 if (r != 0)
2185 goto null_message;
7286037f 2186
992c052c
LP
2187 if (ret) {
2188 r = sd_bus_message_rewind(m, true);
29ddb38f
LP
2189 if (r < 0)
2190 return r;
e3017af9 2191
992c052c
LP
2192 *ret = m;
2193 m = NULL;
2194 return 1;
2195 }
a652755d 2196
40ca29a1 2197 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) {
a652755d 2198
dc74ce9b
LP
2199 log_debug("Unprocessed message call sender=%s object=%s interface=%s member=%s",
2200 strna(sd_bus_message_get_sender(m)),
2201 strna(sd_bus_message_get_path(m)),
2202 strna(sd_bus_message_get_interface(m)),
2203 strna(sd_bus_message_get_member(m)));
2204
992c052c 2205 r = sd_bus_reply_method_errorf(
df2d202e 2206 m,
40ca29a1 2207 SD_BUS_ERROR_UNKNOWN_OBJECT,
992c052c 2208 "Unknown object '%s'.", m->path);
29ddb38f
LP
2209 if (r < 0)
2210 return r;
2211 }
e3017af9 2212
992c052c 2213 return 1;
0a72c2bd 2214
992c052c
LP
2215null_message:
2216 if (r >= 0 && ret)
2217 *ret = NULL;
0a72c2bd 2218
992c052c 2219 return r;
29ddb38f 2220}
0a72c2bd 2221
718db961
LP
2222static int process_closing(sd_bus *bus, sd_bus_message **ret) {
2223 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2224 struct reply_callback *c;
2225 int r;
2226
2227 assert(bus);
2228 assert(bus->state == BUS_CLOSING);
2229
2230 c = hashmap_first(bus->reply_callbacks);
2231 if (c) {
ebcf1f97
LP
2232 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
2233
718db961
LP
2234 /* First, fail all outstanding method calls */
2235 r = bus_message_new_synthetic_error(
2236 bus,
693eb9a2 2237 c->cookie,
14c24659 2238 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
718db961
LP
2239 &m);
2240 if (r < 0)
2241 return r;
2242
7adc46fc 2243 r = bus_seal_synthetic_message(bus, m);
718db961
LP
2244 if (r < 0)
2245 return r;
2246
2247 if (c->timeout != 0)
2248 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
2249
693eb9a2 2250 hashmap_remove(bus->reply_callbacks, &c->cookie);
718db961
LP
2251
2252 bus->current = m;
2253 bus->iteration_counter++;
2254
ebcf1f97
LP
2255 r = c->callback(bus, m, c->userdata, &error_buffer);
2256 r = bus_maybe_reply_error(m, r, &error_buffer);
718db961
LP
2257 free(c);
2258
718db961
LP
2259 goto finish;
2260 }
2261
2262 /* Then, synthesize a Disconnected message */
2263 r = sd_bus_message_new_signal(
2264 bus,
2265 "/org/freedesktop/DBus/Local",
2266 "org.freedesktop.DBus.Local",
2267 "Disconnected",
2268 &m);
2269 if (r < 0)
2270 return r;
2271
34a2c9e8
LP
2272 m->sender = "org.freedesktop.DBus.Local";
2273
7adc46fc 2274 r = bus_seal_synthetic_message(bus, m);
718db961
LP
2275 if (r < 0)
2276 return r;
2277
2278 sd_bus_close(bus);
2279
2280 bus->current = m;
2281 bus->iteration_counter++;
2282
2283 r = process_filter(bus, m);
2284 if (r != 0)
2285 goto finish;
2286
2287 r = process_match(bus, m);
2288 if (r != 0)
2289 goto finish;
2290
2291 if (ret) {
2292 *ret = m;
2293 m = NULL;
2294 }
2295
2296 r = 1;
2297
2298finish:
2299 bus->current = NULL;
2300 return r;
2301}
2302
d9f644e2 2303_public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
8ce2afd6 2304 BUS_DONT_DESTROY(bus);
29ddb38f 2305 int r;
0a72c2bd 2306
992c052c
LP
2307 /* Returns 0 when we didn't do anything. This should cause the
2308 * caller to invoke sd_bus_wait() before returning the next
2309 * time. Returns > 0 when we did something, which possibly
2310 * means *ret is filled in with an unprocessed message. */
0a72c2bd 2311
d6888822
LP
2312 assert_return(bus, -EINVAL);
2313 assert_return(!bus_pid_changed(bus), -ECHILD);
0a72c2bd 2314
992c052c 2315 /* We don't allow recursively invoking sd_bus_process(). */
718db961 2316 assert_return(!bus->current, -EBUSY);
0a72c2bd 2317
992c052c 2318 switch (bus->state) {
0a72c2bd 2319
992c052c 2320 case BUS_UNSET:
992c052c 2321 return -ENOTCONN;
0a72c2bd 2322
6d6f4904
LP
2323 case BUS_CLOSED:
2324 return -ECONNRESET;
2325
992c052c
LP
2326 case BUS_OPENING:
2327 r = bus_socket_process_opening(bus);
32f46480 2328 if (r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
718db961
LP
2329 bus_enter_closing(bus);
2330 r = 1;
2331 } else if (r < 0)
29ddb38f 2332 return r;
992c052c
LP
2333 if (ret)
2334 *ret = NULL;
a652755d
LP
2335 return r;
2336
992c052c 2337 case BUS_AUTHENTICATING:
992c052c 2338 r = bus_socket_process_authenticating(bus);
32f46480 2339 if (r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
718db961
LP
2340 bus_enter_closing(bus);
2341 r = 1;
2342 } else if (r < 0)
29ddb38f 2343 return r;
718db961 2344
992c052c
LP
2345 if (ret)
2346 *ret = NULL;
718db961 2347
992c052c 2348 return r;
a652755d 2349
992c052c
LP
2350 case BUS_RUNNING:
2351 case BUS_HELLO:
992c052c 2352 r = process_running(bus, ret);
32f46480 2353 if (r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
718db961
LP
2354 bus_enter_closing(bus);
2355 r = 1;
2356
2357 if (ret)
2358 *ret = NULL;
2359 }
43a43f50 2360
43a43f50 2361 return r;
718db961
LP
2362
2363 case BUS_CLOSING:
2364 return process_closing(bus, ret);
992c052c 2365 }
43a43f50 2366
992c052c 2367 assert_not_reached("Unknown state");
e3017af9
LP
2368}
2369
992c052c
LP
2370static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
2371 struct pollfd p[2] = {};
2372 int r, e, n;
2373 struct timespec ts;
8efd6381 2374 usec_t m = (usec_t) -1;
adcdb374
LP
2375
2376 assert(bus);
718db961
LP
2377
2378 if (bus->state == BUS_CLOSING)
2379 return 1;
2380
d6888822 2381 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
adcdb374 2382
992c052c
LP
2383 e = sd_bus_get_events(bus);
2384 if (e < 0)
2385 return e;
adcdb374 2386
992c052c 2387 if (need_more)
8efd6381
LP
2388 /* The caller really needs some more data, he doesn't
2389 * care about what's already read, or any timeouts
2390 * except its own.*/
992c052c 2391 e |= POLLIN;
992c052c 2392 else {
8efd6381
LP
2393 usec_t until;
2394 /* The caller wants to process if there's something to
2395 * process, but doesn't care otherwise */
2396
2397 r = sd_bus_get_timeout(bus, &until);
2398 if (r < 0)
2399 return r;
2400 if (r > 0) {
2401 usec_t nw;
2402 nw = now(CLOCK_MONOTONIC);
2403 m = until > nw ? until - nw : 0;
2404 }
992c052c 2405 }
adcdb374 2406
992c052c
LP
2407 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
2408 m = timeout_usec;
adcdb374 2409
992c052c
LP
2410 p[0].fd = bus->input_fd;
2411 if (bus->output_fd == bus->input_fd) {
2412 p[0].events = e;
2413 n = 1;
2414 } else {
2415 p[0].events = e & POLLIN;
2416 p[1].fd = bus->output_fd;
2417 p[1].events = e & POLLOUT;
2418 n = 2;
adcdb374
LP
2419 }
2420
992c052c 2421 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
adcdb374 2422 if (r < 0)
992c052c 2423 return -errno;
adcdb374 2424
992c052c 2425 return r > 0 ? 1 : 0;
adcdb374
LP
2426}
2427
d9f644e2 2428_public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
9db76355 2429
d6888822 2430 assert_return(bus, -EINVAL);
d6888822 2431 assert_return(!bus_pid_changed(bus), -ECHILD);
9db76355 2432
718db961
LP
2433 if (bus->state == BUS_CLOSING)
2434 return 0;
2435
2436 assert_return(BUS_IS_OPEN(bus->state) , -ENOTCONN);
2437
992c052c
LP
2438 if (bus->rqueue_size > 0)
2439 return 0;
9db76355 2440
992c052c
LP
2441 return bus_poll(bus, false, timeout_usec);
2442}
9db76355 2443
d9f644e2 2444_public_ int sd_bus_flush(sd_bus *bus) {
992c052c 2445 int r;
9db76355 2446
d6888822 2447 assert_return(bus, -EINVAL);
d6888822 2448 assert_return(!bus_pid_changed(bus), -ECHILD);
9db76355 2449
718db961
LP
2450 if (bus->state == BUS_CLOSING)
2451 return 0;
2452
2453 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2454
992c052c
LP
2455 r = bus_ensure_running(bus);
2456 if (r < 0)
2457 return r;
9db76355 2458
992c052c
LP
2459 if (bus->wqueue_size <= 0)
2460 return 0;
9db76355 2461
992c052c
LP
2462 for (;;) {
2463 r = dispatch_wqueue(bus);
32f46480
LP
2464 if (r < 0) {
2465 if (r == -EPIPE || r == -ENOTCONN || r == -ESHUTDOWN)
2466 bus_enter_closing(bus);
2467
9db76355 2468 return r;
32f46480 2469 }
9db76355 2470
992c052c
LP
2471 if (bus->wqueue_size <= 0)
2472 return 0;
9db76355 2473
992c052c 2474 r = bus_poll(bus, false, (uint64_t) -1);
9db76355
LP
2475 if (r < 0)
2476 return r;
9db76355 2477 }
9db76355
LP
2478}
2479
d9f644e2
ZJS
2480_public_ int sd_bus_add_filter(sd_bus *bus,
2481 sd_bus_message_handler_t callback,
2482 void *userdata) {
2483
992c052c 2484 struct filter_callback *f;
de1c301e 2485
d6888822
LP
2486 assert_return(bus, -EINVAL);
2487 assert_return(callback, -EINVAL);
2488 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 2489
992c052c
LP
2490 f = new0(struct filter_callback, 1);
2491 if (!f)
29ddb38f 2492 return -ENOMEM;
992c052c
LP
2493 f->callback = callback;
2494 f->userdata = userdata;
29ddb38f 2495
992c052c 2496 bus->filter_callbacks_modified = true;
71fda00f 2497 LIST_PREPEND(callbacks, bus->filter_callbacks, f);
de1c301e
LP
2498 return 0;
2499}
a652755d 2500
d9f644e2
ZJS
2501_public_ int sd_bus_remove_filter(sd_bus *bus,
2502 sd_bus_message_handler_t callback,
2503 void *userdata) {
2504
992c052c 2505 struct filter_callback *f;
a652755d 2506
d6888822
LP
2507 assert_return(bus, -EINVAL);
2508 assert_return(callback, -EINVAL);
2509 assert_return(!bus_pid_changed(bus), -ECHILD);
a652755d 2510
992c052c
LP
2511 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
2512 if (f->callback == callback && f->userdata == userdata) {
2513 bus->filter_callbacks_modified = true;
71fda00f 2514 LIST_REMOVE(callbacks, bus->filter_callbacks, f);
992c052c
LP
2515 free(f);
2516 return 1;
29ddb38f
LP
2517 }
2518 }
2519
992c052c 2520 return 0;
a652755d 2521}
392d5b37 2522
d9f644e2
ZJS
2523_public_ int sd_bus_add_match(sd_bus *bus,
2524 const char *match,
2525 sd_bus_message_handler_t callback,
2526 void *userdata) {
2527
992c052c
LP
2528 struct bus_match_component *components = NULL;
2529 unsigned n_components = 0;
2530 uint64_t cookie = 0;
2531 int r = 0;
392d5b37 2532
d6888822
LP
2533 assert_return(bus, -EINVAL);
2534 assert_return(match, -EINVAL);
2535 assert_return(!bus_pid_changed(bus), -ECHILD);
392d5b37 2536
992c052c
LP
2537 r = bus_match_parse(match, &components, &n_components);
2538 if (r < 0)
2539 goto finish;
29ddb38f 2540
992c052c
LP
2541 if (bus->bus_client) {
2542 cookie = ++bus->match_cookie;
29ddb38f 2543
992c052c
LP
2544 r = bus_add_match_internal(bus, match, components, n_components, cookie);
2545 if (r < 0)
2546 goto finish;
392d5b37
LP
2547 }
2548
992c052c
LP
2549 bus->match_callbacks_modified = true;
2550 r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
29ddb38f 2551 if (r < 0) {
992c052c
LP
2552 if (bus->bus_client)
2553 bus_remove_match_internal(bus, match, cookie);
29ddb38f 2554 }
917b5dc7 2555
992c052c
LP
2556finish:
2557 bus_match_parse_free(components, n_components);
2558 return r;
917b5dc7
LP
2559}
2560
d9f644e2
ZJS
2561_public_ int sd_bus_remove_match(sd_bus *bus,
2562 const char *match,
2563 sd_bus_message_handler_t callback,
2564 void *userdata) {
2565
992c052c
LP
2566 struct bus_match_component *components = NULL;
2567 unsigned n_components = 0;
2568 int r = 0, q = 0;
2569 uint64_t cookie = 0;
917b5dc7 2570
d6888822
LP
2571 assert_return(bus, -EINVAL);
2572 assert_return(match, -EINVAL);
2573 assert_return(!bus_pid_changed(bus), -ECHILD);
917b5dc7 2574
992c052c 2575 r = bus_match_parse(match, &components, &n_components);
29ddb38f
LP
2576 if (r < 0)
2577 return r;
f10dda3b 2578
992c052c
LP
2579 bus->match_callbacks_modified = true;
2580 r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie);
f10dda3b 2581
992c052c
LP
2582 if (bus->bus_client)
2583 q = bus_remove_match_internal(bus, match, cookie);
f10dda3b 2584
992c052c 2585 bus_match_parse_free(components, n_components);
f10dda3b 2586
992c052c 2587 return r < 0 ? r : q;
f10dda3b
LP
2588}
2589
992c052c
LP
2590bool bus_pid_changed(sd_bus *bus) {
2591 assert(bus);
f10dda3b 2592
992c052c
LP
2593 /* We don't support people creating a bus connection and
2594 * keeping it around over a fork(). Let's complain. */
d5a2b9a6 2595
992c052c 2596 return bus->original_pid != getpid();
d5a2b9a6 2597}
40ca29a1
LP
2598
2599static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
0927756b 2600 sd_bus *bus = userdata;
40ca29a1
LP
2601 int r;
2602
2603 assert(bus);
2604
2605 r = sd_bus_process(bus, NULL);
2606 if (r < 0)
2607 return r;
2608
2609 return 1;
2610}
2611
2612static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
0927756b 2613 sd_bus *bus = userdata;
40ca29a1
LP
2614 int r;
2615
2616 assert(bus);
2617
2618 r = sd_bus_process(bus, NULL);
2619 if (r < 0)
2620 return r;
2621
2622 return 1;
2623}
2624
2625static int prepare_callback(sd_event_source *s, void *userdata) {
2626 sd_bus *bus = userdata;
2627 int r, e;
2628 usec_t until;
2629
2630 assert(s);
2631 assert(bus);
2632
2633 e = sd_bus_get_events(bus);
2634 if (e < 0)
2635 return e;
2636
2637 if (bus->output_fd != bus->input_fd) {
2638
2639 r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN);
2640 if (r < 0)
2641 return r;
2642
2643 r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT);
2644 if (r < 0)
2645 return r;
2646 } else {
2647 r = sd_event_source_set_io_events(bus->input_io_event_source, e);
2648 if (r < 0)
2649 return r;
2650 }
2651
2652 r = sd_bus_get_timeout(bus, &until);
2653 if (r < 0)
2654 return r;
2655 if (r > 0) {
2656 int j;
2657
2658 j = sd_event_source_set_time(bus->time_event_source, until);
2659 if (j < 0)
2660 return j;
2661 }
2662
2663 r = sd_event_source_set_enabled(bus->time_event_source, r > 0);
2664 if (r < 0)
2665 return r;
2666
2667 return 1;
2668}
2669
abc5fe72
LP
2670static int quit_callback(sd_event_source *event, void *userdata) {
2671 sd_bus *bus = userdata;
2672
2673 assert(event);
2674
2675 sd_bus_flush(bus);
2676
2677 return 1;
2678}
2679
1e05d493
LP
2680static int attach_io_events(sd_bus *bus) {
2681 int r;
2682
2683 assert(bus);
2684
2685 if (bus->input_fd < 0)
2686 return 0;
2687
2688 if (!bus->event)
2689 return 0;
2690
2691 if (!bus->input_io_event_source) {
2692 r = sd_event_add_io(bus->event, bus->input_fd, 0, io_callback, bus, &bus->input_io_event_source);
2693 if (r < 0)
2694 return r;
2695
2696 r = sd_event_source_set_prepare(bus->input_io_event_source, prepare_callback);
2697 if (r < 0)
2698 return r;
2699
2700 r = sd_event_source_set_priority(bus->input_io_event_source, bus->event_priority);
2701 } else
2702 r = sd_event_source_set_io_fd(bus->input_io_event_source, bus->input_fd);
2703
2704 if (r < 0)
2705 return r;
2706
2707 if (bus->output_fd != bus->input_fd) {
2708 assert(bus->output_fd >= 0);
2709
2710 if (!bus->output_io_event_source) {
2711 r = sd_event_add_io(bus->event, bus->output_fd, 0, io_callback, bus, &bus->output_io_event_source);
2712 if (r < 0)
2713 return r;
2714
2715 r = sd_event_source_set_priority(bus->output_io_event_source, bus->event_priority);
2716 } else
2717 r = sd_event_source_set_io_fd(bus->output_io_event_source, bus->output_fd);
2718
2719 if (r < 0)
2720 return r;
2721 }
2722
2723 return 0;
2724}
2725
2726static void detach_io_events(sd_bus *bus) {
2727 assert(bus);
2728
2729 if (bus->input_io_event_source) {
2730 sd_event_source_set_enabled(bus->input_io_event_source, SD_EVENT_OFF);
2731 bus->input_io_event_source = sd_event_source_unref(bus->input_io_event_source);
2732 }
2733
2734 if (bus->output_io_event_source) {
2735 sd_event_source_set_enabled(bus->output_io_event_source, SD_EVENT_OFF);
2736 bus->output_io_event_source = sd_event_source_unref(bus->output_io_event_source);
2737 }
2738}
2739
d9f644e2 2740_public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) {
40ca29a1
LP
2741 int r;
2742
2743 assert_return(bus, -EINVAL);
40ca29a1
LP
2744 assert_return(!bus->event, -EBUSY);
2745
2746 assert(!bus->input_io_event_source);
2747 assert(!bus->output_io_event_source);
2748 assert(!bus->time_event_source);
2749
76b54375
LP
2750 if (event)
2751 bus->event = sd_event_ref(event);
2752 else {
2753 r = sd_event_default(&bus->event);
2754 if (r < 0)
2755 return r;
2756 }
40ca29a1 2757
1e05d493 2758 bus->event_priority = priority;
40ca29a1 2759
76b54375 2760 r = sd_event_add_monotonic(bus->event, 0, 0, time_callback, bus, &bus->time_event_source);
40ca29a1
LP
2761 if (r < 0)
2762 goto fail;
2763
2764 r = sd_event_source_set_priority(bus->time_event_source, priority);
2765 if (r < 0)
2766 goto fail;
2767
6203e07a 2768 r = sd_event_add_exit(bus->event, quit_callback, bus, &bus->quit_event_source);
abc5fe72
LP
2769 if (r < 0)
2770 goto fail;
2771
1e05d493
LP
2772 r = attach_io_events(bus);
2773 if (r < 0)
2774 goto fail;
2775
40ca29a1
LP
2776 return 0;
2777
2778fail:
2779 sd_bus_detach_event(bus);
2780 return r;
2781}
2782
d9f644e2 2783_public_ int sd_bus_detach_event(sd_bus *bus) {
40ca29a1 2784 assert_return(bus, -EINVAL);
a82cafb9
LP
2785
2786 if (!bus->event)
2787 return 0;
40ca29a1 2788
1e05d493 2789 detach_io_events(bus);
40ca29a1 2790
86befb40
LP
2791 if (bus->time_event_source) {
2792 sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF);
40ca29a1 2793 bus->time_event_source = sd_event_source_unref(bus->time_event_source);
86befb40 2794 }
40ca29a1 2795
86befb40
LP
2796 if (bus->quit_event_source) {
2797 sd_event_source_set_enabled(bus->quit_event_source, SD_EVENT_OFF);
abc5fe72 2798 bus->quit_event_source = sd_event_source_unref(bus->quit_event_source);
86befb40 2799 }
abc5fe72 2800
40ca29a1
LP
2801 if (bus->event)
2802 bus->event = sd_event_unref(bus->event);
2803
a82cafb9 2804 return 1;
40ca29a1 2805}
affff0b6 2806
2be44176
LP
2807_public_ sd_event* sd_bus_get_event(sd_bus *bus) {
2808 assert_return(bus, NULL);
2809
2810 return bus->event;
2811}
2812
76b54375 2813_public_ sd_bus_message* sd_bus_get_current(sd_bus *bus) {
affff0b6
LP
2814 assert_return(bus, NULL);
2815
2816 return bus->current;
2817}
76b54375
LP
2818
2819static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) {
2820 sd_bus *b = NULL;
2821 int r;
2822
2823 assert(bus_open);
2824 assert(default_bus);
2825
2826 if (!ret)
2827 return !!*default_bus;
2828
2829 if (*default_bus) {
2830 *ret = sd_bus_ref(*default_bus);
2831 return 0;
2832 }
2833
2834 r = bus_open(&b);
2835 if (r < 0)
2836 return r;
2837
2838 b->default_bus_ptr = default_bus;
2839 b->tid = gettid();
2840 *default_bus = b;
2841
2842 *ret = b;
2843 return 1;
2844}
2845
2846_public_ int sd_bus_default_system(sd_bus **ret) {
ec202eae 2847 static thread_local sd_bus *default_system_bus = NULL;
76b54375
LP
2848
2849 return bus_default(sd_bus_open_system, &default_system_bus, ret);
2850}
2851
2852_public_ int sd_bus_default_user(sd_bus **ret) {
ec202eae 2853 static thread_local sd_bus *default_user_bus = NULL;
76b54375
LP
2854
2855 return bus_default(sd_bus_open_user, &default_user_bus, ret);
2856}
2857
2858_public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) {
2859 assert_return(b, -EINVAL);
2860 assert_return(tid, -EINVAL);
2861 assert_return(!bus_pid_changed(b), -ECHILD);
2862
2863 if (b->tid != 0) {
2864 *tid = b->tid;
2865 return 0;
2866 }
2867
2868 if (b->event)
2869 return sd_event_get_tid(b->event, tid);
2870
2871 return -ENXIO;
2872}
28383ba1
LP
2873
2874_public_ char *sd_bus_label_escape(const char *s) {
2875 char *r, *t;
2876 const char *f;
2877
2878 assert_return(s, NULL);
2879
2880 /* Escapes all chars that D-Bus' object path cannot deal
2881 * with. Can be reversed with bus_path_unescape(). We special
2882 * case the empty string. */
2883
2884 if (*s == 0)
2885 return strdup("_");
2886
2887 r = new(char, strlen(s)*3 + 1);
2888 if (!r)
2889 return NULL;
2890
2891 for (f = s, t = r; *f; f++) {
2892
2893 /* Escape everything that is not a-zA-Z0-9. We also
2894 * escape 0-9 if it's the first character */
2895
2896 if (!(*f >= 'A' && *f <= 'Z') &&
2897 !(*f >= 'a' && *f <= 'z') &&
2898 !(f > s && *f >= '0' && *f <= '9')) {
2899 *(t++) = '_';
2900 *(t++) = hexchar(*f >> 4);
2901 *(t++) = hexchar(*f);
2902 } else
2903 *(t++) = *f;
2904 }
2905
2906 *t = 0;
2907
2908 return r;
2909}
2910
2911_public_ char *sd_bus_label_unescape(const char *f) {
2912 char *r, *t;
2913
2914 assert_return(f, NULL);
2915
2916 /* Special case for the empty string */
2917 if (streq(f, "_"))
2918 return strdup("");
2919
2920 r = new(char, strlen(f) + 1);
2921 if (!r)
2922 return NULL;
2923
2924 for (t = r; *f; f++) {
2925
2926 if (*f == '_') {
2927 int a, b;
2928
2929 if ((a = unhexchar(f[1])) < 0 ||
2930 (b = unhexchar(f[2])) < 0) {
2931 /* Invalid escape code, let's take it literal then */
2932 *(t++) = '_';
2933 } else {
2934 *(t++) = (char) ((a << 4) | b);
2935 f += 2;
2936 }
2937 } else
2938 *(t++) = *f;
2939 }
2940
2941 *t = 0;
2942
2943 return r;
2944}
5b12334d
LP
2945
2946_public_ int sd_bus_get_peer_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
2947 sd_bus_creds *c;
2948 pid_t pid = 0;
2949 int r;
2950
2951 assert_return(bus, -EINVAL);
95c4fe82 2952 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
5b12334d
LP
2953 assert_return(ret, -EINVAL);
2954 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2955 assert_return(!bus_pid_changed(bus), -ECHILD);
2956 assert_return(!bus->is_kernel, -ENOTSUP);
2957
2958 if (!bus->ucred_valid && !isempty(bus->label))
2959 return -ENODATA;
2960
2961 c = bus_creds_new();
2962 if (!c)
2963 return -ENOMEM;
2964
2965 if (bus->ucred_valid) {
2966 pid = c->pid = bus->ucred.pid;
2967 c->uid = bus->ucred.uid;
2968 c->gid = bus->ucred.gid;
2969
3310dfd5 2970 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
5b12334d
LP
2971 }
2972
2973 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
2974 c->label = strdup(bus->label);
2975 if (!c->label) {
2976 sd_bus_creds_unref(c);
2977 return -ENOMEM;
2978 }
2979
3310dfd5 2980 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
5b12334d
LP
2981 }
2982
2983 r = bus_creds_add_more(c, mask, pid, 0);
2984 if (r < 0)
2985 return r;
2986
2987 *ret = c;
2988 return 0;
2989}
ae095f86
LP
2990
2991_public_ int sd_bus_try_close(sd_bus *bus) {
2992 int r;
2993
2994 assert_return(bus, -EINVAL);
2995 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2996 assert_return(!bus_pid_changed(bus), -ECHILD);
2997 assert_return(bus->is_kernel, -ENOTSUP);
2998
bd746b8b
LP
2999 if (bus->rqueue_size > 0)
3000 return -EBUSY;
3001
14f862a5
LP
3002 if (bus->wqueue_size > 0)
3003 return -EBUSY;
3004
ae095f86
LP
3005 r = bus_kernel_try_close(bus);
3006 if (r < 0)
3007 return r;
3008
3009 sd_bus_close(bus);
3010 return 0;
3011}