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