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