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