]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-bus.c
bus: implement 'unixexec:' protocol
[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>
29
30#include "util.h"
31#include "macro.h"
2571ead1 32#include "missing.h"
2fd9ae2e 33#include "strv.h"
de1c301e
LP
34
35#include "sd-bus.h"
36#include "bus-internal.h"
37#include "bus-message.h"
38#include "bus-type.h"
39
e3017af9
LP
40static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
41
de1c301e
LP
42static void bus_free(sd_bus *b) {
43 struct filter_callback *f;
a652755d 44 struct object_callback *c;
89ffcd2a 45 unsigned i;
de1c301e
LP
46
47 assert(b);
48
49 if (b->fd >= 0)
50 close_nointr_nofail(b->fd);
51
52 free(b->rbuffer);
89ffcd2a
LP
53 free(b->unique_name);
54 free(b->auth_uid);
55 free(b->address);
56
2fd9ae2e
LP
57 free(b->exec_path);
58 strv_free(b->exec_argv);
59
2c93b4ef
LP
60 close_many(b->fds, b->n_fds);
61 free(b->fds);
62
89ffcd2a
LP
63 for (i = 0; i < b->rqueue_size; i++)
64 sd_bus_message_unref(b->rqueue[i]);
de1c301e 65 free(b->rqueue);
89ffcd2a
LP
66
67 for (i = 0; i < b->wqueue_size; i++)
68 sd_bus_message_unref(b->wqueue[i]);
de1c301e 69 free(b->wqueue);
de1c301e
LP
70
71 hashmap_free_free(b->reply_callbacks);
e3017af9 72 prioq_free(b->reply_callbacks_prioq);
de1c301e
LP
73
74 while ((f = b->filter_callbacks)) {
75 LIST_REMOVE(struct filter_callback, callbacks, b->filter_callbacks, f);
76 free(f);
77 }
78
a652755d
LP
79 while ((c = hashmap_steal_first(b->object_callbacks))) {
80 free(c->path);
81 free(c);
82 }
83
84 hashmap_free(b->object_callbacks);
85
de1c301e
LP
86 free(b);
87}
88
021a1e78 89int sd_bus_new(sd_bus **ret) {
de1c301e
LP
90 sd_bus *r;
91
021a1e78
LP
92 if (!ret)
93 return -EINVAL;
94
de1c301e
LP
95 r = new0(sd_bus, 1);
96 if (!r)
021a1e78 97 return -ENOMEM;
de1c301e
LP
98
99 r->n_ref = 1;
100 r->fd = -1;
101 r->message_version = 1;
021a1e78 102 r->negotiate_fds = true;
de1c301e
LP
103
104 /* We guarantee that wqueue always has space for at least one
105 * entry */
106 r->wqueue = new(sd_bus_message*, 1);
107 if (!r->wqueue) {
108 free(r);
021a1e78 109 return -ENOMEM;
de1c301e
LP
110 }
111
021a1e78
LP
112 *ret = r;
113 return 0;
114}
115
116int sd_bus_set_address(sd_bus *bus, const char *address) {
117 char *a;
118
119 if (!bus)
120 return -EINVAL;
121 if (bus->state != BUS_UNSET)
122 return -EPERM;
123 if (!address)
124 return -EINVAL;
125
126 a = strdup(address);
127 if (!a)
128 return -ENOMEM;
129
130 free(bus->address);
131 bus->address = a;
132
133 return 0;
134}
135
136int sd_bus_set_fd(sd_bus *bus, int fd) {
137 if (!bus)
138 return -EINVAL;
139 if (bus->state != BUS_UNSET)
140 return -EPERM;
141 if (fd < 0)
142 return -EINVAL;
143
144 bus->fd = fd;
145 return 0;
146}
147
2fd9ae2e
LP
148int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
149 char *p, **a;
150
151 if (!bus)
152 return -EINVAL;
153 if (bus->state != BUS_UNSET)
154 return -EPERM;
155 if (!path)
156 return -EINVAL;
157 if (strv_isempty(argv))
158 return -EINVAL;
159
160 p = strdup(path);
161 if (!p)
162 return -ENOMEM;
163
164 a = strv_copy(argv);
165 if (!a) {
166 free(p);
167 return -ENOMEM;
168 }
169
170 free(bus->exec_path);
171 strv_free(bus->exec_argv);
172
173 bus->exec_path = p;
174 bus->exec_argv = a;
175
176 return 0;
177}
178
021a1e78
LP
179int sd_bus_set_hello(sd_bus *bus, int b) {
180 if (!bus)
181 return -EINVAL;
182 if (bus->state != BUS_UNSET)
183 return -EPERM;
184
185 bus->send_hello = !!b;
186 return 0;
187}
188
189int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
190 if (!bus)
191 return -EINVAL;
192 if (bus->state != BUS_UNSET)
193 return -EPERM;
194
195 bus->negotiate_fds = !!b;
196 return 0;
197}
de1c301e 198
e3017af9 199static int hello_callback(sd_bus *bus, int error, sd_bus_message *reply, void *userdata) {
de1c301e
LP
200 const char *s;
201 int r;
202
203 assert(bus);
021a1e78 204 assert(bus->state == BUS_HELLO);
e3017af9
LP
205
206 if (error != 0)
207 return -error;
208
de1c301e
LP
209 assert(reply);
210
de1c301e
LP
211 r = sd_bus_message_read(reply, "s", &s);
212 if (r < 0)
213 return r;
214
dafb7591
LP
215 if (!service_name_is_valid(s) || s[0] != ':')
216 return -EBADMSG;
217
de1c301e
LP
218 bus->unique_name = strdup(s);
219 if (!bus->unique_name)
220 return -ENOMEM;
221
dafb7591
LP
222 bus->state = BUS_RUNNING;
223
de1c301e
LP
224 return 1;
225}
226
227static int bus_send_hello(sd_bus *bus) {
228 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
229 int r;
230
231 assert(bus);
232
021a1e78
LP
233 if (!bus->send_hello)
234 return 0;
235
de1c301e
LP
236 r = sd_bus_message_new_method_call(
237 bus,
238 "org.freedesktop.DBus",
239 "/",
240 "org.freedesktop.DBus",
241 "Hello",
242 &m);
243 if (r < 0)
244 return r;
245
e3017af9 246 r = sd_bus_send_with_reply(bus, m, hello_callback, NULL, 0, NULL);
de1c301e
LP
247 if (r < 0)
248 return r;
249
89ffcd2a 250 return r;
de1c301e
LP
251}
252
253static int bus_start_running(sd_bus *bus) {
de1c301e
LP
254 assert(bus);
255
021a1e78 256 if (bus->send_hello) {
de1c301e 257 bus->state = BUS_HELLO;
e3017af9 258 return 1;
de1c301e
LP
259 }
260
261 bus->state = BUS_RUNNING;
e3017af9 262 return 1;
de1c301e
LP
263}
264
265static int parse_address_key(const char **p, const char *key, char **value) {
266 size_t l, n = 0;
267 const char *a;
268 char *r = NULL;
269
270 assert(p);
271 assert(*p);
de1c301e
LP
272 assert(value);
273
2fd9ae2e
LP
274 if (key) {
275 l = strlen(key);
276 if (strncmp(*p, key, l) != 0)
277 return 0;
de1c301e 278
2fd9ae2e
LP
279 if ((*p)[l] != '=')
280 return 0;
de1c301e 281
2fd9ae2e
LP
282 if (*value)
283 return -EINVAL;
de1c301e 284
2fd9ae2e
LP
285 a = *p + l + 1;
286 } else
287 a = *p;
288
289 while (*a != ';' && *a != ',' && *a != 0) {
de1c301e
LP
290 char c, *t;
291
292 if (*a == '%') {
293 int x, y;
294
295 x = unhexchar(a[1]);
296 if (x < 0) {
297 free(r);
298 return x;
299 }
300
301 y = unhexchar(a[2]);
302 if (y < 0) {
303 free(r);
304 return y;
305 }
306
de1c301e 307 c = (char) ((x << 4) | y);
89ffcd2a
LP
308 a += 3;
309 } else {
de1c301e 310 c = *a;
89ffcd2a
LP
311 a++;
312 }
de1c301e 313
89ffcd2a 314 t = realloc(r, n + 2);
de1c301e
LP
315 if (!t) {
316 free(r);
317 return -ENOMEM;
318 }
319
320 r = t;
321 r[n++] = c;
322 }
323
89ffcd2a
LP
324 if (!r) {
325 r = strdup("");
326 if (!r)
327 return -ENOMEM;
328 } else
329 r[n] = 0;
330
331 if (*a == ',')
332 a++;
333
de1c301e 334 *p = a;
2fd9ae2e
LP
335
336 free(*value);
de1c301e 337 *value = r;
2fd9ae2e 338
de1c301e
LP
339 return 1;
340}
341
342static void skip_address_key(const char **p) {
343 assert(p);
344 assert(*p);
345
89ffcd2a
LP
346 *p += strcspn(*p, ",");
347
348 if (**p == ',')
349 (*p) ++;
de1c301e
LP
350}
351
2fd9ae2e
LP
352static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
353 _cleanup_free_ char *path = NULL, *abstract = NULL;
354 size_t l;
de1c301e
LP
355 int r;
356
357 assert(b);
2fd9ae2e
LP
358 assert(p);
359 assert(*p);
360 assert(guid);
de1c301e 361
2fd9ae2e
LP
362 while (**p != 0 && **p != ';') {
363 r = parse_address_key(p, "guid", guid);
364 if (r < 0)
365 return r;
366 else if (r > 0)
367 continue;
de1c301e 368
2fd9ae2e
LP
369 r = parse_address_key(p, "path", &path);
370 if (r < 0)
371 return r;
372 else if (r > 0)
373 continue;
de1c301e 374
2fd9ae2e
LP
375 r = parse_address_key(p, "abstract", &abstract);
376 if (r < 0)
377 return r;
378 else if (r > 0)
379 continue;
de1c301e 380
2fd9ae2e
LP
381 skip_address_key(p);
382 }
de1c301e 383
2fd9ae2e
LP
384 if (!path && !abstract)
385 return -EINVAL;
de1c301e 386
2fd9ae2e
LP
387 if (path && abstract)
388 return -EINVAL;
389
390 if (path) {
391 l = strlen(path);
392 if (l > sizeof(b->sockaddr.un.sun_path))
393 return -E2BIG;
de1c301e 394
2fd9ae2e
LP
395 b->sockaddr.un.sun_family = AF_UNIX;
396 strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
397 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
398 } else if (abstract) {
399 l = strlen(abstract);
400 if (l > sizeof(b->sockaddr.un.sun_path) - 1)
401 return -E2BIG;
402
403 b->sockaddr.un.sun_family = AF_UNIX;
404 b->sockaddr.un.sun_path[0] = 0;
405 strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
406 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
407 }
408
409 return 0;
410}
411
412static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
413 _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
414 struct addrinfo hints, *result;
415 int r;
416
417 assert(b);
418 assert(p);
419 assert(*p);
420 assert(guid);
421
422 while (**p != 0 && **p != ';') {
423 r = parse_address_key(p, "guid", guid);
424 if (r < 0)
425 return r;
426 else if (r > 0)
427 continue;
428
429 r = parse_address_key(p, "host", &host);
430 if (r < 0)
431 return r;
432 else if (r > 0)
433 continue;
434
435 r = parse_address_key(p, "port", &port);
436 if (r < 0)
437 return r;
438 else if (r > 0)
439 continue;
440
441 r = parse_address_key(p, "family", &family);
442 if (r < 0)
443 return r;
444 else if (r > 0)
445 continue;
446
447 skip_address_key(p);
448 }
449
450 if (!host || !port)
451 return -EINVAL;
452
453 zero(hints);
454 hints.ai_socktype = SOCK_STREAM;
455 hints.ai_flags = AI_ADDRCONFIG;
456
457 if (family) {
458 if (streq(family, "ipv4"))
459 hints.ai_family = AF_INET;
460 else if (streq(family, "ipv6"))
461 hints.ai_family = AF_INET6;
462 else
463 return -EINVAL;
464 }
465
466 r = getaddrinfo(host, port, &hints, &result);
467 if (r == EAI_SYSTEM)
468 return -errno;
469 else if (r != 0)
470 return -EADDRNOTAVAIL;
471
472 memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
473 b->sockaddr_size = result->ai_addrlen;
474
475 freeaddrinfo(result);
476
477 return 0;
478}
479
480static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
481 char *path = NULL;
482 unsigned n_argv = 0, j;
483 char **argv = NULL;
484 int r;
485
486 assert(b);
487 assert(p);
488 assert(*p);
489 assert(guid);
490
491 while (**p != 0 && **p != ';') {
492 r = parse_address_key(p, "guid", guid);
493 if (r < 0)
494 goto fail;
495 else if (r > 0)
496 continue;
497
498 r = parse_address_key(p, "path", &path);
499 if (r < 0)
500 goto fail;
501 else if (r > 0)
502 continue;
503
504 if (startswith(*p, "argv")) {
505 unsigned ul;
506
507 errno = 0;
508 ul = strtoul(*p + 4, (char**) p, 10);
509 if (errno != 0 || **p != '=' || ul > 256) {
510 r = -EINVAL;
511 goto fail;
512 }
513
514 (*p) ++;
515
516 if (ul >= n_argv) {
517 char **x;
518
519 x = realloc(argv, sizeof(char*) * (ul + 2));
520 if (!x) {
521 r = -ENOMEM;
522 goto fail;
523 }
524
525 memset(x + n_argv, 0, sizeof(char*) * (ul - n_argv + 2));
526
527 argv = x;
528 n_argv = ul + 1;
529 }
530
531 r = parse_address_key(p, NULL, argv + ul);
de1c301e 532 if (r < 0)
2fd9ae2e 533 goto fail;
de1c301e 534
2fd9ae2e 535 continue;
de1c301e
LP
536 }
537
2fd9ae2e
LP
538 skip_address_key(p);
539 }
de1c301e 540
2fd9ae2e
LP
541 if (!path)
542 goto fail;
de1c301e 543
2fd9ae2e
LP
544 /* Make sure there are no holes in the array, with the
545 * exception of argv[0] */
546 for (j = 1; j < n_argv; j++)
547 if (!argv[j]) {
548 r = -EINVAL;
549 goto fail;
550 }
551
552 if (argv && argv[0] == NULL) {
553 argv[0] = strdup(path);
554 if (!argv[0]) {
555 r = -ENOMEM;
556 goto fail;
557 }
558 }
de1c301e 559
2fd9ae2e
LP
560 b->exec_path = path;
561 b->exec_argv = argv;
562 return 0;
de1c301e 563
2fd9ae2e
LP
564fail:
565 for (j = 0; j < n_argv; j++)
566 free(argv[j]);
567
568 free(argv);
569 free(path);
570 return r;
571}
572
573static void bus_reset_parsed_address(sd_bus *b) {
574 assert(b);
575
576 zero(b->sockaddr);
577 b->sockaddr_size = 0;
578 strv_free(b->exec_argv);
579 free(b->exec_path);
580 b->exec_path = NULL;
581 b->exec_argv = NULL;
582 b->peer = SD_ID128_NULL;
583}
584
585static int bus_parse_next_address(sd_bus *b) {
586 _cleanup_free_ char *guid = NULL;
587 const char *a;
588 int r;
589
590 assert(b);
591
592 if (!b->address)
593 return 0;
594 if (b->address[b->address_index] == 0)
595 return 0;
596
597 bus_reset_parsed_address(b);
598
599 a = b->address + b->address_index;
de1c301e 600
2fd9ae2e 601 while (*a != 0) {
de1c301e 602
2fd9ae2e
LP
603 if (*a == ';') {
604 a++;
605 continue;
de1c301e
LP
606 }
607
2fd9ae2e
LP
608 if (startswith(a, "unix:")) {
609 a += 5;
de1c301e 610
2fd9ae2e 611 r = parse_unix_address(b, &a, &guid);
de1c301e
LP
612 if (r < 0)
613 return r;
2fd9ae2e 614 break;
de1c301e 615
2fd9ae2e 616 } else if (startswith(a, "tcp:")) {
de1c301e 617
2fd9ae2e
LP
618 a += 4;
619 r = parse_tcp_address(b, &a, &guid);
de1c301e
LP
620 if (r < 0)
621 return r;
de1c301e 622
2fd9ae2e
LP
623 break;
624
625 } else if (startswith(a, "unixexec:")) {
626
627 a += 9;
628 r = parse_exec_address(b, &a, &guid);
de1c301e
LP
629 if (r < 0)
630 return r;
de1c301e 631
2fd9ae2e 632 break;
de1c301e 633
de1c301e
LP
634 }
635
2fd9ae2e
LP
636 a = strchr(a, ';');
637 if (!a)
638 return 0;
de1c301e
LP
639 }
640
641 if (guid) {
642 r = sd_id128_from_string(guid, &b->peer);
643 if (r < 0)
644 return r;
645 }
646
2fd9ae2e 647 b->address_index = a - b->address;
de1c301e
LP
648 return 1;
649}
650
651static void iovec_advance(struct iovec *iov, unsigned *idx, size_t size) {
652
653 while (size > 0) {
654 struct iovec *i = iov + *idx;
655
656 if (i->iov_len > size) {
657 i->iov_base = (uint8_t*) i->iov_base + size;
658 i->iov_len -= size;
659 return;
660 }
661
662 size -= i->iov_len;
663
664 i->iov_base = NULL;
665 i->iov_len = 0;
666
667 (*idx) ++;
668 }
669}
670
671static int bus_write_auth(sd_bus *b) {
672 struct msghdr mh;
673 ssize_t k;
674
675 assert(b);
676 assert(b->state == BUS_AUTHENTICATING);
677
678 if (b->auth_index >= ELEMENTSOF(b->auth_iovec))
679 return 0;
680
e3017af9
LP
681 if (b->auth_timeout == 0)
682 b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
683
de1c301e
LP
684 zero(mh);
685 mh.msg_iov = b->auth_iovec + b->auth_index;
686 mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
687
688 k = sendmsg(b->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
689 if (k < 0)
690 return errno == EAGAIN ? 0 : -errno;
691
692 iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
693
694 return 1;
695}
696
697static int bus_auth_verify(sd_bus *b) {
021a1e78 698 char *e, *f, *start;
de1c301e
LP
699 sd_id128_t peer;
700 unsigned i;
701 int r;
702
021a1e78
LP
703 /* We expect two response lines: "OK" and possibly
704 * "AGREE_UNIX_FD" */
de1c301e
LP
705
706 e = memmem(b->rbuffer, b->rbuffer_size, "\r\n", 2);
707 if (!e)
708 return 0;
709
021a1e78
LP
710 if (b->negotiate_fds) {
711 f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
712 if (!f)
713 return 0;
714
715 start = f + 2;
716 } else {
717 f = NULL;
718 start = e + 2;
719 }
720
721 /* Nice! We got all the lines we need. First check the OK
722 * line */
de1c301e
LP
723
724 if (e - (char*) b->rbuffer != 3 + 32)
725 return -EPERM;
726
727 if (memcmp(b->rbuffer, "OK ", 3))
728 return -EPERM;
729
730 for (i = 0; i < 32; i += 2) {
731 int x, y;
732
733 x = unhexchar(((char*) b->rbuffer)[3 + i]);
89ffcd2a 734 y = unhexchar(((char*) b->rbuffer)[3 + i + 1]);
de1c301e
LP
735
736 if (x < 0 || y < 0)
737 return -EINVAL;
738
739 peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
740 }
741
742 if (!sd_id128_equal(b->peer, SD_ID128_NULL) &&
743 !sd_id128_equal(b->peer, peer))
744 return -EPERM;
745
746 b->peer = peer;
747
021a1e78
LP
748 /* And possibly check the second line, too */
749
750 if (f)
751 b->can_fds =
752 (f - e == sizeof("\r\nAGREE_UNIX_FD") - 1) &&
753 memcmp(e + 2, "AGREE_UNIX_FD", sizeof("AGREE_UNIX_FD") - 1) == 0;
de1c301e 754
021a1e78
LP
755 b->rbuffer_size -= (start - (char*) b->rbuffer);
756 memmove(b->rbuffer, start, b->rbuffer_size);
89ffcd2a 757
de1c301e
LP
758 r = bus_start_running(b);
759 if (r < 0)
760 return r;
761
762 return 1;
763}
764
765static int bus_read_auth(sd_bus *b) {
766 struct msghdr mh;
767 struct iovec iov;
768 size_t n;
769 ssize_t k;
770 int r;
89ffcd2a 771 void *p;
de1c301e
LP
772
773 assert(b);
774
775 r = bus_auth_verify(b);
776 if (r != 0)
777 return r;
778
779 n = MAX(3 + 32 + 2 + sizeof("AGREE_UNIX_FD") - 1 + 2, b->rbuffer_size * 2);
25220239
LP
780
781 if (n > BUS_AUTH_SIZE_MAX)
782 n = BUS_AUTH_SIZE_MAX;
783
784 if (b->rbuffer_size >= n)
785 return -ENOBUFS;
786
89ffcd2a
LP
787 p = realloc(b->rbuffer, n);
788 if (!p)
789 return -ENOMEM;
790
791 b->rbuffer = p;
de1c301e
LP
792
793 zero(iov);
794 iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size;
795 iov.iov_len = n - b->rbuffer_size;
796
797 zero(mh);
798 mh.msg_iov = &iov;
799 mh.msg_iovlen = 1;
800
801 k = recvmsg(b->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
802 if (k < 0)
803 return errno == EAGAIN ? 0 : -errno;
66f931b4
LP
804 if (k == 0)
805 return -ECONNRESET;
de1c301e
LP
806
807 b->rbuffer_size += k;
808
809 r = bus_auth_verify(b);
810 if (r != 0)
811 return r;
812
e3017af9 813 return 1;
de1c301e
LP
814}
815
2571ead1
LP
816static int bus_setup_fd(sd_bus *b) {
817 int one;
818
819 assert(b);
820
821 /* Enable SO_PASSCRED + SO_PASSEC. We try this on any socket,
822 * just in case. This is actually irrelavant for */
823 one = 1;
824 setsockopt(b->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
825 setsockopt(b->fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
826
827 /* Increase the buffers to a MB */
828 fd_inc_rcvbuf(b->fd, 1024*1024);
829 fd_inc_sndbuf(b->fd, 1024*1024);
830
831 return 0;
832}
833
de1c301e 834static int bus_start_auth(sd_bus *b) {
89ffcd2a 835 static const char auth_prefix[] = "\0AUTH EXTERNAL ";
021a1e78
LP
836 static const char auth_suffix_with_unix_fd[] = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
837 static const char auth_suffix_without_unix_fd[] = "\r\nBEGIN\r\n";
de1c301e
LP
838
839 char text[20 + 1]; /* enough space for a 64bit integer plus NUL */
840 size_t l;
021a1e78 841 const char *auth_suffix;
2fd9ae2e
LP
842 int domain = 0, r;
843 socklen_t sl;
de1c301e
LP
844
845 assert(b);
846
847 b->state = BUS_AUTHENTICATING;
848
2fd9ae2e
LP
849 sl = sizeof(domain);
850 r = getsockopt(b->fd, SOL_SOCKET, SO_DOMAIN, &domain, &sl);
851 if (r < 0)
852 return -errno;
853
854 if (domain != AF_UNIX)
855 b->negotiate_fds = false;
856
de1c301e
LP
857 snprintf(text, sizeof(text), "%llu", (unsigned long long) geteuid());
858 char_array_0(text);
859
860 l = strlen(text);
861 b->auth_uid = hexmem(text, l);
862 if (!b->auth_uid)
863 return -ENOMEM;
864
021a1e78
LP
865 auth_suffix = b->negotiate_fds ? auth_suffix_with_unix_fd : auth_suffix_without_unix_fd;
866
de1c301e
LP
867 b->auth_iovec[0].iov_base = (void*) auth_prefix;
868 b->auth_iovec[0].iov_len = sizeof(auth_prefix) -1;
869 b->auth_iovec[1].iov_base = (void*) b->auth_uid;
870 b->auth_iovec[1].iov_len = l * 2;
871 b->auth_iovec[2].iov_base = (void*) auth_suffix;
021a1e78 872 b->auth_iovec[2].iov_len = strlen(auth_suffix);
de1c301e
LP
873 b->auth_size = sizeof(auth_prefix) - 1 + l * 2 + sizeof(auth_suffix) - 1;
874
875 return bus_write_auth(b);
876}
877
2fd9ae2e 878static int bus_connect(sd_bus *b) {
de1c301e
LP
879 int r;
880
881 assert(b);
882 assert(b->fd < 0);
2fd9ae2e 883 assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
de1c301e 884
2fd9ae2e
LP
885 b->fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
886 if (b->fd < 0)
887 return -errno;
de1c301e 888
2fd9ae2e
LP
889 r = bus_setup_fd(b);
890 if (r < 0)
891 return r;
2571ead1 892
2fd9ae2e
LP
893 r = connect(b->fd, &b->sockaddr.sa, b->sockaddr_size);
894 if (r < 0) {
895 if (errno == EINPROGRESS)
896 return 1;
de1c301e 897
2fd9ae2e
LP
898 return -errno;
899 }
900
901 return bus_start_auth(b);
902}
903
904static int bus_exec(sd_bus *b) {
905 int s[2];
906 pid_t pid;
907
908 assert(b);
909 assert(b->fd < 0);
910 assert(b->exec_path);
de1c301e 911
2fd9ae2e
LP
912 b->fd = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
913 if (b->fd < 0)
914 return -errno;
915
916 pid = fork();
917 if (pid < 0) {
918 close_pipe(s);
919 return -errno;
920 }
921 if (pid == 0) {
922 /* Child */
923
924 close_all_fds(s, 2);
925 close_nointr_nofail(s[0]);
926
927 assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO);
928 assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
929
930 if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO)
931 close_nointr_nofail(s[1]);
932
933 fd_cloexec(STDIN_FILENO, false);
934 fd_cloexec(STDOUT_FILENO, false);
935 fd_nonblock(STDIN_FILENO, false);
936 fd_nonblock(STDOUT_FILENO, false);
937
938 if (b->exec_argv)
939 execvp(b->exec_path, b->exec_argv);
940 else {
941 const char *argv[] = { b->exec_path, NULL };
942 execvp(b->exec_path, (char**) argv);
de1c301e
LP
943 }
944
2fd9ae2e
LP
945 _exit(EXIT_FAILURE);
946 }
2571ead1 947
2fd9ae2e
LP
948 close_nointr_nofail(s[1]);
949 b->fd = s[0];
2571ead1 950
2fd9ae2e
LP
951 return bus_start_auth(b);
952}
953
954static int bus_start_connect(sd_bus *b) {
955 int r;
956
957 assert(b);
958
959 for (;;) {
2571ead1
LP
960 if (b->fd >= 0) {
961 close_nointr_nofail(b->fd);
962 b->fd = -1;
963 }
2fd9ae2e
LP
964
965 if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
966 r = bus_connect(b);
967 if (r >= 0)
968 return r;
969
970 b->last_connect_error = -r;
971
972 } else if (b->exec_path) {
973
974 r = bus_exec(b);
975 if (r >= 0)
976 return r;
977
978 b->last_connect_error = -r;
979 }
980
981 r = bus_parse_next_address(b);
982 if (r < 0)
983 return r;
984 if (r == 0)
985 return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
de1c301e
LP
986 }
987}
988
021a1e78
LP
989static int bus_start_fd(sd_bus *b) {
990 int r;
991
992 assert(b);
993
994 r = fd_nonblock(b->fd, true);
995 if (r < 0)
996 return r;
997
998 r = fd_cloexec(b->fd, true);
999 if (r < 0)
1000 return r;
1001
1002 r = bus_setup_fd(b);
1003 if (r < 0)
1004 return r;
1005
1006 return bus_start_auth(b);
1007}
1008
1009int sd_bus_start(sd_bus *bus) {
1010 int r;
1011
1012 if (!bus)
1013 return -EINVAL;
1014 if (bus->state != BUS_UNSET)
1015 return -EPERM;
1016
1017 bus->state = BUS_OPENING;
1018
1019 if (bus->fd >= 0)
1020 r = bus_start_fd(bus);
1021 else if (bus->address)
1022 r = bus_start_connect(bus);
1023 else
1024 return -EINVAL;
1025
1026 if (r < 0)
1027 return r;
1028
1029 return bus_send_hello(bus);
1030}
1031
de1c301e
LP
1032int sd_bus_open_system(sd_bus **ret) {
1033 const char *e;
1034 sd_bus *b;
1035 int r;
1036
1037 if (!ret)
1038 return -EINVAL;
1039
021a1e78
LP
1040 r = sd_bus_new(&b);
1041 if (r < 0)
1042 return r;
1043
de1c301e
LP
1044 e = getenv("DBUS_SYSTEM_BUS_ADDRESS");
1045 if (e) {
021a1e78 1046 r = sd_bus_set_address(b, e);
de1c301e 1047 if (r < 0)
021a1e78 1048 goto fail;
89ffcd2a 1049 } else {
89ffcd2a
LP
1050 b->sockaddr.un.sun_family = AF_UNIX;
1051 strncpy(b->sockaddr.un.sun_path, "/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
1052 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/dbus/system_bus_socket") - 1;
89ffcd2a 1053 }
de1c301e 1054
021a1e78
LP
1055 b->send_hello = true;
1056
1057 r = sd_bus_start(b);
1058 if (r < 0)
1059 goto fail;
de1c301e
LP
1060
1061 *ret = b;
1062 return 0;
021a1e78
LP
1063
1064fail:
1065 bus_free(b);
1066 return r;
de1c301e
LP
1067}
1068
1069int sd_bus_open_user(sd_bus **ret) {
1070 const char *e;
1071 sd_bus *b;
1072 size_t l;
1073 int r;
1074
1075 if (!ret)
1076 return -EINVAL;
1077
021a1e78
LP
1078 r = sd_bus_new(&b);
1079 if (r < 0)
1080 return r;
1081
de1c301e
LP
1082 e = getenv("DBUS_SESSION_BUS_ADDRESS");
1083 if (e) {
021a1e78 1084 r = sd_bus_set_address(b, e);
de1c301e 1085 if (r < 0)
021a1e78 1086 goto fail;
89ffcd2a
LP
1087 } else {
1088 e = getenv("XDG_RUNTIME_DIR");
021a1e78
LP
1089 if (!e) {
1090 r = -ENOENT;
1091 goto fail;
1092 }
de1c301e 1093
89ffcd2a 1094 l = strlen(e);
021a1e78
LP
1095 if (l + 4 > sizeof(b->sockaddr.un.sun_path)) {
1096 r = -E2BIG;
1097 goto fail;
1098 }
de1c301e 1099
89ffcd2a
LP
1100 b->sockaddr.un.sun_family = AF_UNIX;
1101 memcpy(mempcpy(b->sockaddr.un.sun_path, e, l), "/bus", 4);
1102 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 4;
de1c301e
LP
1103 }
1104
021a1e78 1105 b->send_hello = true;
de1c301e 1106
021a1e78 1107 r = sd_bus_start(b);
2571ead1
LP
1108 if (r < 0)
1109 goto fail;
de1c301e
LP
1110
1111 *ret = b;
1112 return 0;
2571ead1
LP
1113
1114fail:
021a1e78 1115 bus_free(b);
2571ead1 1116 return r;
de1c301e
LP
1117}
1118
1119void sd_bus_close(sd_bus *bus) {
1120 if (!bus)
1121 return;
1122 if (bus->fd < 0)
1123 return;
1124
1125 close_nointr_nofail(bus->fd);
1126 bus->fd = -1;
1127}
1128
1129sd_bus *sd_bus_ref(sd_bus *bus) {
1130 if (!bus)
1131 return NULL;
1132
1133 assert(bus->n_ref > 0);
1134
1135 bus->n_ref++;
1136 return bus;
1137}
1138
1139sd_bus *sd_bus_unref(sd_bus *bus) {
1140 if (!bus)
1141 return NULL;
1142
1143 assert(bus->n_ref > 0);
1144 bus->n_ref--;
1145
1146 if (bus->n_ref <= 0)
1147 bus_free(bus);
1148
1149 return NULL;
1150}
1151
e3017af9
LP
1152int sd_bus_is_open(sd_bus *bus) {
1153 if (!bus)
1154 return -EINVAL;
1155
021a1e78 1156 return bus->state != BUS_UNSET && bus->fd >= 0;
e3017af9
LP
1157}
1158
d728d708
LP
1159int sd_bus_can_send(sd_bus *bus, char type) {
1160 int r;
1161
de1c301e
LP
1162 if (!bus)
1163 return -EINVAL;
021a1e78
LP
1164 if (bus->fd < 0)
1165 return -ENOTCONN;
de1c301e 1166
d728d708 1167 if (type == SD_BUS_TYPE_UNIX_FD) {
021a1e78
LP
1168 if (!bus->negotiate_fds)
1169 return 0;
1170
20902f3e 1171 r = bus_ensure_running(bus);
d728d708
LP
1172 if (r < 0)
1173 return r;
de1c301e 1174
d728d708
LP
1175 return bus->can_fds;
1176 }
1177
1178 return bus_type_is_valid(type);
de1c301e
LP
1179}
1180
d728d708
LP
1181int sd_bus_get_peer(sd_bus *bus, sd_id128_t *peer) {
1182 int r;
de1c301e
LP
1183
1184 if (!bus)
1185 return -EINVAL;
d728d708
LP
1186 if (!peer)
1187 return -EINVAL;
de1c301e 1188
20902f3e 1189 r = bus_ensure_running(bus);
d728d708
LP
1190 if (r < 0)
1191 return r;
de1c301e 1192
d728d708
LP
1193 *peer = bus->peer;
1194 return 0;
de1c301e
LP
1195}
1196
1197static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
1198 assert(m);
1199
89ffcd2a
LP
1200 if (m->header->version > b->message_version)
1201 return -EPERM;
1202
de1c301e
LP
1203 if (m->sealed)
1204 return 0;
1205
9a17484d 1206 return bus_message_seal(m, ++b->serial);
de1c301e
LP
1207}
1208
1209static int message_write(sd_bus *bus, sd_bus_message *m, size_t *idx) {
1210 struct msghdr mh;
1211 struct iovec *iov;
1212 ssize_t k;
1213 size_t n;
1214 unsigned j;
1215
1216 assert(bus);
1217 assert(m);
1218 assert(idx);
89ffcd2a 1219 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1220
e3017af9
LP
1221 if (*idx >= m->size)
1222 return 0;
2c93b4ef
LP
1223 zero(mh);
1224
1225 if (m->n_fds > 0) {
1226 struct cmsghdr *control;
1227 control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
1228
1229 mh.msg_control = control;
1230 control->cmsg_level = SOL_SOCKET;
1231 control->cmsg_type = SCM_RIGHTS;
1232 mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
1233 memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
1234 }
e3017af9 1235
de1c301e
LP
1236 n = m->n_iovec * sizeof(struct iovec);
1237 iov = alloca(n);
1238 memcpy(iov, m->iovec, n);
1239
1240 j = 0;
1241 iovec_advance(iov, &j, *idx);
1242
de1c301e
LP
1243 mh.msg_iov = iov;
1244 mh.msg_iovlen = m->n_iovec;
1245
1246 k = sendmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
1247 if (k < 0)
e3017af9 1248 return errno == EAGAIN ? 0 : -errno;
de1c301e
LP
1249
1250 *idx += (size_t) k;
e3017af9 1251 return 1;
de1c301e
LP
1252}
1253
1254static int message_read_need(sd_bus *bus, size_t *need) {
1255 uint32_t a, b;
1256 uint8_t e;
25220239 1257 uint64_t sum;
de1c301e
LP
1258
1259 assert(bus);
1260 assert(need);
89ffcd2a 1261 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1262
89ffcd2a 1263 if (bus->rbuffer_size < sizeof(struct bus_header)) {
e3017af9
LP
1264 *need = sizeof(struct bus_header) + 8;
1265
1266 /* Minimum message size:
1267 *
1268 * Header +
1269 *
1270 * Method Call: +2 string headers
1271 * Signal: +3 string headers
1272 * Method Error: +1 string headers
1273 * +1 uint32 headers
1274 * Method Reply: +1 uint32 headers
1275 *
1276 * A string header is at least 9 bytes
1277 * A uint32 header is at least 8 bytes
1278 *
1279 * Hence the minimum message size of a valid message
1280 * is header + 8 bytes */
1281
de1c301e
LP
1282 return 0;
1283 }
1284
1285 a = ((const uint32_t*) bus->rbuffer)[1];
1286 b = ((const uint32_t*) bus->rbuffer)[3];
1287
1288 e = ((const uint8_t*) bus->rbuffer)[0];
1289 if (e == SD_BUS_LITTLE_ENDIAN) {
1290 a = le32toh(a);
1291 b = le32toh(b);
1292 } else if (e == SD_BUS_BIG_ENDIAN) {
1293 a = be32toh(a);
1294 b = be32toh(b);
1295 } else
89ffcd2a 1296 return -EBADMSG;
de1c301e 1297
25220239
LP
1298 sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
1299 if (sum >= BUS_MESSAGE_SIZE_MAX)
1300 return -ENOBUFS;
1301
1302 *need = (size_t) sum;
de1c301e
LP
1303 return 0;
1304}
1305
1306static int message_make(sd_bus *bus, size_t size, sd_bus_message **m) {
1307 sd_bus_message *t;
2c93b4ef 1308 void *b;
de1c301e
LP
1309 int r;
1310
1311 assert(bus);
1312 assert(m);
1313 assert(bus->rbuffer_size >= size);
89ffcd2a 1314 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1315
de1c301e 1316 if (bus->rbuffer_size > size) {
9e1fe7c3
ZJS
1317 b = memdup((const uint8_t*) bus->rbuffer + size,
1318 bus->rbuffer_size - size);
1319 if (!b)
de1c301e 1320 return -ENOMEM;
2c93b4ef
LP
1321 } else
1322 b = NULL;
de1c301e 1323
2571ead1 1324 r = bus_message_from_malloc(bus->rbuffer, size,
2c93b4ef 1325 bus->fds, bus->n_fds,
2571ead1 1326 bus->ucred_valid ? &bus->ucred : NULL,
2c93b4ef
LP
1327 bus->label[0] ? bus->label : NULL,
1328 &t);
80a46c73
LP
1329 if (r < 0) {
1330 free(b);
1331 return r;
1332 }
de1c301e
LP
1333
1334 bus->rbuffer = b;
1335 bus->rbuffer_size -= size;
1336
2c93b4ef
LP
1337 bus->fds = NULL;
1338 bus->n_fds = 0;
1339
de1c301e
LP
1340 *m = t;
1341 return 1;
1342}
1343
1344static int message_read(sd_bus *bus, sd_bus_message **m) {
1345 struct msghdr mh;
1346 struct iovec iov;
1347 ssize_t k;
1348 size_t need;
1349 int r;
1350 void *b;
2571ead1
LP
1351 union {
1352 struct cmsghdr cmsghdr;
2c93b4ef
LP
1353 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) +
1354 CMSG_SPACE(sizeof(struct ucred)) +
2571ead1
LP
1355 CMSG_SPACE(NAME_MAX)]; /*selinux label */
1356 } control;
1357 struct cmsghdr *cmsg;
de1c301e
LP
1358
1359 assert(bus);
1360 assert(m);
89ffcd2a 1361 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e
LP
1362
1363 r = message_read_need(bus, &need);
1364 if (r < 0)
1365 return r;
1366
1367 if (bus->rbuffer_size >= need)
1368 return message_make(bus, need, m);
1369
1370 b = realloc(bus->rbuffer, need);
1371 if (!b)
1372 return -ENOMEM;
1373
89ffcd2a
LP
1374 bus->rbuffer = b;
1375
de1c301e
LP
1376 zero(iov);
1377 iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size;
1378 iov.iov_len = need - bus->rbuffer_size;
1379
1380 zero(mh);
1381 mh.msg_iov = &iov;
1382 mh.msg_iovlen = 1;
2571ead1
LP
1383 mh.msg_control = &control;
1384 mh.msg_controllen = sizeof(control);
de1c301e 1385
2571ead1 1386 k = recvmsg(bus->fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
de1c301e
LP
1387 if (k < 0)
1388 return errno == EAGAIN ? 0 : -errno;
66f931b4
LP
1389 if (k == 0)
1390 return -ECONNRESET;
de1c301e
LP
1391
1392 bus->rbuffer_size += k;
2571ead1
LP
1393
1394 for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
1395 if (cmsg->cmsg_level == SOL_SOCKET &&
2c93b4ef
LP
1396 cmsg->cmsg_type == SCM_RIGHTS) {
1397 int n, *f;
1398
1399 n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
1400
1401 f = realloc(bus->fds, sizeof(int) + (bus->n_fds + n));
1402 if (!f) {
1403 close_many((int*) CMSG_DATA(cmsg), n);
1404 return -ENOMEM;
1405 }
1406
1407 memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
1408 bus->fds = f;
1409 bus->n_fds += n;
1410 } else if (cmsg->cmsg_level == SOL_SOCKET &&
2571ead1
LP
1411 cmsg->cmsg_type == SCM_CREDENTIALS &&
1412 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1413
1414 memcpy(&bus->ucred, CMSG_DATA(cmsg), sizeof(struct ucred));
1415 bus->ucred_valid = true;
1416
1417 } else if (cmsg->cmsg_level == SOL_SOCKET &&
1418 cmsg->cmsg_type == SCM_SECURITY) {
1419
1420 size_t l;
1421 l = cmsg->cmsg_len - CMSG_LEN(0);
1422 memcpy(&bus->label, CMSG_DATA(cmsg), l);
1423 bus->label[l] = 0;
1424 }
1425 }
de1c301e
LP
1426
1427 r = message_read_need(bus, &need);
1428 if (r < 0)
1429 return r;
1430
1431 if (bus->rbuffer_size >= need)
1432 return message_make(bus, need, m);
1433
e3017af9 1434 return 1;
de1c301e
LP
1435}
1436
1437static int dispatch_wqueue(sd_bus *bus) {
e3017af9 1438 int r, ret = 0;
de1c301e
LP
1439
1440 assert(bus);
89ffcd2a 1441 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e
LP
1442
1443 if (bus->fd < 0)
1444 return -ENOTCONN;
1445
1446 while (bus->wqueue_size > 0) {
1447
1448 r = message_write(bus, bus->wqueue[0], &bus->windex);
1449 if (r < 0) {
1450 sd_bus_close(bus);
1451 return r;
1452 } else if (r == 0)
e3017af9
LP
1453 /* Didn't do anything this time */
1454 return ret;
1455 else if (bus->windex >= bus->wqueue[0]->size) {
de1c301e
LP
1456 /* Fully written. Let's drop the entry from
1457 * the queue.
1458 *
1459 * This isn't particularly optimized, but
1460 * well, this is supposed to be our worst-case
1461 * buffer only, and the socket buffer is
1462 * supposed to be our primary buffer, and if
1463 * it got full, then all bets are off
1464 * anyway. */
1465
1466 sd_bus_message_unref(bus->wqueue[0]);
1467 bus->wqueue_size --;
1468 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1469 bus->windex = 0;
1470
e3017af9 1471 ret = 1;
de1c301e
LP
1472 }
1473 }
1474
e3017af9 1475 return ret;
de1c301e
LP
1476}
1477
1478static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
2bf938c1 1479 sd_bus_message *z = NULL;
e3017af9 1480 int r, ret = 0;
de1c301e
LP
1481
1482 assert(bus);
1483 assert(m);
89ffcd2a 1484 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e
LP
1485
1486 if (bus->fd < 0)
1487 return -ENOTCONN;
1488
1489 if (bus->rqueue_size > 0) {
1490 /* Dispatch a queued message */
1491
1492 *m = bus->rqueue[0];
1493 bus->rqueue_size --;
1494 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1495 return 1;
1496 }
1497
1498 /* Try to read a new message */
e3017af9
LP
1499 do {
1500 r = message_read(bus, &z);
1501 if (r < 0) {
1502 sd_bus_close(bus);
1503 return r;
1504 }
1505 if (r == 0)
1506 return ret;
de1c301e 1507
e3017af9
LP
1508 r = 1;
1509 } while (!z);
1510
1511 *m = z;
1512 return 1;
de1c301e
LP
1513}
1514
1515int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
1516 int r;
1517
1518 if (!bus)
1519 return -EINVAL;
021a1e78
LP
1520 if (bus->state == BUS_UNSET)
1521 return -ENOTCONN;
de1c301e
LP
1522 if (bus->fd < 0)
1523 return -ENOTCONN;
1524 if (!m)
1525 return -EINVAL;
021a1e78
LP
1526
1527 if (m->n_fds > 0) {
1528 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1529 if (r < 0)
1530 return r;
1531 if (r == 0)
1532 return -ENOTSUP;
1533 }
de1c301e 1534
29f6aadd
LP
1535 /* If the serial number isn't kept, then we know that no reply
1536 * is expected */
1537 if (!serial && !m->sealed)
1538 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1539
de1c301e
LP
1540 r = bus_seal_message(bus, m);
1541 if (r < 0)
1542 return r;
1543
5407f2de
LP
1544 /* If this is a reply and no reply was requested, then let's
1545 * suppress this, if we can */
1546 if (m->dont_send && !serial)
1547 return 0;
1548
89ffcd2a 1549 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
de1c301e
LP
1550 size_t idx = 0;
1551
1552 r = message_write(bus, m, &idx);
1553 if (r < 0) {
1554 sd_bus_close(bus);
1555 return r;
e3017af9 1556 } else if (idx < m->size) {
de1c301e
LP
1557 /* Wasn't fully written. So let's remember how
1558 * much was written. Note that the first entry
1559 * of the wqueue array is always allocated so
1560 * that we always can remember how much was
1561 * written. */
1562 bus->wqueue[0] = sd_bus_message_ref(m);
1563 bus->wqueue_size = 1;
1564 bus->windex = idx;
1565 }
1566 } else {
1567 sd_bus_message **q;
1568
1569 /* Just append it to the queue. */
1570
25220239 1571 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
de1c301e
LP
1572 return -ENOBUFS;
1573
1574 q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
1575 if (!q)
1576 return -ENOMEM;
1577
1578 bus->wqueue = q;
1579 q[bus->wqueue_size ++] = sd_bus_message_ref(m);
1580 }
1581
1582 if (serial)
1583 *serial = BUS_MESSAGE_SERIAL(m);
1584
1585 return 0;
1586}
1587
1588static usec_t calc_elapse(uint64_t usec) {
1589 if (usec == (uint64_t) -1)
1590 return 0;
1591
1592 if (usec == 0)
e3017af9 1593 usec = BUS_DEFAULT_TIMEOUT;
de1c301e
LP
1594
1595 return now(CLOCK_MONOTONIC) + usec;
1596}
1597
e3017af9
LP
1598static int timeout_compare(const void *a, const void *b) {
1599 const struct reply_callback *x = a, *y = b;
1600
1601 if (x->timeout != 0 && y->timeout == 0)
1602 return -1;
1603
1604 if (x->timeout == 0 && y->timeout != 0)
1605 return 1;
1606
1607 if (x->timeout < y->timeout)
1608 return -1;
1609
1610 if (x->timeout > y->timeout)
1611 return 1;
1612
1613 return 0;
1614}
1615
de1c301e
LP
1616int sd_bus_send_with_reply(
1617 sd_bus *bus,
1618 sd_bus_message *m,
1619 sd_message_handler_t callback,
1620 void *userdata,
1621 uint64_t usec,
1622 uint64_t *serial) {
1623
1624 struct reply_callback *c;
1625 int r;
1626
1627 if (!bus)
1628 return -EINVAL;
021a1e78
LP
1629 if (bus->state == BUS_UNSET)
1630 return -ENOTCONN;
89ffcd2a 1631 if (bus->fd < 0)
de1c301e
LP
1632 return -ENOTCONN;
1633 if (!m)
1634 return -EINVAL;
1635 if (!callback)
1636 return -EINVAL;
89ffcd2a 1637 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1638 return -EINVAL;
89ffcd2a
LP
1639 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1640 return -EINVAL;
1641
1642 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1643 if (r < 0)
1644 return r;
de1c301e 1645
e3017af9
LP
1646 if (usec != (uint64_t) -1) {
1647 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1648 if (r < 0)
1649 return r;
1650 }
1651
de1c301e
LP
1652 r = bus_seal_message(bus, m);
1653 if (r < 0)
1654 return r;
1655
1656 c = new(struct reply_callback, 1);
1657 if (!c)
1658 return -ENOMEM;
1659
1660 c->callback = callback;
1661 c->userdata = userdata;
1662 c->serial = BUS_MESSAGE_SERIAL(m);
1663 c->timeout = calc_elapse(usec);
1664
1665 r = hashmap_put(bus->reply_callbacks, &c->serial, c);
1666 if (r < 0) {
1667 free(c);
1668 return r;
1669 }
1670
e3017af9
LP
1671 if (c->timeout != 0) {
1672 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1673 if (r < 0) {
1674 c->timeout = 0;
1675 sd_bus_send_with_reply_cancel(bus, c->serial);
1676 return r;
1677 }
1678 }
1679
de1c301e
LP
1680 r = sd_bus_send(bus, m, serial);
1681 if (r < 0) {
e3017af9 1682 sd_bus_send_with_reply_cancel(bus, c->serial);
de1c301e
LP
1683 return r;
1684 }
1685
1686 return r;
1687}
1688
1689int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) {
e3017af9 1690 struct reply_callback *c;
de1c301e
LP
1691
1692 if (!bus)
1693 return -EINVAL;
1694 if (serial == 0)
1695 return -EINVAL;
1696
1697 c = hashmap_remove(bus->reply_callbacks, &serial);
1698 if (!c)
1699 return 0;
1700
e3017af9
LP
1701 if (c->timeout != 0)
1702 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1703
de1c301e
LP
1704 free(c);
1705 return 1;
1706}
1707
20902f3e 1708int bus_ensure_running(sd_bus *bus) {
89ffcd2a
LP
1709 int r;
1710
1711 assert(bus);
1712
021a1e78
LP
1713 if (bus->fd < 0)
1714 return -ENOTCONN;
1715 if (bus->state == BUS_UNSET)
1716 return -ENOTCONN;
1717
d728d708
LP
1718 if (bus->state == BUS_RUNNING)
1719 return 1;
89ffcd2a
LP
1720
1721 for (;;) {
1722 r = sd_bus_process(bus, NULL);
1723 if (r < 0)
1724 return r;
d728d708
LP
1725 if (bus->state == BUS_RUNNING)
1726 return 1;
e3017af9
LP
1727 if (r > 0)
1728 continue;
89ffcd2a
LP
1729
1730 r = sd_bus_wait(bus, (uint64_t) -1);
1731 if (r < 0)
1732 return r;
1733 }
1734}
1735
de1c301e
LP
1736int sd_bus_send_with_reply_and_block(
1737 sd_bus *bus,
1738 sd_bus_message *m,
1739 uint64_t usec,
1740 sd_bus_error *error,
1741 sd_bus_message **reply) {
1742
1743 int r;
1744 usec_t timeout;
1745 uint64_t serial;
1746 bool room = false;
1747
1748 if (!bus)
1749 return -EINVAL;
89ffcd2a 1750 if (bus->fd < 0)
de1c301e 1751 return -ENOTCONN;
021a1e78
LP
1752 if (bus->state == BUS_UNSET)
1753 return -ENOTCONN;
de1c301e
LP
1754 if (!m)
1755 return -EINVAL;
89ffcd2a 1756 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1757 return -EINVAL;
89ffcd2a 1758 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
de1c301e 1759 return -EINVAL;
89ffcd2a
LP
1760 if (bus_error_is_dirty(error))
1761 return -EINVAL;
1762
20902f3e 1763 r = bus_ensure_running(bus);
89ffcd2a
LP
1764 if (r < 0)
1765 return r;
de1c301e
LP
1766
1767 r = sd_bus_send(bus, m, &serial);
1768 if (r < 0)
1769 return r;
1770
1771 timeout = calc_elapse(usec);
1772
1773 for (;;) {
1774 usec_t left;
e3017af9 1775 sd_bus_message *incoming = NULL;
de1c301e
LP
1776
1777 if (!room) {
1778 sd_bus_message **q;
1779
25220239
LP
1780 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1781 return -ENOBUFS;
1782
de1c301e
LP
1783 /* Make sure there's room for queuing this
1784 * locally, before we read the message */
1785
1786 q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
1787 if (!q)
1788 return -ENOMEM;
1789
1790 bus->rqueue = q;
1791 room = true;
1792 }
1793
1794 r = message_read(bus, &incoming);
1795 if (r < 0)
1796 return r;
e3017af9 1797 if (incoming) {
89ffcd2a 1798
de1c301e
LP
1799 if (incoming->reply_serial == serial) {
1800 /* Found a match! */
1801
1802 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) {
1803 *reply = incoming;
1804 return 0;
1805 }
1806
1807 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) {
1808 int k;
1809
1810 r = sd_bus_error_copy(error, &incoming->error);
1811 if (r < 0) {
1812 sd_bus_message_unref(incoming);
1813 return r;
1814 }
1815
1816 k = bus_error_to_errno(&incoming->error);
1817 sd_bus_message_unref(incoming);
1818 return k;
1819 }
1820
1821 sd_bus_message_unref(incoming);
1822 return -EIO;
1823 }
1824
1825 /* There's already guaranteed to be room for
1826 * this, so need to resize things here */
1827 bus->rqueue[bus->rqueue_size ++] = incoming;
1828 room = false;
1829
1830 /* Try to read more, right-away */
1831 continue;
1832 }
e3017af9
LP
1833 if (r != 0)
1834 continue;
de1c301e
LP
1835
1836 if (timeout > 0) {
1837 usec_t n;
1838
1839 n = now(CLOCK_MONOTONIC);
1840 if (n >= timeout)
1841 return -ETIMEDOUT;
1842
1843 left = timeout - n;
1844 } else
1845 left = (uint64_t) -1;
1846
e3017af9 1847 r = bus_poll(bus, true, left);
de1c301e
LP
1848 if (r < 0)
1849 return r;
1850
1851 r = dispatch_wqueue(bus);
1852 if (r < 0)
1853 return r;
1854 }
1855}
1856
1857int sd_bus_get_fd(sd_bus *bus) {
1858 if (!bus)
1859 return -EINVAL;
1860
1861 if (bus->fd < 0)
89ffcd2a 1862 return -ENOTCONN;
de1c301e
LP
1863
1864 return bus->fd;
1865}
1866
1867int sd_bus_get_events(sd_bus *bus) {
1868 int flags = 0;
1869
1870 if (!bus)
1871 return -EINVAL;
021a1e78
LP
1872 if (bus->state == BUS_UNSET)
1873 return -ENOTCONN;
de1c301e 1874 if (bus->fd < 0)
89ffcd2a 1875 return -ENOTCONN;
de1c301e
LP
1876
1877 if (bus->state == BUS_OPENING)
1878 flags |= POLLOUT;
89ffcd2a
LP
1879 else if (bus->state == BUS_AUTHENTICATING) {
1880
1881 if (bus->auth_index < ELEMENTSOF(bus->auth_iovec))
1882 flags |= POLLOUT;
1883
1884 flags |= POLLIN;
1885
1886 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
de1c301e
LP
1887 if (bus->rqueue_size <= 0)
1888 flags |= POLLIN;
1889 if (bus->wqueue_size > 0)
1890 flags |= POLLOUT;
1891 }
1892
1893 return flags;
1894}
1895
e3017af9
LP
1896int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
1897 struct reply_callback *c;
1898
1899 if (!bus)
1900 return -EINVAL;
1901 if (!timeout_usec)
1902 return -EINVAL;
021a1e78
LP
1903 if (bus->state == BUS_UNSET)
1904 return -ENOTCONN;
e3017af9
LP
1905 if (bus->fd < 0)
1906 return -ENOTCONN;
1907
1908 if (bus->state == BUS_AUTHENTICATING) {
1909 *timeout_usec = bus->auth_timeout;
1910 return 1;
1911 }
1912
1913 if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO)
1914 return 0;
1915
1916 c = prioq_peek(bus->reply_callbacks_prioq);
1917 if (!c)
1918 return 0;
1919
1920 *timeout_usec = c->timeout;
1921 return 1;
1922}
1923
1924static int process_timeout(sd_bus *bus) {
e3017af9
LP
1925 struct reply_callback *c;
1926 usec_t n;
1927 int r;
1928
1929 assert(bus);
1930
1931 c = prioq_peek(bus->reply_callbacks_prioq);
1932 if (!c)
1933 return 0;
1934
1935 n = now(CLOCK_MONOTONIC);
1936 if (c->timeout > n)
1937 return 0;
1938
1939 assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
1940 hashmap_remove(bus->reply_callbacks, &c->serial);
1941
1942 r = c->callback(bus, ETIMEDOUT, NULL, c->userdata);
1943 free(c);
1944
1945 return r < 0 ? r : 1;
1946}
1947
a652755d
LP
1948static int process_reply(sd_bus *bus, sd_bus_message *m) {
1949 struct reply_callback *c;
1950 int r;
1951
1952 assert(bus);
1953 assert(m);
1954
1955 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1956 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1957 return 0;
1958
1959 c = hashmap_remove(bus->reply_callbacks, &m->reply_serial);
1960 if (!c)
1961 return 0;
1962
1963 if (c->timeout != 0)
1964 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1965
1966 r = c->callback(bus, 0, m, c->userdata);
1967 free(c);
1968
1969 return r;
1970}
1971
1972static int process_filter(sd_bus *bus, sd_bus_message *m) {
1973 struct filter_callback *l;
1974 int r;
1975
1976 LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
1977 r = l->callback(bus, 0, m, l->userdata);
1978 if (r != 0)
1979 return r;
1980 }
1981
1982 return 0;
1983}
1984
b9bf7e2b
LP
1985static int process_builtin(sd_bus *bus, sd_bus_message *m) {
1986 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1987 int r;
1988
1989 assert(bus);
1990 assert(m);
1991
1992 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1993 return 0;
1994
1995 if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
1996 return 0;
1997
1998 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1999 return 1;
2000
2001 if (streq_ptr(m->member, "Ping"))
2002 r = sd_bus_message_new_method_return(bus, m, &reply);
2003 else if (streq_ptr(m->member, "GetMachineId")) {
2004 sd_id128_t id;
2005 char sid[33];
2006
2007 r = sd_id128_get_machine(&id);
2008 if (r < 0)
2009 return r;
2010
2011 r = sd_bus_message_new_method_return(bus, m, &reply);
2012 if (r < 0)
2013 return r;
2014
2015 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
2016 } else {
2017 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_INIT;
2018
2019 sd_bus_error_set(&error,
2020 "org.freedesktop.DBus.Error.UnknownMethod",
2021 "Unknown method '%s' on interface '%s'.", m->member, m->interface);
2022
2023 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
2024 }
2025
2026 if (r < 0)
2027 return r;
2028
2029 r = sd_bus_send(bus, reply, NULL);
2030 if (r < 0)
2031 return r;
2032
2033 return 1;
2034}
2035
a652755d
LP
2036static int process_object(sd_bus *bus, sd_bus_message *m) {
2037 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_INIT;
2038 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2039 struct object_callback *c;
2040 char *p;
e3017af9 2041 int r;
a652755d 2042 bool found = false;
e3017af9
LP
2043
2044 assert(bus);
2045 assert(m);
2046
a652755d
LP
2047 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2048 return 0;
e3017af9 2049
a652755d
LP
2050 if (hashmap_isempty(bus->object_callbacks))
2051 return 0;
e3017af9 2052
a652755d
LP
2053 c = hashmap_get(bus->object_callbacks, m->path);
2054 if (c) {
2055 r = c->callback(bus, 0, m, c->userdata);
2056 if (r != 0)
2057 return r;
2058
2059 found = true;
2060 }
e3017af9 2061
a652755d
LP
2062 /* Look for fallback prefixes */
2063 p = strdupa(m->path);
2064 for (;;) {
2065 char *e;
2066
2067 e = strrchr(p, '/');
2068 if (e == p || !e)
2069 break;
2070
2071 *e = 0;
2072
2073 c = hashmap_get(bus->object_callbacks, p);
2074 if (c && c->is_fallback) {
2075 r = c->callback(bus, 0, m, c->userdata);
e3017af9
LP
2076 if (r != 0)
2077 return r;
a652755d
LP
2078
2079 found = true;
e3017af9
LP
2080 }
2081 }
2082
a652755d
LP
2083 if (!found)
2084 return 0;
2085
2086 sd_bus_error_set(&error,
2087 "org.freedesktop.DBus.Error.UnknownMethod",
2088 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
2089
2090 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
2091 if (r < 0)
2092 return r;
2093
2094 r = sd_bus_send(bus, reply, NULL);
2095 if (r < 0)
2096 return r;
e3017af9 2097
a652755d
LP
2098 return 1;
2099}
2100
2101static int process_message(sd_bus *bus, sd_bus_message *m) {
2102 int r;
2103
2104 assert(bus);
2105 assert(m);
2106
2107 r = process_reply(bus, m);
2108 if (r != 0)
2109 return r;
2110
2111 r = process_filter(bus, m);
2112 if (r != 0)
2113 return r;
2114
2115 r = process_builtin(bus, m);
2116 if (r != 0)
2117 return r;
2118
2119 return process_object(bus, m);
e3017af9
LP
2120}
2121
de1c301e 2122int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
de1c301e
LP
2123 int r;
2124
e3017af9
LP
2125 /* Returns 0 when we didn't do anything. This should cause the
2126 * caller to invoke sd_bus_wait() before returning the next
2127 * time. Returns > 0 when we did something, which possibly
2128 * means *ret is filled in with an unprocessed message. */
2129
de1c301e
LP
2130 if (!bus)
2131 return -EINVAL;
021a1e78
LP
2132 if (bus->state == BUS_UNSET)
2133 return -ENOTCONN;
de1c301e
LP
2134 if (bus->fd < 0)
2135 return -ENOTCONN;
2136
2137 if (bus->state == BUS_OPENING) {
2138 struct pollfd p;
2139
2140 zero(p);
2141 p.fd = bus->fd;
2142 p.events = POLLOUT;
2143
2144 r = poll(&p, 1, 0);
2145 if (r < 0)
2146 return -errno;
2147
2148 if (p.revents & (POLLOUT|POLLERR|POLLHUP)) {
89ffcd2a 2149 int error = 0;
de1c301e
LP
2150 socklen_t slen = sizeof(error);
2151
2152 r = getsockopt(bus->fd, SOL_SOCKET, SO_ERROR, &error, &slen);
2153 if (r < 0)
e3017af9
LP
2154 bus->last_connect_error = errno;
2155 else if (error != 0)
2156 bus->last_connect_error = error;
de1c301e 2157 else if (p.revents & (POLLERR|POLLHUP))
e3017af9
LP
2158 bus->last_connect_error = ECONNREFUSED;
2159 else {
2160 r = bus_start_auth(bus);
2161 goto null_message;
2162 }
de1c301e
LP
2163
2164 /* Try next address */
2fd9ae2e 2165 bus_reset_parsed_address(bus);
e3017af9
LP
2166 r = bus_start_connect(bus);
2167 goto null_message;
de1c301e
LP
2168 }
2169
e3017af9
LP
2170 r = 0;
2171 goto null_message;
de1c301e
LP
2172
2173 } else if (bus->state == BUS_AUTHENTICATING) {
2174
e3017af9
LP
2175 if (now(CLOCK_MONOTONIC) >= bus->auth_timeout)
2176 return -ETIMEDOUT;
2177
de1c301e 2178 r = bus_write_auth(bus);
e3017af9
LP
2179 if (r != 0)
2180 goto null_message;
de1c301e
LP
2181
2182 r = bus_read_auth(bus);
e3017af9 2183 goto null_message;
de1c301e
LP
2184
2185 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
89ffcd2a 2186 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
e3017af9
LP
2187 int k;
2188
2189 r = process_timeout(bus);
2190 if (r != 0)
2191 goto null_message;
de1c301e
LP
2192
2193 r = dispatch_wqueue(bus);
e3017af9
LP
2194 if (r != 0)
2195 goto null_message;
de1c301e 2196
e3017af9 2197 k = r;
de1c301e 2198 r = dispatch_rqueue(bus, &m);
e3017af9 2199 if (r < 0)
de1c301e 2200 return r;
e3017af9
LP
2201 if (!m) {
2202 if (r == 0)
2203 r = k;
2204 goto null_message;
de1c301e
LP
2205 }
2206
e3017af9
LP
2207 r = process_message(bus, m);
2208 if (r != 0)
2209 goto null_message;
de1c301e
LP
2210
2211 if (ret) {
2212 *ret = m;
89ffcd2a 2213 m = NULL;
de1c301e
LP
2214 return 1;
2215 }
2216
b9bf7e2b 2217 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL) {
89ffcd2a 2218 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
b9bf7e2b
LP
2219 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_INIT;
2220
2221 sd_bus_error_set(&error, "org.freedesktop.DBus.Error.UnknownObject", "Unknown object '%s'.", m->path);
89ffcd2a 2222
b9bf7e2b 2223 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
89ffcd2a
LP
2224 if (r < 0)
2225 return r;
2226
2227 r = sd_bus_send(bus, reply, NULL);
2228 if (r < 0)
2229 return r;
2230 }
2231
e3017af9 2232 return 1;
de1c301e
LP
2233 }
2234
89ffcd2a 2235 assert_not_reached("Unknown state");
e3017af9
LP
2236
2237null_message:
2238 if (r >= 0 && ret)
2239 *ret = NULL;
2240
2241 return r;
de1c301e
LP
2242}
2243
e3017af9 2244static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
de1c301e
LP
2245 struct pollfd p;
2246 int r, e;
2247 struct timespec ts;
e3017af9
LP
2248 usec_t until, m;
2249
2250 assert(bus);
de1c301e 2251
de1c301e 2252 if (bus->fd < 0)
89ffcd2a
LP
2253 return -ENOTCONN;
2254
de1c301e
LP
2255 e = sd_bus_get_events(bus);
2256 if (e < 0)
2257 return e;
2258
e3017af9
LP
2259 if (need_more)
2260 e |= POLLIN;
2261
2262 r = sd_bus_get_timeout(bus, &until);
2263 if (r < 0)
2264 return r;
2265 if (r == 0)
2266 m = (uint64_t) -1;
2267 else {
2268 usec_t n;
2269 n = now(CLOCK_MONOTONIC);
2270 m = until > n ? until - n : 0;
2271 }
2272
2273 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
2274 m = timeout_usec;
2275
de1c301e
LP
2276 zero(p);
2277 p.fd = bus->fd;
2278 p.events = e;
2279
e3017af9 2280 r = ppoll(&p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
de1c301e 2281 if (r < 0)
89ffcd2a 2282 return -errno;
de1c301e 2283
e3017af9
LP
2284 return r > 0 ? 1 : 0;
2285}
2286
2287int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
2288
2289 if (!bus)
2290 return -EINVAL;
021a1e78
LP
2291 if (bus->state == BUS_UNSET)
2292 return -ENOTCONN;
e3017af9
LP
2293 if (bus->fd < 0)
2294 return -ENOTCONN;
2295 if (bus->rqueue_size > 0)
2296 return 0;
2297
2298 return bus_poll(bus, false, timeout_usec);
de1c301e
LP
2299}
2300
2301int sd_bus_flush(sd_bus *bus) {
2302 int r;
2303
2304 if (!bus)
2305 return -EINVAL;
021a1e78
LP
2306 if (bus->state == BUS_UNSET)
2307 return -ENOTCONN;
de1c301e
LP
2308 if (bus->fd < 0)
2309 return -ENOTCONN;
2310
20902f3e 2311 r = bus_ensure_running(bus);
89ffcd2a
LP
2312 if (r < 0)
2313 return r;
2314
2315 if (bus->wqueue_size <= 0)
de1c301e
LP
2316 return 0;
2317
2318 for (;;) {
2319 r = dispatch_wqueue(bus);
2320 if (r < 0)
2321 return r;
2322
89ffcd2a 2323 if (bus->wqueue_size <= 0)
de1c301e
LP
2324 return 0;
2325
e3017af9 2326 r = bus_poll(bus, false, (uint64_t) -1);
de1c301e
LP
2327 if (r < 0)
2328 return r;
2329 }
2330}
2331
2332int sd_bus_add_filter(sd_bus *bus, sd_message_handler_t callback, void *userdata) {
2333 struct filter_callback *f;
2334
2335 if (!bus)
2336 return -EINVAL;
2337 if (!callback)
2338 return -EINVAL;
2339
2340 f = new(struct filter_callback, 1);
2341 if (!f)
2342 return -ENOMEM;
2343 f->callback = callback;
2344 f->userdata = userdata;
2345
2346 LIST_PREPEND(struct filter_callback, callbacks, bus->filter_callbacks, f);
2347 return 0;
2348}
2349
2350int sd_bus_remove_filter(sd_bus *bus, sd_message_handler_t callback, void *userdata) {
2351 struct filter_callback *f;
2352
2353 if (!bus)
2354 return -EINVAL;
2355 if (!callback)
2356 return -EINVAL;
2357
2358 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
2359 if (f->callback == callback && f->userdata == userdata) {
2360 LIST_REMOVE(struct filter_callback, callbacks, bus->filter_callbacks, f);
2361 free(f);
2362 return 1;
2363 }
2364 }
2365
2366 return 0;
2367}
a652755d
LP
2368
2369static int bus_add_object(
2370 sd_bus *bus,
2371 bool fallback,
2372 const char *path,
2373 sd_message_handler_t callback,
2374 void *userdata) {
2375
2376 struct object_callback *c;
2377 int r;
2378
2379 if (!bus)
2380 return -EINVAL;
2381 if (!path)
2382 return -EINVAL;
2383 if (!callback)
2384 return -EINVAL;
2385
2386 r = hashmap_ensure_allocated(&bus->object_callbacks, string_hash_func, string_compare_func);
2387 if (r < 0)
2388 return r;
2389
2390 c = new(struct object_callback, 1);
2391 if (!c)
2392 return -ENOMEM;
2393
2394 c->path = strdup(path);
2395 if (!path) {
2396 free(c);
2397 return -ENOMEM;
2398 }
2399
2400 c->callback = callback;
2401 c->userdata = userdata;
2402 c->is_fallback = fallback;
2403
2404 r = hashmap_put(bus->object_callbacks, c->path, c);
2405 if (r < 0) {
2406 free(c->path);
2407 free(c);
2408 return r;
2409 }
2410
2411 return 0;
2412}
2413
2414static int bus_remove_object(
2415 sd_bus *bus,
2416 bool fallback,
2417 const char *path,
2418 sd_message_handler_t callback,
2419 void *userdata) {
2420
2421 struct object_callback *c;
2422
2423 if (!bus)
2424 return -EINVAL;
2425 if (!path)
2426 return -EINVAL;
2427 if (!callback)
2428 return -EINVAL;
2429
2430 c = hashmap_get(bus->object_callbacks, path);
2431 if (!c)
2432 return 0;
2433
2434 if (c->callback != callback || c->userdata != userdata || c->is_fallback != fallback)
2435 return 0;
2436
2437 assert_se(c == hashmap_remove(bus->object_callbacks, c->path));
2438
2439 free(c->path);
2440 free(c);
2441
2442 return 1;
2443}
2444
2445int sd_bus_add_object(sd_bus *bus, const char *path, sd_message_handler_t callback, void *userdata) {
2446 return bus_add_object(bus, false, path, callback, userdata);
2447}
2448
2449int sd_bus_remove_object(sd_bus *bus, const char *path, sd_message_handler_t callback, void *userdata) {
2450 return bus_remove_object(bus, false, path, callback, userdata);
2451}
2452
2453int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_message_handler_t callback, void *userdata) {
2454 return bus_add_object(bus, true, prefix, callback, userdata);
2455}
2456
2457int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_message_handler_t callback, void *userdata) {
2458 return bus_remove_object(bus, true, prefix, callback, userdata);
2459}