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