chiark / gitweb /
hashmap: introduce hash_ops to make struct Hashmap smaller
[elogind.git] / src / libsystemd / sd-bus / bus-objects.c
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 <sys/capability.h>
23
24 #include "strv.h"
25 #include "set.h"
26 #include "bus-internal.h"
27 #include "bus-message.h"
28 #include "bus-type.h"
29 #include "bus-signature.h"
30 #include "bus-introspect.h"
31 #include "bus-util.h"
32 #include "bus-slot.h"
33 #include "bus-objects.h"
34
35 static int node_vtable_get_userdata(
36                 sd_bus *bus,
37                 const char *path,
38                 struct node_vtable *c,
39                 void **userdata,
40                 sd_bus_error *error) {
41
42         sd_bus_slot *s;
43         void *u;
44         int r;
45
46         assert(bus);
47         assert(path);
48         assert(c);
49
50         s = container_of(c, sd_bus_slot, node_vtable);
51         u = s->userdata;
52         if (c->find) {
53                 bus->current_slot = sd_bus_slot_ref(s);
54                 bus->current_userdata = u;
55                 r = c->find(bus, path, c->interface, u, &u, error);
56                 bus->current_userdata = NULL;
57                 bus->current_slot = sd_bus_slot_unref(s);
58
59                 if (r < 0)
60                         return r;
61                 if (sd_bus_error_is_set(error))
62                         return -sd_bus_error_get_errno(error);
63                 if (r == 0)
64                         return r;
65         }
66
67         if (userdata)
68                 *userdata = u;
69
70         return 1;
71 }
72
73 static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
74         assert(p);
75
76         return (uint8_t*) u + p->x.property.offset;
77 }
78
79 static int vtable_property_get_userdata(
80                 sd_bus *bus,
81                 const char *path,
82                 struct vtable_member *p,
83                 void **userdata,
84                 sd_bus_error *error) {
85
86         void *u;
87         int r;
88
89         assert(bus);
90         assert(path);
91         assert(p);
92         assert(userdata);
93
94         r = node_vtable_get_userdata(bus, path, p->parent, &u, error);
95         if (r <= 0)
96                 return r;
97         if (bus->nodes_modified)
98                 return 0;
99
100         *userdata = vtable_property_convert_userdata(p->vtable, u);
101         return 1;
102 }
103
104 static int add_enumerated_to_set(
105                 sd_bus *bus,
106                 const char *prefix,
107                 struct node_enumerator *first,
108                 Set *s,
109                 sd_bus_error *error) {
110
111         struct node_enumerator *c;
112         int r;
113
114         assert(bus);
115         assert(prefix);
116         assert(s);
117
118         LIST_FOREACH(enumerators, c, first) {
119                 char **children = NULL, **k;
120                 sd_bus_slot *slot;
121
122                 if (bus->nodes_modified)
123                         return 0;
124
125                 slot = container_of(c, sd_bus_slot, node_enumerator);
126
127                 bus->current_slot = sd_bus_slot_ref(slot);
128                 bus->current_userdata = slot->userdata;
129                 r = c->callback(bus, prefix, slot->userdata, &children, error);
130                 bus->current_userdata = NULL;
131                 bus->current_slot = sd_bus_slot_unref(slot);
132
133                 if (r < 0)
134                         return r;
135                 if (sd_bus_error_is_set(error))
136                         return -sd_bus_error_get_errno(error);
137
138                 STRV_FOREACH(k, children) {
139                         if (r < 0) {
140                                 free(*k);
141                                 continue;
142                         }
143
144                         if (!object_path_is_valid(*k)){
145                                 free(*k);
146                                 r = -EINVAL;
147                                 continue;
148                         }
149
150                         if (!object_path_startswith(*k, prefix)) {
151                                 free(*k);
152                                 continue;
153                         }
154
155                         r = set_consume(s, *k);
156                         if (r == -EEXIST)
157                                 r = 0;
158                 }
159
160                 free(children);
161                 if (r < 0)
162                         return r;
163         }
164
165         return 0;
166 }
167
168 static int add_subtree_to_set(
169                 sd_bus *bus,
170                 const char *prefix,
171                 struct node *n,
172                 Set *s,
173                 sd_bus_error *error) {
174
175         struct node *i;
176         int r;
177
178         assert(bus);
179         assert(prefix);
180         assert(n);
181         assert(s);
182
183         r = add_enumerated_to_set(bus, prefix, n->enumerators, s, error);
184         if (r < 0)
185                 return r;
186         if (bus->nodes_modified)
187                 return 0;
188
189         LIST_FOREACH(siblings, i, n->child) {
190                 char *t;
191
192                 if (!object_path_startswith(i->path, prefix))
193                         continue;
194
195                 t = strdup(i->path);
196                 if (!t)
197                         return -ENOMEM;
198
199                 r = set_consume(s, t);
200                 if (r < 0 && r != -EEXIST)
201                         return r;
202
203                 r = add_subtree_to_set(bus, prefix, i, s, error);
204                 if (r < 0)
205                         return r;
206                 if (bus->nodes_modified)
207                         return 0;
208         }
209
210         return 0;
211 }
212
213 static int get_child_nodes(
214                 sd_bus *bus,
215                 const char *prefix,
216                 struct node *n,
217                 Set **_s,
218                 sd_bus_error *error) {
219
220         Set *s = NULL;
221         int r;
222
223         assert(bus);
224         assert(prefix);
225         assert(n);
226         assert(_s);
227
228         s = set_new(&string_hash_ops);
229         if (!s)
230                 return -ENOMEM;
231
232         r = add_subtree_to_set(bus, prefix, n, s, error);
233         if (r < 0) {
234                 set_free_free(s);
235                 return r;
236         }
237
238         *_s = s;
239         return 0;
240 }
241
242 static int node_callbacks_run(
243                 sd_bus *bus,
244                 sd_bus_message *m,
245                 struct node_callback *first,
246                 bool require_fallback,
247                 bool *found_object) {
248
249         struct node_callback *c;
250         int r;
251
252         assert(bus);
253         assert(m);
254         assert(found_object);
255
256         LIST_FOREACH(callbacks, c, first) {
257                 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
258                 sd_bus_slot *slot;
259
260                 if (bus->nodes_modified)
261                         return 0;
262
263                 if (require_fallback && !c->is_fallback)
264                         continue;
265
266                 *found_object = true;
267
268                 if (c->last_iteration == bus->iteration_counter)
269                         continue;
270
271                 c->last_iteration = bus->iteration_counter;
272
273                 r = sd_bus_message_rewind(m, true);
274                 if (r < 0)
275                         return r;
276
277                 slot = container_of(c, sd_bus_slot, node_callback);
278
279                 bus->current_slot = sd_bus_slot_ref(slot);
280                 bus->current_handler = c->callback;
281                 bus->current_userdata = slot->userdata;
282                 r = c->callback(bus, m, slot->userdata, &error_buffer);
283                 bus->current_userdata = NULL;
284                 bus->current_handler = NULL;
285                 bus->current_slot = sd_bus_slot_unref(slot);
286
287                 r = bus_maybe_reply_error(m, r, &error_buffer);
288                 if (r != 0)
289                         return r;
290         }
291
292         return 0;
293 }
294
295 #define CAPABILITY_SHIFT(x) (((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF)
296
297 static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) {
298         uint64_t cap;
299         int r;
300
301         assert(bus);
302         assert(m);
303         assert(c);
304
305         /* If the entire bus is trusted let's grant access */
306         if (bus->trusted)
307                 return 0;
308
309         /* If the member is marked UNPRIVILEGED let's grant access */
310         if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED)
311                 return 0;
312
313         /* Check have the caller has the requested capability
314          * set. Note that the flags value contains the capability
315          * number plus one, which we need to subtract here. We do this
316          * so that we have 0 as special value for "default
317          * capability". */
318         cap = CAPABILITY_SHIFT(c->vtable->flags);
319         if (cap == 0)
320                 cap = CAPABILITY_SHIFT(c->parent->vtable[0].flags);
321         if (cap == 0)
322                 cap = CAP_SYS_ADMIN;
323         else
324                 cap --;
325
326         r = sd_bus_query_sender_privilege(m, cap);
327         if (r < 0)
328                 return r;
329         if (r > 0)
330                 return 0;
331
332         return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member);
333 }
334
335 static int method_callbacks_run(
336                 sd_bus *bus,
337                 sd_bus_message *m,
338                 struct vtable_member *c,
339                 bool require_fallback,
340                 bool *found_object) {
341
342         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
343         const char *signature;
344         void *u;
345         int r;
346
347         assert(bus);
348         assert(m);
349         assert(c);
350         assert(found_object);
351
352         if (require_fallback && !c->parent->is_fallback)
353                 return 0;
354
355         r = check_access(bus, m, c, &error);
356         if (r < 0)
357                 return bus_maybe_reply_error(m, r, &error);
358
359         r = node_vtable_get_userdata(bus, m->path, c->parent, &u, &error);
360         if (r <= 0)
361                 return bus_maybe_reply_error(m, r, &error);
362         if (bus->nodes_modified)
363                 return 0;
364
365         *found_object = true;
366
367         if (c->last_iteration == bus->iteration_counter)
368                 return 0;
369
370         c->last_iteration = bus->iteration_counter;
371
372         r = sd_bus_message_rewind(m, true);
373         if (r < 0)
374                 return r;
375
376         signature = sd_bus_message_get_signature(m, true);
377         if (!signature)
378                 return -EINVAL;
379
380         if (!streq(strempty(c->vtable->x.method.signature), signature))
381                 return sd_bus_reply_method_errorf(
382                                 m,
383                                 SD_BUS_ERROR_INVALID_ARGS,
384                                 "Invalid arguments '%s' to call %s.%s(), expecting '%s'.",
385                                 signature, c->interface, c->member, strempty(c->vtable->x.method.signature));
386
387         /* Keep track what the signature of the reply to this message
388          * should be, so that this can be enforced when sealing the
389          * reply. */
390         m->enforced_reply_signature = strempty(c->vtable->x.method.result);
391
392         if (c->vtable->x.method.handler) {
393                 sd_bus_slot *slot;
394
395                 slot = container_of(c->parent, sd_bus_slot, node_vtable);
396
397                 bus->current_slot = sd_bus_slot_ref(slot);
398                 bus->current_handler = c->vtable->x.method.handler;
399                 bus->current_userdata = u;
400                 r = c->vtable->x.method.handler(bus, m, u, &error);
401                 bus->current_userdata = NULL;
402                 bus->current_handler = NULL;
403                 bus->current_slot = sd_bus_slot_unref(slot);
404
405                 return bus_maybe_reply_error(m, r, &error);
406         }
407
408         /* If the method callback is NULL, make this a successful NOP */
409         r = sd_bus_reply_method_return(m, NULL);
410         if (r < 0)
411                 return r;
412
413         return 1;
414 }
415
416 static int invoke_property_get(
417                 sd_bus *bus,
418                 sd_bus_slot *slot,
419                 const sd_bus_vtable *v,
420                 const char *path,
421                 const char *interface,
422                 const char *property,
423                 sd_bus_message *reply,
424                 void *userdata,
425                 sd_bus_error *error) {
426
427         const void *p;
428         int r;
429
430         assert(bus);
431         assert(slot);
432         assert(v);
433         assert(path);
434         assert(interface);
435         assert(property);
436         assert(reply);
437
438         if (v->x.property.get) {
439
440                 bus->current_slot = sd_bus_slot_ref(slot);
441                 bus->current_userdata = userdata;
442                 r = v->x.property.get(bus, path, interface, property, reply, userdata, error);
443                 bus->current_userdata = NULL;
444                 bus->current_slot = sd_bus_slot_unref(slot);
445
446                 if (r < 0)
447                         return r;
448                 if (sd_bus_error_is_set(error))
449                         return -sd_bus_error_get_errno(error);
450                 return r;
451         }
452
453         /* Automatic handling if no callback is defined. */
454
455         if (streq(v->x.property.signature, "as"))
456                 return sd_bus_message_append_strv(reply, *(char***) userdata);
457
458         assert(signature_is_single(v->x.property.signature, false));
459         assert(bus_type_is_basic(v->x.property.signature[0]));
460
461         switch (v->x.property.signature[0]) {
462
463         case SD_BUS_TYPE_STRING:
464         case SD_BUS_TYPE_SIGNATURE:
465                 p = strempty(*(char**) userdata);
466                 break;
467
468         case SD_BUS_TYPE_OBJECT_PATH:
469                 p = *(char**) userdata;
470                 assert(p);
471                 break;
472
473         default:
474                 p = userdata;
475                 break;
476         }
477
478         return sd_bus_message_append_basic(reply, v->x.property.signature[0], p);
479 }
480
481 static int invoke_property_set(
482                 sd_bus *bus,
483                 sd_bus_slot *slot,
484                 const sd_bus_vtable *v,
485                 const char *path,
486                 const char *interface,
487                 const char *property,
488                 sd_bus_message *value,
489                 void *userdata,
490                 sd_bus_error *error) {
491
492         int r;
493
494         assert(bus);
495         assert(slot);
496         assert(v);
497         assert(path);
498         assert(interface);
499         assert(property);
500         assert(value);
501
502         if (v->x.property.set) {
503
504                 bus->current_slot = sd_bus_slot_ref(slot);
505                 bus->current_userdata = userdata;
506                 r = v->x.property.set(bus, path, interface, property, value, userdata, error);
507                 bus->current_userdata = NULL;
508                 bus->current_slot = sd_bus_slot_unref(slot);
509
510                 if (r < 0)
511                         return r;
512                 if (sd_bus_error_is_set(error))
513                         return -sd_bus_error_get_errno(error);
514                 return r;
515         }
516
517         /*  Automatic handling if no callback is defined. */
518
519         assert(signature_is_single(v->x.property.signature, false));
520         assert(bus_type_is_basic(v->x.property.signature[0]));
521
522         switch (v->x.property.signature[0]) {
523
524         case SD_BUS_TYPE_STRING:
525         case SD_BUS_TYPE_OBJECT_PATH:
526         case SD_BUS_TYPE_SIGNATURE: {
527                 const char *p;
528                 char *n;
529
530                 r = sd_bus_message_read_basic(value, v->x.property.signature[0], &p);
531                 if (r < 0)
532                         return r;
533
534                 n = strdup(p);
535                 if (!n)
536                         return -ENOMEM;
537
538                 free(*(char**) userdata);
539                 *(char**) userdata = n;
540
541                 break;
542         }
543
544         default:
545                 r = sd_bus_message_read_basic(value, v->x.property.signature[0], userdata);
546                 if (r < 0)
547                         return r;
548
549                 break;
550         }
551
552         return 1;
553 }
554
555 static int property_get_set_callbacks_run(
556                 sd_bus *bus,
557                 sd_bus_message *m,
558                 struct vtable_member *c,
559                 bool require_fallback,
560                 bool is_get,
561                 bool *found_object) {
562
563         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
564         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
565         sd_bus_slot *slot;
566         void *u = NULL;
567         int r;
568
569         assert(bus);
570         assert(m);
571         assert(c);
572         assert(found_object);
573
574         if (require_fallback && !c->parent->is_fallback)
575                 return 0;
576
577         r = vtable_property_get_userdata(bus, m->path, c, &u, &error);
578         if (r <= 0)
579                 return bus_maybe_reply_error(m, r, &error);
580         if (bus->nodes_modified)
581                 return 0;
582
583         slot = container_of(c->parent, sd_bus_slot, node_vtable);
584
585         *found_object = true;
586
587         r = sd_bus_message_new_method_return(m, &reply);
588         if (r < 0)
589                 return r;
590
591         if (is_get) {
592                 /* Note that we do not protect against reexecution
593                  * here (using the last_iteration check, see below),
594                  * should the node tree have changed and we got called
595                  * again. We assume that property Get() calls are
596                  * ultimately without side-effects or if they aren't
597                  * then at least idempotent. */
598
599                 r = sd_bus_message_open_container(reply, 'v', c->vtable->x.property.signature);
600                 if (r < 0)
601                         return r;
602
603                 /* Note that we do not do an access check here. Read
604                  * access to properties is always unrestricted, since
605                  * PropertiesChanged signals broadcast contents
606                  * anyway. */
607
608                 r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error);
609                 if (r < 0)
610                         return bus_maybe_reply_error(m, r, &error);
611
612                 if (bus->nodes_modified)
613                         return 0;
614
615                 r = sd_bus_message_close_container(reply);
616                 if (r < 0)
617                         return r;
618
619         } else {
620                 if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
621                         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member);
622
623                 /* Avoid that we call the set routine more than once
624                  * if the processing of this message got restarted
625                  * because the node tree changed. */
626                 if (c->last_iteration == bus->iteration_counter)
627                         return 0;
628
629                 c->last_iteration = bus->iteration_counter;
630
631                 r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
632                 if (r < 0)
633                         return r;
634
635                 r = check_access(bus, m, c, &error);
636                 if (r < 0)
637                         return bus_maybe_reply_error(m, r, &error);
638
639                 r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error);
640                 if (r < 0)
641                         return bus_maybe_reply_error(m, r, &error);
642
643                 if (bus->nodes_modified)
644                         return 0;
645
646                 r = sd_bus_message_exit_container(m);
647                 if (r < 0)
648                         return r;
649         }
650
651         r = sd_bus_send(bus, reply, NULL);
652         if (r < 0)
653                 return r;
654
655         return 1;
656 }
657
658 static int vtable_append_one_property(
659                 sd_bus *bus,
660                 sd_bus_message *reply,
661                 const char *path,
662                 struct node_vtable *c,
663                 const sd_bus_vtable *v,
664                 void *userdata,
665                 sd_bus_error *error) {
666
667         sd_bus_slot *slot;
668         int r;
669
670         assert(bus);
671         assert(reply);
672         assert(path);
673         assert(c);
674         assert(v);
675
676         r = sd_bus_message_open_container(reply, 'e', "sv");
677         if (r < 0)
678                 return r;
679
680         r = sd_bus_message_append(reply, "s", v->x.property.member);
681         if (r < 0)
682                 return r;
683
684         r = sd_bus_message_open_container(reply, 'v', v->x.property.signature);
685         if (r < 0)
686                 return r;
687
688         slot = container_of(c, sd_bus_slot, node_vtable);
689
690         r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
691         if (r < 0)
692                 return r;
693         if (bus->nodes_modified)
694                 return 0;
695
696         r = sd_bus_message_close_container(reply);
697         if (r < 0)
698                 return r;
699
700         r = sd_bus_message_close_container(reply);
701         if (r < 0)
702                 return r;
703
704         return 0;
705 }
706
707 static int vtable_append_all_properties(
708                 sd_bus *bus,
709                 sd_bus_message *reply,
710                 const char *path,
711                 struct node_vtable *c,
712                 void *userdata,
713                 sd_bus_error *error) {
714
715         const sd_bus_vtable *v;
716         int r;
717
718         assert(bus);
719         assert(reply);
720         assert(path);
721         assert(c);
722
723         if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
724                 return 1;
725
726         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
727                 if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
728                         continue;
729
730                 if (v->flags & SD_BUS_VTABLE_HIDDEN)
731                         continue;
732
733                 r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
734                 if (r < 0)
735                         return r;
736                 if (bus->nodes_modified)
737                         return 0;
738         }
739
740         return 1;
741 }
742
743 static int property_get_all_callbacks_run(
744                 sd_bus *bus,
745                 sd_bus_message *m,
746                 struct node_vtable *first,
747                 bool require_fallback,
748                 const char *iface,
749                 bool *found_object) {
750
751         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
752         struct node_vtable *c;
753         bool found_interface;
754         int r;
755
756         assert(bus);
757         assert(m);
758         assert(found_object);
759
760         r = sd_bus_message_new_method_return(m, &reply);
761         if (r < 0)
762                 return r;
763
764         r = sd_bus_message_open_container(reply, 'a', "{sv}");
765         if (r < 0)
766                 return r;
767
768         found_interface = !iface ||
769                 streq(iface, "org.freedesktop.DBus.Properties") ||
770                 streq(iface, "org.freedesktop.DBus.Peer") ||
771                 streq(iface, "org.freedesktop.DBus.Introspectable");
772
773         LIST_FOREACH(vtables, c, first) {
774                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
775                 void *u;
776
777                 if (require_fallback && !c->is_fallback)
778                         continue;
779
780                 r = node_vtable_get_userdata(bus, m->path, c, &u, &error);
781                 if (r < 0)
782                         return bus_maybe_reply_error(m, r, &error);
783                 if (bus->nodes_modified)
784                         return 0;
785                 if (r == 0)
786                         continue;
787
788                 *found_object = true;
789
790                 if (iface && !streq(c->interface, iface))
791                         continue;
792                 found_interface = true;
793
794                 r = vtable_append_all_properties(bus, reply, m->path, c, u, &error);
795                 if (r < 0)
796                         return bus_maybe_reply_error(m, r, &error);
797                 if (bus->nodes_modified)
798                         return 0;
799         }
800
801         if (!found_interface) {
802                 r = sd_bus_reply_method_errorf(
803                                 m,
804                                 SD_BUS_ERROR_UNKNOWN_INTERFACE,
805                                 "Unknown interface '%s'.", iface);
806                 if (r < 0)
807                         return r;
808
809                 return 1;
810         }
811
812         r = sd_bus_message_close_container(reply);
813         if (r < 0)
814                 return r;
815
816         r = sd_bus_send(bus, reply, NULL);
817         if (r < 0)
818                 return r;
819
820         return 1;
821 }
822
823 static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
824         assert(bus);
825         assert(n);
826
827         if (n->object_managers)
828                 return true;
829
830         if (n->parent)
831                 return bus_node_with_object_manager(bus, n->parent);
832
833         return false;
834 }
835
836 static bool bus_node_exists(
837                 sd_bus *bus,
838                 struct node *n,
839                 const char *path,
840                 bool require_fallback) {
841
842         struct node_vtable *c;
843         struct node_callback *k;
844
845         assert(bus);
846         assert(n);
847         assert(path);
848
849         /* Tests if there's anything attached directly to this node
850          * for the specified path */
851
852         LIST_FOREACH(callbacks, k, n->callbacks) {
853                 if (require_fallback && !k->is_fallback)
854                         continue;
855
856                 return true;
857         }
858
859         LIST_FOREACH(vtables, c, n->vtables) {
860                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
861
862                 if (require_fallback && !c->is_fallback)
863                         continue;
864
865                 if (node_vtable_get_userdata(bus, path, c, NULL, &error) > 0)
866                         return true;
867                 if (bus->nodes_modified)
868                         return false;
869         }
870
871         return !require_fallback && (n->enumerators || n->object_managers);
872 }
873
874 static int process_introspect(
875                 sd_bus *bus,
876                 sd_bus_message *m,
877                 struct node *n,
878                 bool require_fallback,
879                 bool *found_object) {
880
881         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
882         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
883         _cleanup_set_free_free_ Set *s = NULL;
884         const char *previous_interface = NULL;
885         struct introspect intro;
886         struct node_vtable *c;
887         bool empty;
888         int r;
889
890         assert(bus);
891         assert(m);
892         assert(n);
893         assert(found_object);
894
895         r = get_child_nodes(bus, m->path, n, &s, &error);
896         if (r < 0)
897                 return bus_maybe_reply_error(m, r, &error);
898         if (bus->nodes_modified)
899                 return 0;
900
901         r = introspect_begin(&intro, bus->trusted);
902         if (r < 0)
903                 return r;
904
905         r = introspect_write_default_interfaces(&intro, bus_node_with_object_manager(bus, n));
906         if (r < 0)
907                 return r;
908
909         empty = set_isempty(s);
910
911         LIST_FOREACH(vtables, c, n->vtables) {
912                 if (require_fallback && !c->is_fallback)
913                         continue;
914
915                 r = node_vtable_get_userdata(bus, m->path, c, NULL, &error);
916                 if (r < 0) {
917                         r = bus_maybe_reply_error(m, r, &error);
918                         goto finish;
919                 }
920                 if (bus->nodes_modified) {
921                         r = 0;
922                         goto finish;
923                 }
924                 if (r == 0)
925                         continue;
926
927                 empty = false;
928
929                 if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
930                         continue;
931
932                 if (!streq_ptr(previous_interface, c->interface)) {
933
934                         if (previous_interface)
935                                 fputs(" </interface>\n", intro.f);
936
937                         fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
938                 }
939
940                 r = introspect_write_interface(&intro, c->vtable);
941                 if (r < 0)
942                         goto finish;
943
944                 previous_interface = c->interface;
945         }
946
947         if (previous_interface)
948                 fputs(" </interface>\n", intro.f);
949
950         if (empty) {
951                 /* Nothing?, let's see if we exist at all, and if not
952                  * refuse to do anything */
953                 r = bus_node_exists(bus, n, m->path, require_fallback);
954                 if (r < 0)
955                         return r;
956                 if (bus->nodes_modified)
957                         return 0;
958                 if (r == 0)
959                         goto finish;
960         }
961
962         *found_object = true;
963
964         r = introspect_write_child_nodes(&intro, s, m->path);
965         if (r < 0)
966                 goto finish;
967
968         r = introspect_finish(&intro, bus, m, &reply);
969         if (r < 0)
970                 goto finish;
971
972         r = sd_bus_send(bus, reply, NULL);
973         if (r < 0)
974                 goto finish;
975
976         r = 1;
977
978 finish:
979         introspect_free(&intro);
980         return r;
981 }
982
983 static int object_manager_serialize_path(
984                 sd_bus *bus,
985                 sd_bus_message *reply,
986                 const char *prefix,
987                 const char *path,
988                 bool require_fallback,
989                 sd_bus_error *error) {
990
991         const char *previous_interface = NULL;
992         bool found_something = false;
993         struct node_vtable *i;
994         struct node *n;
995         int r;
996
997         assert(bus);
998         assert(reply);
999         assert(prefix);
1000         assert(path);
1001         assert(error);
1002
1003         n = hashmap_get(bus->nodes, prefix);
1004         if (!n)
1005                 return 0;
1006
1007         LIST_FOREACH(vtables, i, n->vtables) {
1008                 void *u;
1009
1010                 if (require_fallback && !i->is_fallback)
1011                         continue;
1012
1013                 r = node_vtable_get_userdata(bus, path, i, &u, error);
1014                 if (r < 0)
1015                         return r;
1016                 if (bus->nodes_modified)
1017                         return 0;
1018                 if (r == 0)
1019                         continue;
1020
1021                 if (!found_something) {
1022
1023                         /* Open the object part */
1024
1025                         r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
1026                         if (r < 0)
1027                                 return r;
1028
1029                         r = sd_bus_message_append(reply, "o", path);
1030                         if (r < 0)
1031                                 return r;
1032
1033                         r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
1034                         if (r < 0)
1035                                 return r;
1036
1037                         found_something = true;
1038                 }
1039
1040                 if (!streq_ptr(previous_interface, i->interface)) {
1041
1042                         /* Maybe close the previous interface part */
1043
1044                         if (previous_interface) {
1045                                 r = sd_bus_message_close_container(reply);
1046                                 if (r < 0)
1047                                         return r;
1048
1049                                 r = sd_bus_message_close_container(reply);
1050                                 if (r < 0)
1051                                         return r;
1052                         }
1053
1054                         /* Open the new interface part */
1055
1056                         r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
1057                         if (r < 0)
1058                                 return r;
1059
1060                         r = sd_bus_message_append(reply, "s", i->interface);
1061                         if (r < 0)
1062                                 return r;
1063
1064                         r = sd_bus_message_open_container(reply, 'a', "{sv}");
1065                         if (r < 0)
1066                                 return r;
1067                 }
1068
1069                 r = vtable_append_all_properties(bus, reply, path, i, u, error);
1070                 if (r < 0)
1071                         return r;
1072                 if (bus->nodes_modified)
1073                         return 0;
1074
1075                 previous_interface = i->interface;
1076         }
1077
1078         if (previous_interface) {
1079                 r = sd_bus_message_close_container(reply);
1080                 if (r < 0)
1081                         return r;
1082
1083                 r = sd_bus_message_close_container(reply);
1084                 if (r < 0)
1085                         return r;
1086         }
1087
1088         if (found_something) {
1089                 r = sd_bus_message_close_container(reply);
1090                 if (r < 0)
1091                         return r;
1092
1093                 r = sd_bus_message_close_container(reply);
1094                 if (r < 0)
1095                         return r;
1096         }
1097
1098         return 1;
1099 }
1100
1101 static int object_manager_serialize_path_and_fallbacks(
1102                 sd_bus *bus,
1103                 sd_bus_message *reply,
1104                 const char *path,
1105                 sd_bus_error *error) {
1106
1107         char *prefix;
1108         int r;
1109
1110         assert(bus);
1111         assert(reply);
1112         assert(path);
1113         assert(error);
1114
1115         /* First, add all vtables registered for this path */
1116         r = object_manager_serialize_path(bus, reply, path, path, false, error);
1117         if (r < 0)
1118                 return r;
1119         if (bus->nodes_modified)
1120                 return 0;
1121
1122         /* Second, add fallback vtables registered for any of the prefixes */
1123         prefix = alloca(strlen(path) + 1);
1124         OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
1125                 r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
1126                 if (r < 0)
1127                         return r;
1128                 if (bus->nodes_modified)
1129                         return 0;
1130         }
1131
1132         return 0;
1133 }
1134
1135 static int process_get_managed_objects(
1136                 sd_bus *bus,
1137                 sd_bus_message *m,
1138                 struct node *n,
1139                 bool require_fallback,
1140                 bool *found_object) {
1141
1142         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1143         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1144         _cleanup_set_free_free_ Set *s = NULL;
1145         bool empty;
1146         int r;
1147
1148         assert(bus);
1149         assert(m);
1150         assert(n);
1151         assert(found_object);
1152
1153         if (!bus_node_with_object_manager(bus, n))
1154                 return 0;
1155
1156         r = get_child_nodes(bus, m->path, n, &s, &error);
1157         if (r < 0)
1158                 return r;
1159         if (bus->nodes_modified)
1160                 return 0;
1161
1162         r = sd_bus_message_new_method_return(m, &reply);
1163         if (r < 0)
1164                 return r;
1165
1166         r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}");
1167         if (r < 0)
1168                 return r;
1169
1170         empty = set_isempty(s);
1171         if (empty) {
1172                 struct node_vtable *c;
1173
1174                 /* Hmm, so we have no children? Then let's check
1175                  * whether we exist at all, i.e. whether at least one
1176                  * vtable exists. */
1177
1178                 LIST_FOREACH(vtables, c, n->vtables) {
1179
1180                         if (require_fallback && !c->is_fallback)
1181                                 continue;
1182
1183                         if (r < 0)
1184                                 return r;
1185                         if (r == 0)
1186                                 continue;
1187
1188                         empty = false;
1189                         break;
1190                 }
1191
1192                 if (empty)
1193                         return 0;
1194         } else {
1195                 Iterator i;
1196                 char *path;
1197
1198                 SET_FOREACH(path, s, i) {
1199                         r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
1200                         if (r < 0)
1201                                 return r;
1202
1203                         if (bus->nodes_modified)
1204                                 return 0;
1205                 }
1206         }
1207
1208         r = sd_bus_message_close_container(reply);
1209         if (r < 0)
1210                 return r;
1211
1212         r = sd_bus_send(bus, reply, NULL);
1213         if (r < 0)
1214                 return r;
1215
1216         return 1;
1217 }
1218
1219 static int object_find_and_run(
1220                 sd_bus *bus,
1221                 sd_bus_message *m,
1222                 const char *p,
1223                 bool require_fallback,
1224                 bool *found_object) {
1225
1226         struct node *n;
1227         struct vtable_member vtable_key, *v;
1228         int r;
1229
1230         assert(bus);
1231         assert(m);
1232         assert(p);
1233         assert(found_object);
1234
1235         n = hashmap_get(bus->nodes, p);
1236         if (!n)
1237                 return 0;
1238
1239         /* First, try object callbacks */
1240         r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object);
1241         if (r != 0)
1242                 return r;
1243         if (bus->nodes_modified)
1244                 return 0;
1245
1246         if (!m->interface || !m->member)
1247                 return 0;
1248
1249         /* Then, look for a known method */
1250         vtable_key.path = (char*) p;
1251         vtable_key.interface = m->interface;
1252         vtable_key.member = m->member;
1253
1254         v = hashmap_get(bus->vtable_methods, &vtable_key);
1255         if (v) {
1256                 r = method_callbacks_run(bus, m, v, require_fallback, found_object);
1257                 if (r != 0)
1258                         return r;
1259                 if (bus->nodes_modified)
1260                         return 0;
1261         }
1262
1263         /* Then, look for a known property */
1264         if (streq(m->interface, "org.freedesktop.DBus.Properties")) {
1265                 bool get = false;
1266
1267                 get = streq(m->member, "Get");
1268
1269                 if (get || streq(m->member, "Set")) {
1270
1271                         r = sd_bus_message_rewind(m, true);
1272                         if (r < 0)
1273                                 return r;
1274
1275                         vtable_key.path = (char*) p;
1276
1277                         r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member);
1278                         if (r < 0)
1279                                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface and member parameters");
1280
1281                         v = hashmap_get(bus->vtable_properties, &vtable_key);
1282                         if (v) {
1283                                 r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object);
1284                                 if (r != 0)
1285                                         return r;
1286                         }
1287
1288                 } else if (streq(m->member, "GetAll")) {
1289                         const char *iface;
1290
1291                         r = sd_bus_message_rewind(m, true);
1292                         if (r < 0)
1293                                 return r;
1294
1295                         r = sd_bus_message_read(m, "s", &iface);
1296                         if (r < 0)
1297                                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface parameter");
1298
1299                         if (iface[0] == 0)
1300                                 iface = NULL;
1301
1302                         r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object);
1303                         if (r != 0)
1304                                 return r;
1305                 }
1306
1307         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1308
1309                 if (!isempty(sd_bus_message_get_signature(m, true)))
1310                         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
1311
1312                 r = process_introspect(bus, m, n, require_fallback, found_object);
1313                 if (r != 0)
1314                         return r;
1315
1316         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
1317
1318                 if (!isempty(sd_bus_message_get_signature(m, true)))
1319                         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
1320
1321                 r = process_get_managed_objects(bus, m, n, require_fallback, found_object);
1322                 if (r != 0)
1323                         return r;
1324         }
1325
1326         if (bus->nodes_modified)
1327                 return 0;
1328
1329         if (!*found_object) {
1330                 r = bus_node_exists(bus, n, m->path, require_fallback);
1331                 if (r < 0)
1332                         return r;
1333                 if (r > 0)
1334                         *found_object = true;
1335         }
1336
1337         return 0;
1338 }
1339
1340 int bus_process_object(sd_bus *bus, sd_bus_message *m) {
1341         int r;
1342         size_t pl;
1343         bool found_object = false;
1344
1345         assert(bus);
1346         assert(m);
1347
1348         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1349                 return 0;
1350
1351         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1352                 return 0;
1353
1354         if (hashmap_isempty(bus->nodes))
1355                 return 0;
1356
1357         /* Never respond to broadcast messages */
1358         if (bus->bus_client && !m->destination)
1359                 return 0;
1360
1361         assert(m->path);
1362         assert(m->member);
1363
1364         pl = strlen(m->path);
1365         do {
1366                 char prefix[pl+1];
1367
1368                 bus->nodes_modified = false;
1369
1370                 r = object_find_and_run(bus, m, m->path, false, &found_object);
1371                 if (r != 0)
1372                         return r;
1373
1374                 /* Look for fallback prefixes */
1375                 OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) {
1376
1377                         if (bus->nodes_modified)
1378                                 break;
1379
1380                         r = object_find_and_run(bus, m, prefix, true, &found_object);
1381                         if (r != 0)
1382                                 return r;
1383                 }
1384
1385         } while (bus->nodes_modified);
1386
1387         if (!found_object)
1388                 return 0;
1389
1390         if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
1391             sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
1392                 r = sd_bus_reply_method_errorf(
1393                                 m,
1394                                 SD_BUS_ERROR_UNKNOWN_PROPERTY,
1395                                 "Unknown property or interface.");
1396         else
1397                 r = sd_bus_reply_method_errorf(
1398                                 m,
1399                                 SD_BUS_ERROR_UNKNOWN_METHOD,
1400                                 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
1401
1402         if (r < 0)
1403                 return r;
1404
1405         return 1;
1406 }
1407
1408 static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
1409         struct node *n, *parent;
1410         const char *e;
1411         _cleanup_free_ char *s = NULL;
1412         char *p;
1413         int r;
1414
1415         assert(bus);
1416         assert(path);
1417         assert(path[0] == '/');
1418
1419         n = hashmap_get(bus->nodes, path);
1420         if (n)
1421                 return n;
1422
1423         r = hashmap_ensure_allocated(&bus->nodes, &string_hash_ops);
1424         if (r < 0)
1425                 return NULL;
1426
1427         s = strdup(path);
1428         if (!s)
1429                 return NULL;
1430
1431         if (streq(path, "/"))
1432                 parent = NULL;
1433         else {
1434                 e = strrchr(path, '/');
1435                 assert(e);
1436
1437                 p = strndupa(path, MAX(1, path - e));
1438
1439                 parent = bus_node_allocate(bus, p);
1440                 if (!parent)
1441                         return NULL;
1442         }
1443
1444         n = new0(struct node, 1);
1445         if (!n)
1446                 return NULL;
1447
1448         n->parent = parent;
1449         n->path = s;
1450         s = NULL; /* do not free */
1451
1452         r = hashmap_put(bus->nodes, n->path, n);
1453         if (r < 0) {
1454                 free(n->path);
1455                 free(n);
1456                 return NULL;
1457         }
1458
1459         if (parent)
1460                 LIST_PREPEND(siblings, parent->child, n);
1461
1462         return n;
1463 }
1464
1465 void bus_node_gc(sd_bus *b, struct node *n) {
1466         assert(b);
1467
1468         if (!n)
1469                 return;
1470
1471         if (n->child ||
1472             n->callbacks ||
1473             n->vtables ||
1474             n->enumerators ||
1475             n->object_managers)
1476                 return;
1477
1478         assert(hashmap_remove(b->nodes, n->path) == n);
1479
1480         if (n->parent)
1481                 LIST_REMOVE(siblings, n->parent->child, n);
1482
1483         free(n->path);
1484         bus_node_gc(b, n->parent);
1485         free(n);
1486 }
1487
1488 static int bus_add_object(
1489                 sd_bus *bus,
1490                 sd_bus_slot **slot,
1491                 bool fallback,
1492                 const char *path,
1493                 sd_bus_message_handler_t callback,
1494                 void *userdata) {
1495
1496         sd_bus_slot *s;
1497         struct node *n;
1498         int r;
1499
1500         assert_return(bus, -EINVAL);
1501         assert_return(object_path_is_valid(path), -EINVAL);
1502         assert_return(callback, -EINVAL);
1503         assert_return(!bus_pid_changed(bus), -ECHILD);
1504
1505         n = bus_node_allocate(bus, path);
1506         if (!n)
1507                 return -ENOMEM;
1508
1509         s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata);
1510         if (!s) {
1511                 r = -ENOMEM;
1512                 goto fail;
1513         }
1514
1515         s->node_callback.callback = callback;
1516         s->node_callback.is_fallback = fallback;
1517
1518         s->node_callback.node = n;
1519         LIST_PREPEND(callbacks, n->callbacks, &s->node_callback);
1520         bus->nodes_modified = true;
1521
1522         if (slot)
1523                 *slot = s;
1524
1525         return 0;
1526
1527 fail:
1528         sd_bus_slot_unref(s);
1529         bus_node_gc(bus, n);
1530
1531         return r;
1532 }
1533
1534 _public_ int sd_bus_add_object(
1535                 sd_bus *bus,
1536                 sd_bus_slot **slot,
1537                 const char *path,
1538                 sd_bus_message_handler_t callback,
1539                 void *userdata) {
1540
1541         return bus_add_object(bus, slot, false, path, callback, userdata);
1542 }
1543
1544 _public_ int sd_bus_add_fallback(
1545                 sd_bus *bus,
1546                 sd_bus_slot **slot,
1547                 const char *prefix,
1548                 sd_bus_message_handler_t callback,
1549                 void *userdata) {
1550
1551         return bus_add_object(bus, slot, true, prefix, callback, userdata);
1552 }
1553
1554 static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
1555         const struct vtable_member *m = a;
1556         uint8_t hash_key2[HASH_KEY_SIZE];
1557         unsigned long ret;
1558
1559         assert(m);
1560
1561         ret = string_hash_func(m->path, hash_key);
1562
1563         /* Use a slightly different hash key for the interface */
1564         memcpy(hash_key2, hash_key, HASH_KEY_SIZE);
1565         hash_key2[0]++;
1566         ret ^= string_hash_func(m->interface, hash_key2);
1567
1568         /* And an even different one for the  member */
1569         hash_key2[0]++;
1570         ret ^= string_hash_func(m->member, hash_key2);
1571
1572         return ret;
1573 }
1574
1575 static int vtable_member_compare_func(const void *a, const void *b) {
1576         const struct vtable_member *x = a, *y = b;
1577         int r;
1578
1579         assert(x);
1580         assert(y);
1581
1582         r = strcmp(x->path, y->path);
1583         if (r != 0)
1584                 return r;
1585
1586         r = strcmp(x->interface, y->interface);
1587         if (r != 0)
1588                 return r;
1589
1590         return strcmp(x->member, y->member);
1591 }
1592
1593 static const struct hash_ops vtable_member_hash_ops = {
1594         .hash = vtable_member_hash_func,
1595         .compare = vtable_member_compare_func
1596 };
1597
1598 static int add_object_vtable_internal(
1599                 sd_bus *bus,
1600                 sd_bus_slot **slot,
1601                 const char *path,
1602                 const char *interface,
1603                 const sd_bus_vtable *vtable,
1604                 bool fallback,
1605                 sd_bus_object_find_t find,
1606                 void *userdata) {
1607
1608         sd_bus_slot *s = NULL;
1609         struct node_vtable *i, *existing = NULL;
1610         const sd_bus_vtable *v;
1611         struct node *n;
1612         int r;
1613
1614         assert_return(bus, -EINVAL);
1615         assert_return(object_path_is_valid(path), -EINVAL);
1616         assert_return(interface_name_is_valid(interface), -EINVAL);
1617         assert_return(vtable, -EINVAL);
1618         assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
1619         assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
1620         assert_return(!bus_pid_changed(bus), -ECHILD);
1621         assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
1622                       !streq(interface, "org.freedesktop.DBus.Introspectable") &&
1623                       !streq(interface, "org.freedesktop.DBus.Peer") &&
1624                       !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL);
1625
1626         r = hashmap_ensure_allocated(&bus->vtable_methods, &vtable_member_hash_ops);
1627         if (r < 0)
1628                 return r;
1629
1630         r = hashmap_ensure_allocated(&bus->vtable_properties, &vtable_member_hash_ops);
1631         if (r < 0)
1632                 return r;
1633
1634         n = bus_node_allocate(bus, path);
1635         if (!n)
1636                 return -ENOMEM;
1637
1638         LIST_FOREACH(vtables, i, n->vtables) {
1639                 if (i->is_fallback != fallback) {
1640                         r = -EPROTOTYPE;
1641                         goto fail;
1642                 }
1643
1644                 if (streq(i->interface, interface)) {
1645
1646                         if (i->vtable == vtable) {
1647                                 r = -EEXIST;
1648                                 goto fail;
1649                         }
1650
1651                         existing = i;
1652                 }
1653         }
1654
1655         s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata);
1656         if (!s) {
1657                 r = -ENOMEM;
1658                 goto fail;
1659         }
1660
1661         s->node_vtable.is_fallback = fallback;
1662         s->node_vtable.vtable = vtable;
1663         s->node_vtable.find = find;
1664
1665         s->node_vtable.interface = strdup(interface);
1666         if (!s->node_vtable.interface) {
1667                 r = -ENOMEM;
1668                 goto fail;
1669         }
1670
1671         for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
1672
1673                 switch (v->type) {
1674
1675                 case _SD_BUS_VTABLE_METHOD: {
1676                         struct vtable_member *m;
1677
1678                         if (!member_name_is_valid(v->x.method.member) ||
1679                             !signature_is_valid(strempty(v->x.method.signature), false) ||
1680                             !signature_is_valid(strempty(v->x.method.result), false) ||
1681                             !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) ||
1682                             v->flags & (SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) {
1683                                 r = -EINVAL;
1684                                 goto fail;
1685                         }
1686
1687                         m = new0(struct vtable_member, 1);
1688                         if (!m) {
1689                                 r = -ENOMEM;
1690                                 goto fail;
1691                         }
1692
1693                         m->parent = &s->node_vtable;
1694                         m->path = n->path;
1695                         m->interface = s->node_vtable.interface;
1696                         m->member = v->x.method.member;
1697                         m->vtable = v;
1698
1699                         r = hashmap_put(bus->vtable_methods, m, m);
1700                         if (r < 0) {
1701                                 free(m);
1702                                 goto fail;
1703                         }
1704
1705                         break;
1706                 }
1707
1708                 case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
1709
1710                         if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) {
1711                                 r = -EINVAL;
1712                                 goto fail;
1713                         }
1714
1715                         /* Fall through */
1716
1717                 case _SD_BUS_VTABLE_PROPERTY: {
1718                         struct vtable_member *m;
1719
1720                         if (!member_name_is_valid(v->x.property.member) ||
1721                             !signature_is_single(v->x.property.signature, false) ||
1722                             !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) ||
1723                             v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
1724                             (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 ||
1725                             (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) {
1726                                 r = -EINVAL;
1727                                 goto fail;
1728                         }
1729
1730                         m = new0(struct vtable_member, 1);
1731                         if (!m) {
1732                                 r = -ENOMEM;
1733                                 goto fail;
1734                         }
1735
1736                         m->parent = &s->node_vtable;
1737                         m->path = n->path;
1738                         m->interface = s->node_vtable.interface;
1739                         m->member = v->x.property.member;
1740                         m->vtable = v;
1741
1742                         r = hashmap_put(bus->vtable_properties, m, m);
1743                         if (r < 0) {
1744                                 free(m);
1745                                 goto fail;
1746                         }
1747
1748                         break;
1749                 }
1750
1751                 case _SD_BUS_VTABLE_SIGNAL:
1752
1753                         if (!member_name_is_valid(v->x.signal.member) ||
1754                             !signature_is_valid(strempty(v->x.signal.signature), false) ||
1755                             v->flags & SD_BUS_VTABLE_UNPRIVILEGED) {
1756                                 r = -EINVAL;
1757                                 goto fail;
1758                         }
1759
1760                         break;
1761
1762                 default:
1763                         r = -EINVAL;
1764                         goto fail;
1765                 }
1766         }
1767
1768         s->node_vtable.node = n;
1769         LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable);
1770         bus->nodes_modified = true;
1771
1772         if (slot)
1773                 *slot = s;
1774
1775         return 0;
1776
1777 fail:
1778         sd_bus_slot_unref(s);
1779         bus_node_gc(bus, n);
1780
1781         return r;
1782 }
1783
1784 _public_ int sd_bus_add_object_vtable(
1785                 sd_bus *bus,
1786                 sd_bus_slot **slot,
1787                 const char *path,
1788                 const char *interface,
1789                 const sd_bus_vtable *vtable,
1790                 void *userdata) {
1791
1792         return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata);
1793 }
1794
1795 _public_ int sd_bus_add_fallback_vtable(
1796                 sd_bus *bus,
1797                 sd_bus_slot **slot,
1798                 const char *prefix,
1799                 const char *interface,
1800                 const sd_bus_vtable *vtable,
1801                 sd_bus_object_find_t find,
1802                 void *userdata) {
1803
1804         return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata);
1805 }
1806
1807 _public_ int sd_bus_add_node_enumerator(
1808                 sd_bus *bus,
1809                 sd_bus_slot **slot,
1810                 const char *path,
1811                 sd_bus_node_enumerator_t callback,
1812                 void *userdata) {
1813
1814         sd_bus_slot *s;
1815         struct node *n;
1816         int r;
1817
1818         assert_return(bus, -EINVAL);
1819         assert_return(object_path_is_valid(path), -EINVAL);
1820         assert_return(callback, -EINVAL);
1821         assert_return(!bus_pid_changed(bus), -ECHILD);
1822
1823         n = bus_node_allocate(bus, path);
1824         if (!n)
1825                 return -ENOMEM;
1826
1827         s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata);
1828         if (!s) {
1829                 r = -ENOMEM;
1830                 goto fail;
1831         }
1832
1833         s->node_enumerator.callback = callback;
1834
1835         s->node_enumerator.node = n;
1836         LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator);
1837         bus->nodes_modified = true;
1838
1839         if (slot)
1840                 *slot = s;
1841
1842         return 0;
1843
1844 fail:
1845         sd_bus_slot_unref(s);
1846         bus_node_gc(bus, n);
1847
1848         return r;
1849 }
1850
1851 static int emit_properties_changed_on_interface(
1852                 sd_bus *bus,
1853                 const char *prefix,
1854                 const char *path,
1855                 const char *interface,
1856                 bool require_fallback,
1857                 bool *found_interface,
1858                 char **names) {
1859
1860         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1861         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1862         bool has_invalidating = false, has_changing = false;
1863         struct vtable_member key = {};
1864         struct node_vtable *c;
1865         struct node *n;
1866         char **property;
1867         void *u = NULL;
1868         int r;
1869
1870         assert(bus);
1871         assert(prefix);
1872         assert(path);
1873         assert(interface);
1874         assert(found_interface);
1875
1876         n = hashmap_get(bus->nodes, prefix);
1877         if (!n)
1878                 return 0;
1879
1880         r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
1881         if (r < 0)
1882                 return r;
1883
1884         r = sd_bus_message_append(m, "s", interface);
1885         if (r < 0)
1886                 return r;
1887
1888         r = sd_bus_message_open_container(m, 'a', "{sv}");
1889         if (r < 0)
1890                 return r;
1891
1892         key.path = prefix;
1893         key.interface = interface;
1894
1895         LIST_FOREACH(vtables, c, n->vtables) {
1896                 if (require_fallback && !c->is_fallback)
1897                         continue;
1898
1899                 if (!streq(c->interface, interface))
1900                         continue;
1901
1902                 r = node_vtable_get_userdata(bus, path, c, &u, &error);
1903                 if (r < 0)
1904                         return r;
1905                 if (bus->nodes_modified)
1906                         return 0;
1907                 if (r == 0)
1908                         continue;
1909
1910                 *found_interface = true;
1911
1912                 if (names) {
1913                         /* If the caller specified a list of
1914                          * properties we include exactly those in the
1915                          * PropertiesChanged message */
1916
1917                         STRV_FOREACH(property, names) {
1918                                 struct vtable_member *v;
1919
1920                                 assert_return(member_name_is_valid(*property), -EINVAL);
1921
1922                                 key.member = *property;
1923                                 v = hashmap_get(bus->vtable_properties, &key);
1924                                 if (!v)
1925                                         return -ENOENT;
1926
1927                                 /* If there are two vtables for the same
1928                                  * interface, let's handle this property when
1929                                  * we come to that vtable. */
1930                                 if (c != v->parent)
1931                                         continue;
1932
1933                                 assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE ||
1934                                               v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION, -EDOM);
1935
1936                                 assert_return(!(v->vtable->flags & SD_BUS_VTABLE_HIDDEN), -EDOM);
1937
1938                                 if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
1939                                         has_invalidating = true;
1940                                         continue;
1941                                 }
1942
1943                                 has_changing = true;
1944
1945                                 r = vtable_append_one_property(bus, m, m->path, c, v->vtable, u, &error);
1946                                 if (r < 0)
1947                                         return r;
1948                                 if (bus->nodes_modified)
1949                                         return 0;
1950                         }
1951                 } else {
1952                         const sd_bus_vtable *v;
1953
1954                         /* If the caller specified no properties list
1955                          * we include all properties that are marked
1956                          * as changing in the message. */
1957
1958                         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
1959                                 if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
1960                                         continue;
1961
1962                                 if (v->flags & SD_BUS_VTABLE_HIDDEN)
1963                                         continue;
1964
1965                                 if (v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
1966                                         has_invalidating = true;
1967                                         continue;
1968                                 }
1969
1970                                 if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
1971                                         continue;
1972
1973                                 has_changing = true;
1974
1975                                 r = vtable_append_one_property(bus, m, m->path, c, v, u, &error);
1976                                 if (r < 0)
1977                                         return r;
1978                                 if (bus->nodes_modified)
1979                                         return 0;
1980                         }
1981                 }
1982         }
1983
1984         if (!has_invalidating && !has_changing)
1985                 return 0;
1986
1987         r = sd_bus_message_close_container(m);
1988         if (r < 0)
1989                 return r;
1990
1991         r = sd_bus_message_open_container(m, 'a', "s");
1992         if (r < 0)
1993                 return r;
1994
1995         if (has_invalidating) {
1996                 LIST_FOREACH(vtables, c, n->vtables) {
1997                         if (require_fallback && !c->is_fallback)
1998                                 continue;
1999
2000                         if (!streq(c->interface, interface))
2001                                 continue;
2002
2003                         r = node_vtable_get_userdata(bus, path, c, &u, &error);
2004                         if (r < 0)
2005                                 return r;
2006                         if (bus->nodes_modified)
2007                                 return 0;
2008                         if (r == 0)
2009                                 continue;
2010
2011                         if (names) {
2012                                 STRV_FOREACH(property, names) {
2013                                         struct vtable_member *v;
2014
2015                                         key.member = *property;
2016                                         assert_se(v = hashmap_get(bus->vtable_properties, &key));
2017                                         assert(c == v->parent);
2018
2019                                         if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
2020                                                 continue;
2021
2022                                         r = sd_bus_message_append(m, "s", *property);
2023                                         if (r < 0)
2024                                                 return r;
2025                                 }
2026                         } else {
2027                                 const sd_bus_vtable *v;
2028
2029                                 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
2030                                         if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
2031                                                 continue;
2032
2033                                         if (v->flags & SD_BUS_VTABLE_HIDDEN)
2034                                                 continue;
2035
2036                                         if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
2037                                                 continue;
2038
2039                                         r = sd_bus_message_append(m, "s", v->x.property.member);
2040                                         if (r < 0)
2041                                                 return r;
2042                                 }
2043                         }
2044                 }
2045         }
2046
2047         r = sd_bus_message_close_container(m);
2048         if (r < 0)
2049                 return r;
2050
2051         r = sd_bus_send(bus, m, NULL);
2052         if (r < 0)
2053                 return r;
2054
2055         return 1;
2056 }
2057
2058 _public_ int sd_bus_emit_properties_changed_strv(
2059                 sd_bus *bus,
2060                 const char *path,
2061                 const char *interface,
2062                 char **names) {
2063
2064         BUS_DONT_DESTROY(bus);
2065         bool found_interface = false;
2066         char *prefix;
2067         int r;
2068
2069         assert_return(bus, -EINVAL);
2070         assert_return(object_path_is_valid(path), -EINVAL);
2071         assert_return(interface_name_is_valid(interface), -EINVAL);
2072         assert_return(!bus_pid_changed(bus), -ECHILD);
2073
2074         if (!BUS_IS_OPEN(bus->state))
2075                 return -ENOTCONN;
2076
2077         /* A non-NULL but empty names list means nothing needs to be
2078            generated. A NULL list OTOH indicates that all properties
2079            that are set to EMITS_CHANGE or EMITS_INVALIDATION shall be
2080            included in the PropertiesChanged message. */
2081         if (names && names[0] == NULL)
2082                 return 0;
2083
2084         do {
2085                 bus->nodes_modified = false;
2086
2087                 r = emit_properties_changed_on_interface(bus, path, path, interface, false, &found_interface, names);
2088                 if (r != 0)
2089                         return r;
2090                 if (bus->nodes_modified)
2091                         continue;
2092
2093                 prefix = alloca(strlen(path) + 1);
2094                 OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
2095                         r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names);
2096                         if (r != 0)
2097                                 return r;
2098                         if (bus->nodes_modified)
2099                                 break;
2100                 }
2101
2102         } while (bus->nodes_modified);
2103
2104         return found_interface ? 0 : -ENOENT;
2105 }
2106
2107 _public_ int sd_bus_emit_properties_changed(
2108                 sd_bus *bus,
2109                 const char *path,
2110                 const char *interface,
2111                 const char *name, ...)  {
2112
2113         char **names;
2114
2115         assert_return(bus, -EINVAL);
2116         assert_return(object_path_is_valid(path), -EINVAL);
2117         assert_return(interface_name_is_valid(interface), -EINVAL);
2118         assert_return(!bus_pid_changed(bus), -ECHILD);
2119
2120         if (!BUS_IS_OPEN(bus->state))
2121                 return -ENOTCONN;
2122
2123         if (!name)
2124                 return 0;
2125
2126         names = strv_from_stdarg_alloca(name);
2127
2128         return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
2129 }
2130
2131 static int interfaces_added_append_one_prefix(
2132                 sd_bus *bus,
2133                 sd_bus_message *m,
2134                 const char *prefix,
2135                 const char *path,
2136                 const char *interface,
2137                 bool require_fallback) {
2138
2139         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2140         bool found_interface = false;
2141         struct node_vtable *c;
2142         struct node *n;
2143         void *u = NULL;
2144         int r;
2145
2146         assert(bus);
2147         assert(m);
2148         assert(prefix);
2149         assert(path);
2150         assert(interface);
2151
2152         n = hashmap_get(bus->nodes, prefix);
2153         if (!n)
2154                 return 0;
2155
2156         LIST_FOREACH(vtables, c, n->vtables) {
2157                 if (require_fallback && !c->is_fallback)
2158                         continue;
2159
2160                 if (!streq(c->interface, interface))
2161                         continue;
2162
2163                 r = node_vtable_get_userdata(bus, path, c, &u, &error);
2164                 if (r < 0)
2165                         return r;
2166                 if (bus->nodes_modified)
2167                         return 0;
2168                 if (r == 0)
2169                         continue;
2170
2171                 if (!found_interface) {
2172                         r = sd_bus_message_append_basic(m, 's', interface);
2173                         if (r < 0)
2174                                 return r;
2175
2176                         r = sd_bus_message_open_container(m, 'a', "{sv}");
2177                         if (r < 0)
2178                                 return r;
2179
2180                         found_interface = true;
2181                 }
2182
2183                 r = vtable_append_all_properties(bus, m, path, c, u, &error);
2184                 if (r < 0)
2185                         return r;
2186                 if (bus->nodes_modified)
2187                         return 0;
2188         }
2189
2190         if (found_interface) {
2191                 r = sd_bus_message_close_container(m);
2192                 if (r < 0)
2193                         return r;
2194         }
2195
2196         return found_interface;
2197 }
2198
2199 static int interfaces_added_append_one(
2200                 sd_bus *bus,
2201                 sd_bus_message *m,
2202                 const char *path,
2203                 const char *interface) {
2204
2205         char *prefix;
2206         int r;
2207
2208         assert(bus);
2209         assert(m);
2210         assert(path);
2211         assert(interface);
2212
2213         r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false);
2214         if (r != 0)
2215                 return r;
2216         if (bus->nodes_modified)
2217                 return 0;
2218
2219         prefix = alloca(strlen(path) + 1);
2220         OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
2221                 r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
2222                 if (r != 0)
2223                         return r;
2224                 if (bus->nodes_modified)
2225                         return 0;
2226         }
2227
2228         return -ENOENT;
2229 }
2230
2231 _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
2232         BUS_DONT_DESTROY(bus);
2233
2234         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2235         char **i;
2236         int r;
2237
2238         assert_return(bus, -EINVAL);
2239         assert_return(object_path_is_valid(path), -EINVAL);
2240         assert_return(!bus_pid_changed(bus), -ECHILD);
2241
2242         if (!BUS_IS_OPEN(bus->state))
2243                 return -ENOTCONN;
2244
2245         if (strv_isempty(interfaces))
2246                 return 0;
2247
2248         do {
2249                 bus->nodes_modified = false;
2250                 m = sd_bus_message_unref(m);
2251
2252                 r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
2253                 if (r < 0)
2254                         return r;
2255
2256                 r = sd_bus_message_append_basic(m, 'o', path);
2257                 if (r < 0)
2258                         return r;
2259
2260                 r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
2261                 if (r < 0)
2262                         return r;
2263
2264                 STRV_FOREACH(i, interfaces) {
2265                         assert_return(interface_name_is_valid(*i), -EINVAL);
2266
2267                         r = sd_bus_message_open_container(m, 'e', "sa{sv}");
2268                         if (r < 0)
2269                                 return r;
2270
2271                         r = interfaces_added_append_one(bus, m, path, *i);
2272                         if (r < 0)
2273                                 return r;
2274
2275                         if (bus->nodes_modified)
2276                                 break;
2277
2278                         r = sd_bus_message_close_container(m);
2279                         if (r < 0)
2280                                 return r;
2281                 }
2282
2283                 if (bus->nodes_modified)
2284                         continue;
2285
2286                 r = sd_bus_message_close_container(m);
2287                 if (r < 0)
2288                         return r;
2289
2290         } while (bus->nodes_modified);
2291
2292         return sd_bus_send(bus, m, NULL);
2293 }
2294
2295 _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
2296         char **interfaces;
2297
2298         assert_return(bus, -EINVAL);
2299         assert_return(object_path_is_valid(path), -EINVAL);
2300         assert_return(!bus_pid_changed(bus), -ECHILD);
2301
2302         if (!BUS_IS_OPEN(bus->state))
2303                 return -ENOTCONN;
2304
2305         interfaces = strv_from_stdarg_alloca(interface);
2306
2307         return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
2308 }
2309
2310 _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
2311         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2312         int r;
2313
2314         assert_return(bus, -EINVAL);
2315         assert_return(object_path_is_valid(path), -EINVAL);
2316         assert_return(!bus_pid_changed(bus), -ECHILD);
2317
2318         if (!BUS_IS_OPEN(bus->state))
2319                 return -ENOTCONN;
2320
2321         if (strv_isempty(interfaces))
2322                 return 0;
2323
2324         r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
2325         if (r < 0)
2326                 return r;
2327
2328         r = sd_bus_message_append_basic(m, 'o', path);
2329         if (r < 0)
2330                 return r;
2331
2332         r = sd_bus_message_append_strv(m, interfaces);
2333         if (r < 0)
2334                 return r;
2335
2336         return sd_bus_send(bus, m, NULL);
2337 }
2338
2339 _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
2340         char **interfaces;
2341
2342         assert_return(bus, -EINVAL);
2343         assert_return(object_path_is_valid(path), -EINVAL);
2344         assert_return(!bus_pid_changed(bus), -ECHILD);
2345
2346         if (!BUS_IS_OPEN(bus->state))
2347                 return -ENOTCONN;
2348
2349         interfaces = strv_from_stdarg_alloca(interface);
2350
2351         return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
2352 }
2353
2354 _public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) {
2355         sd_bus_slot *s;
2356         struct node *n;
2357         int r;
2358
2359         assert_return(bus, -EINVAL);
2360         assert_return(object_path_is_valid(path), -EINVAL);
2361         assert_return(!bus_pid_changed(bus), -ECHILD);
2362
2363         n = bus_node_allocate(bus, path);
2364         if (!n)
2365                 return -ENOMEM;
2366
2367         s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL);
2368         if (!s) {
2369                 r = -ENOMEM;
2370                 goto fail;
2371         }
2372
2373         s->node_object_manager.node = n;
2374         LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager);
2375         bus->nodes_modified = true;
2376
2377         if (slot)
2378                 *slot = s;
2379
2380         return 0;
2381
2382 fail:
2383         sd_bus_slot_unref(s);
2384         bus_node_gc(bus, n);
2385
2386         return r;
2387 }