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