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