chiark / gitweb /
sd-bus: rework credential query logic
[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                 const char *signature = NULL;
621                 char type = 0;
622
623                 if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
624                         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member);
625
626                 /* Avoid that we call the set routine more than once
627                  * if the processing of this message got restarted
628                  * because the node tree changed. */
629                 if (c->last_iteration == bus->iteration_counter)
630                         return 0;
631
632                 c->last_iteration = bus->iteration_counter;
633
634                 r = sd_bus_message_peek_type(m, &type, &signature);
635                 if (r < 0)
636                         return r;
637
638                 if (type != 'v' || !streq(strempty(signature), strempty(c->vtable->x.property.signature)))
639                         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Incorrect parameters for property '%s', expected '%s', got '%s'.", c->member, strempty(c->vtable->x.property.signature), strempty(signature));
640
641                 r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
642                 if (r < 0)
643                         return r;
644
645                 r = check_access(bus, m, c, &error);
646                 if (r < 0)
647                         return bus_maybe_reply_error(m, r, &error);
648
649                 r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error);
650                 if (r < 0)
651                         return bus_maybe_reply_error(m, r, &error);
652
653                 if (bus->nodes_modified)
654                         return 0;
655
656                 r = sd_bus_message_exit_container(m);
657                 if (r < 0)
658                         return r;
659         }
660
661         r = sd_bus_send(bus, reply, NULL);
662         if (r < 0)
663                 return r;
664
665         return 1;
666 }
667
668 static int vtable_append_one_property(
669                 sd_bus *bus,
670                 sd_bus_message *reply,
671                 const char *path,
672                 struct node_vtable *c,
673                 const sd_bus_vtable *v,
674                 void *userdata,
675                 sd_bus_error *error) {
676
677         sd_bus_slot *slot;
678         int r;
679
680         assert(bus);
681         assert(reply);
682         assert(path);
683         assert(c);
684         assert(v);
685
686         r = sd_bus_message_open_container(reply, 'e', "sv");
687         if (r < 0)
688                 return r;
689
690         r = sd_bus_message_append(reply, "s", v->x.property.member);
691         if (r < 0)
692                 return r;
693
694         r = sd_bus_message_open_container(reply, 'v', v->x.property.signature);
695         if (r < 0)
696                 return r;
697
698         slot = container_of(c, sd_bus_slot, node_vtable);
699
700         r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
701         if (r < 0)
702                 return r;
703         if (bus->nodes_modified)
704                 return 0;
705
706         r = sd_bus_message_close_container(reply);
707         if (r < 0)
708                 return r;
709
710         r = sd_bus_message_close_container(reply);
711         if (r < 0)
712                 return r;
713
714         return 0;
715 }
716
717 static int vtable_append_all_properties(
718                 sd_bus *bus,
719                 sd_bus_message *reply,
720                 const char *path,
721                 struct node_vtable *c,
722                 void *userdata,
723                 sd_bus_error *error) {
724
725         const sd_bus_vtable *v;
726         int r;
727
728         assert(bus);
729         assert(reply);
730         assert(path);
731         assert(c);
732
733         if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
734                 return 1;
735
736         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
737                 if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
738                         continue;
739
740                 if (v->flags & SD_BUS_VTABLE_HIDDEN)
741                         continue;
742
743                 r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
744                 if (r < 0)
745                         return r;
746                 if (bus->nodes_modified)
747                         return 0;
748         }
749
750         return 1;
751 }
752
753 static int property_get_all_callbacks_run(
754                 sd_bus *bus,
755                 sd_bus_message *m,
756                 struct node_vtable *first,
757                 bool require_fallback,
758                 const char *iface,
759                 bool *found_object) {
760
761         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
762         struct node_vtable *c;
763         bool found_interface;
764         int r;
765
766         assert(bus);
767         assert(m);
768         assert(found_object);
769
770         r = sd_bus_message_new_method_return(m, &reply);
771         if (r < 0)
772                 return r;
773
774         r = sd_bus_message_open_container(reply, 'a', "{sv}");
775         if (r < 0)
776                 return r;
777
778         found_interface = !iface ||
779                 streq(iface, "org.freedesktop.DBus.Properties") ||
780                 streq(iface, "org.freedesktop.DBus.Peer") ||
781                 streq(iface, "org.freedesktop.DBus.Introspectable");
782
783         LIST_FOREACH(vtables, c, first) {
784                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
785                 void *u;
786
787                 if (require_fallback && !c->is_fallback)
788                         continue;
789
790                 r = node_vtable_get_userdata(bus, m->path, c, &u, &error);
791                 if (r < 0)
792                         return bus_maybe_reply_error(m, r, &error);
793                 if (bus->nodes_modified)
794                         return 0;
795                 if (r == 0)
796                         continue;
797
798                 *found_object = true;
799
800                 if (iface && !streq(c->interface, iface))
801                         continue;
802                 found_interface = true;
803
804                 r = vtable_append_all_properties(bus, reply, m->path, c, u, &error);
805                 if (r < 0)
806                         return bus_maybe_reply_error(m, r, &error);
807                 if (bus->nodes_modified)
808                         return 0;
809         }
810
811         if (!found_interface) {
812                 r = sd_bus_reply_method_errorf(
813                                 m,
814                                 SD_BUS_ERROR_UNKNOWN_INTERFACE,
815                                 "Unknown interface '%s'.", iface);
816                 if (r < 0)
817                         return r;
818
819                 return 1;
820         }
821
822         r = sd_bus_message_close_container(reply);
823         if (r < 0)
824                 return r;
825
826         r = sd_bus_send(bus, reply, NULL);
827         if (r < 0)
828                 return r;
829
830         return 1;
831 }
832
833 static int bus_node_exists(
834                 sd_bus *bus,
835                 struct node *n,
836                 const char *path,
837                 bool require_fallback) {
838
839         struct node_vtable *c;
840         struct node_callback *k;
841         int r;
842
843         assert(bus);
844         assert(n);
845         assert(path);
846
847         /* Tests if there's anything attached directly to this node
848          * for the specified path */
849
850         if (!require_fallback && (n->enumerators || n->object_managers))
851                 return true;
852
853         LIST_FOREACH(callbacks, k, n->callbacks) {
854                 if (require_fallback && !k->is_fallback)
855                         continue;
856
857                 return 1;
858         }
859
860         LIST_FOREACH(vtables, c, n->vtables) {
861                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
862
863                 if (require_fallback && !c->is_fallback)
864                         continue;
865
866                 r = node_vtable_get_userdata(bus, path, c, NULL, &error);
867                 if (r != 0)
868                         return r;
869                 if (bus->nodes_modified)
870                         return 0;
871         }
872
873         return 0;
874 }
875
876 static int process_introspect(
877                 sd_bus *bus,
878                 sd_bus_message *m,
879                 struct node *n,
880                 bool require_fallback,
881                 bool *found_object) {
882
883         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
884         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
885         _cleanup_set_free_free_ Set *s = NULL;
886         const char *previous_interface = NULL;
887         struct introspect intro;
888         struct node_vtable *c;
889         bool empty;
890         int r;
891
892         assert(bus);
893         assert(m);
894         assert(n);
895         assert(found_object);
896
897         r = get_child_nodes(bus, m->path, n, &s, &error);
898         if (r < 0)
899                 return bus_maybe_reply_error(m, r, &error);
900         if (bus->nodes_modified)
901                 return 0;
902
903         r = introspect_begin(&intro, bus->trusted);
904         if (r < 0)
905                 return r;
906
907         r = introspect_write_default_interfaces(&intro, !require_fallback && n->object_managers);
908         if (r < 0)
909                 return r;
910
911         empty = set_isempty(s);
912
913         LIST_FOREACH(vtables, c, n->vtables) {
914                 if (require_fallback && !c->is_fallback)
915                         continue;
916
917                 r = node_vtable_get_userdata(bus, m->path, c, NULL, &error);
918                 if (r < 0) {
919                         r = bus_maybe_reply_error(m, r, &error);
920                         goto finish;
921                 }
922                 if (bus->nodes_modified) {
923                         r = 0;
924                         goto finish;
925                 }
926                 if (r == 0)
927                         continue;
928
929                 empty = false;
930
931                 if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
932                         continue;
933
934                 if (!streq_ptr(previous_interface, c->interface)) {
935
936                         if (previous_interface)
937                                 fputs(" </interface>\n", intro.f);
938
939                         fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
940                 }
941
942                 r = introspect_write_interface(&intro, c->vtable);
943                 if (r < 0)
944                         goto finish;
945
946                 previous_interface = c->interface;
947         }
948
949         if (previous_interface)
950                 fputs(" </interface>\n", intro.f);
951
952         if (empty) {
953                 /* Nothing?, let's see if we exist at all, and if not
954                  * refuse to do anything */
955                 r = bus_node_exists(bus, n, m->path, require_fallback);
956                 if (r <= 0)
957                         goto finish;
958                 if (bus->nodes_modified) {
959                         r = 0;
960                         goto finish;
961                 }
962         }
963
964         *found_object = true;
965
966         r = introspect_write_child_nodes(&intro, s, m->path);
967         if (r < 0)
968                 goto finish;
969
970         r = introspect_finish(&intro, bus, m, &reply);
971         if (r < 0)
972                 goto finish;
973
974         r = sd_bus_send(bus, reply, NULL);
975         if (r < 0)
976                 goto finish;
977
978         r = 1;
979
980 finish:
981         introspect_free(&intro);
982         return r;
983 }
984
985 static int object_manager_serialize_path(
986                 sd_bus *bus,
987                 sd_bus_message *reply,
988                 const char *prefix,
989                 const char *path,
990                 bool require_fallback,
991                 sd_bus_error *error) {
992
993         const char *previous_interface = NULL;
994         bool found_something = false;
995         struct node_vtable *i;
996         struct node *n;
997         int r;
998
999         assert(bus);
1000         assert(reply);
1001         assert(prefix);
1002         assert(path);
1003         assert(error);
1004
1005         n = hashmap_get(bus->nodes, prefix);
1006         if (!n)
1007                 return 0;
1008
1009         LIST_FOREACH(vtables, i, n->vtables) {
1010                 void *u;
1011
1012                 if (require_fallback && !i->is_fallback)
1013                         continue;
1014
1015                 r = node_vtable_get_userdata(bus, path, i, &u, error);
1016                 if (r < 0)
1017                         return r;
1018                 if (bus->nodes_modified)
1019                         return 0;
1020                 if (r == 0)
1021                         continue;
1022
1023                 if (!found_something) {
1024
1025                         /* Open the object part */
1026
1027                         r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
1028                         if (r < 0)
1029                                 return r;
1030
1031                         r = sd_bus_message_append(reply, "o", path);
1032                         if (r < 0)
1033                                 return r;
1034
1035                         r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
1036                         if (r < 0)
1037                                 return r;
1038
1039                         found_something = true;
1040                 }
1041
1042                 if (!streq_ptr(previous_interface, i->interface)) {
1043
1044                         /* Maybe close the previous interface part */
1045
1046                         if (previous_interface) {
1047                                 r = sd_bus_message_close_container(reply);
1048                                 if (r < 0)
1049                                         return r;
1050
1051                                 r = sd_bus_message_close_container(reply);
1052                                 if (r < 0)
1053                                         return r;
1054                         }
1055
1056                         /* Open the new interface part */
1057
1058                         r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
1059                         if (r < 0)
1060                                 return r;
1061
1062                         r = sd_bus_message_append(reply, "s", i->interface);
1063                         if (r < 0)
1064                                 return r;
1065
1066                         r = sd_bus_message_open_container(reply, 'a', "{sv}");
1067                         if (r < 0)
1068                                 return r;
1069                 }
1070
1071                 r = vtable_append_all_properties(bus, reply, path, i, u, error);
1072                 if (r < 0)
1073                         return r;
1074                 if (bus->nodes_modified)
1075                         return 0;
1076
1077                 previous_interface = i->interface;
1078         }
1079
1080         if (previous_interface) {
1081                 r = sd_bus_message_close_container(reply);
1082                 if (r < 0)
1083                         return r;
1084
1085                 r = sd_bus_message_close_container(reply);
1086                 if (r < 0)
1087                         return r;
1088         }
1089
1090         if (found_something) {
1091                 r = sd_bus_message_close_container(reply);
1092                 if (r < 0)
1093                         return r;
1094
1095                 r = sd_bus_message_close_container(reply);
1096                 if (r < 0)
1097                         return r;
1098         }
1099
1100         return 1;
1101 }
1102
1103 static int object_manager_serialize_path_and_fallbacks(
1104                 sd_bus *bus,
1105                 sd_bus_message *reply,
1106                 const char *path,
1107                 sd_bus_error *error) {
1108
1109         char *prefix;
1110         int r;
1111
1112         assert(bus);
1113         assert(reply);
1114         assert(path);
1115         assert(error);
1116
1117         /* First, add all vtables registered for this path */
1118         r = object_manager_serialize_path(bus, reply, path, path, false, error);
1119         if (r < 0)
1120                 return r;
1121         if (bus->nodes_modified)
1122                 return 0;
1123
1124         /* Second, add fallback vtables registered for any of the prefixes */
1125         prefix = alloca(strlen(path) + 1);
1126         OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
1127                 r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
1128                 if (r < 0)
1129                         return r;
1130                 if (bus->nodes_modified)
1131                         return 0;
1132         }
1133
1134         return 0;
1135 }
1136
1137 static int process_get_managed_objects(
1138                 sd_bus *bus,
1139                 sd_bus_message *m,
1140                 struct node *n,
1141                 bool require_fallback,
1142                 bool *found_object) {
1143
1144         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1145         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1146         _cleanup_set_free_free_ Set *s = NULL;
1147         Iterator i;
1148         char *path;
1149         int r;
1150
1151         assert(bus);
1152         assert(m);
1153         assert(n);
1154         assert(found_object);
1155
1156         /* Spec says, GetManagedObjects() is only implemented on the root of a
1157          * sub-tree. Therefore, we require a registered object-manager on
1158          * exactly the queried path, otherwise, we refuse to respond. */
1159
1160         if (require_fallback || !n->object_managers)
1161                 return 0;
1162
1163         r = get_child_nodes(bus, m->path, n, &s, &error);
1164         if (r < 0)
1165                 return r;
1166         if (bus->nodes_modified)
1167                 return 0;
1168
1169         r = sd_bus_message_new_method_return(m, &reply);
1170         if (r < 0)
1171                 return r;
1172
1173         r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}");
1174         if (r < 0)
1175                 return r;
1176
1177         SET_FOREACH(path, s, i) {
1178                 r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
1179                 if (r < 0)
1180                         return r;
1181
1182                 if (bus->nodes_modified)
1183                         return 0;
1184         }
1185
1186         r = sd_bus_message_close_container(reply);
1187         if (r < 0)
1188                 return r;
1189
1190         r = sd_bus_send(bus, reply, NULL);
1191         if (r < 0)
1192                 return r;
1193
1194         return 1;
1195 }
1196
1197 static int object_find_and_run(
1198                 sd_bus *bus,
1199                 sd_bus_message *m,
1200                 const char *p,
1201                 bool require_fallback,
1202                 bool *found_object) {
1203
1204         struct node *n;
1205         struct vtable_member vtable_key, *v;
1206         int r;
1207
1208         assert(bus);
1209         assert(m);
1210         assert(p);
1211         assert(found_object);
1212
1213         n = hashmap_get(bus->nodes, p);
1214         if (!n)
1215                 return 0;
1216
1217         /* First, try object callbacks */
1218         r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object);
1219         if (r != 0)
1220                 return r;
1221         if (bus->nodes_modified)
1222                 return 0;
1223
1224         if (!m->interface || !m->member)
1225                 return 0;
1226
1227         /* Then, look for a known method */
1228         vtable_key.path = (char*) p;
1229         vtable_key.interface = m->interface;
1230         vtable_key.member = m->member;
1231
1232         v = hashmap_get(bus->vtable_methods, &vtable_key);
1233         if (v) {
1234                 r = method_callbacks_run(bus, m, v, require_fallback, found_object);
1235                 if (r != 0)
1236                         return r;
1237                 if (bus->nodes_modified)
1238                         return 0;
1239         }
1240
1241         /* Then, look for a known property */
1242         if (streq(m->interface, "org.freedesktop.DBus.Properties")) {
1243                 bool get = false;
1244
1245                 get = streq(m->member, "Get");
1246
1247                 if (get || streq(m->member, "Set")) {
1248
1249                         r = sd_bus_message_rewind(m, true);
1250                         if (r < 0)
1251                                 return r;
1252
1253                         vtable_key.path = (char*) p;
1254
1255                         r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member);
1256                         if (r < 0)
1257                                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface and member parameters");
1258
1259                         v = hashmap_get(bus->vtable_properties, &vtable_key);
1260                         if (v) {
1261                                 r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object);
1262                                 if (r != 0)
1263                                         return r;
1264                         }
1265
1266                 } else if (streq(m->member, "GetAll")) {
1267                         const char *iface;
1268
1269                         r = sd_bus_message_rewind(m, true);
1270                         if (r < 0)
1271                                 return r;
1272
1273                         r = sd_bus_message_read(m, "s", &iface);
1274                         if (r < 0)
1275                                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface parameter");
1276
1277                         if (iface[0] == 0)
1278                                 iface = NULL;
1279
1280                         r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object);
1281                         if (r != 0)
1282                                 return r;
1283                 }
1284
1285         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1286
1287                 if (!isempty(sd_bus_message_get_signature(m, true)))
1288                         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
1289
1290                 r = process_introspect(bus, m, n, require_fallback, found_object);
1291                 if (r != 0)
1292                         return r;
1293
1294         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
1295
1296                 if (!isempty(sd_bus_message_get_signature(m, true)))
1297                         return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
1298
1299                 r = process_get_managed_objects(bus, m, n, require_fallback, found_object);
1300                 if (r != 0)
1301                         return r;
1302         }
1303
1304         if (bus->nodes_modified)
1305                 return 0;
1306
1307         if (!*found_object) {
1308                 r = bus_node_exists(bus, n, m->path, require_fallback);
1309                 if (r < 0)
1310                         return r;
1311                 if (bus->nodes_modified)
1312                         return 0;
1313                 if (r > 0)
1314                         *found_object = true;
1315         }
1316
1317         return 0;
1318 }
1319
1320 int bus_process_object(sd_bus *bus, sd_bus_message *m) {
1321         int r;
1322         size_t pl;
1323         bool found_object = false;
1324
1325         assert(bus);
1326         assert(m);
1327
1328         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1329                 return 0;
1330
1331         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1332                 return 0;
1333
1334         if (hashmap_isempty(bus->nodes))
1335                 return 0;
1336
1337         /* Never respond to broadcast messages */
1338         if (bus->bus_client && !m->destination)
1339                 return 0;
1340
1341         assert(m->path);
1342         assert(m->member);
1343
1344         pl = strlen(m->path);
1345         do {
1346                 char prefix[pl+1];
1347
1348                 bus->nodes_modified = false;
1349
1350                 r = object_find_and_run(bus, m, m->path, false, &found_object);
1351                 if (r != 0)
1352                         return r;
1353
1354                 /* Look for fallback prefixes */
1355                 OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) {
1356
1357                         if (bus->nodes_modified)
1358                                 break;
1359
1360                         r = object_find_and_run(bus, m, prefix, true, &found_object);
1361                         if (r != 0)
1362                                 return r;
1363                 }
1364
1365         } while (bus->nodes_modified);
1366
1367         if (!found_object)
1368                 return 0;
1369
1370         if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
1371             sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
1372                 r = sd_bus_reply_method_errorf(
1373                                 m,
1374                                 SD_BUS_ERROR_UNKNOWN_PROPERTY,
1375                                 "Unknown property or interface.");
1376         else
1377                 r = sd_bus_reply_method_errorf(
1378                                 m,
1379                                 SD_BUS_ERROR_UNKNOWN_METHOD,
1380                                 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
1381
1382         if (r < 0)
1383                 return r;
1384
1385         return 1;
1386 }
1387
1388 static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
1389         struct node *n, *parent;
1390         const char *e;
1391         _cleanup_free_ char *s = NULL;
1392         char *p;
1393         int r;
1394
1395         assert(bus);
1396         assert(path);
1397         assert(path[0] == '/');
1398
1399         n = hashmap_get(bus->nodes, path);
1400         if (n)
1401                 return n;
1402
1403         r = hashmap_ensure_allocated(&bus->nodes, &string_hash_ops);
1404         if (r < 0)
1405                 return NULL;
1406
1407         s = strdup(path);
1408         if (!s)
1409                 return NULL;
1410
1411         if (streq(path, "/"))
1412                 parent = NULL;
1413         else {
1414                 e = strrchr(path, '/');
1415                 assert(e);
1416
1417                 p = strndupa(path, MAX(1, path - e));
1418
1419                 parent = bus_node_allocate(bus, p);
1420                 if (!parent)
1421                         return NULL;
1422         }
1423
1424         n = new0(struct node, 1);
1425         if (!n)
1426                 return NULL;
1427
1428         n->parent = parent;
1429         n->path = s;
1430         s = NULL; /* do not free */
1431
1432         r = hashmap_put(bus->nodes, n->path, n);
1433         if (r < 0) {
1434                 free(n->path);
1435                 free(n);
1436                 return NULL;
1437         }
1438
1439         if (parent)
1440                 LIST_PREPEND(siblings, parent->child, n);
1441
1442         return n;
1443 }
1444
1445 void bus_node_gc(sd_bus *b, struct node *n) {
1446         assert(b);
1447
1448         if (!n)
1449                 return;
1450
1451         if (n->child ||
1452             n->callbacks ||
1453             n->vtables ||
1454             n->enumerators ||
1455             n->object_managers)
1456                 return;
1457
1458         assert(hashmap_remove(b->nodes, n->path) == n);
1459
1460         if (n->parent)
1461                 LIST_REMOVE(siblings, n->parent->child, n);
1462
1463         free(n->path);
1464         bus_node_gc(b, n->parent);
1465         free(n);
1466 }
1467
1468 static int bus_add_object(
1469                 sd_bus *bus,
1470                 sd_bus_slot **slot,
1471                 bool fallback,
1472                 const char *path,
1473                 sd_bus_message_handler_t callback,
1474                 void *userdata) {
1475
1476         sd_bus_slot *s;
1477         struct node *n;
1478         int r;
1479
1480         assert_return(bus, -EINVAL);
1481         assert_return(object_path_is_valid(path), -EINVAL);
1482         assert_return(callback, -EINVAL);
1483         assert_return(!bus_pid_changed(bus), -ECHILD);
1484
1485         n = bus_node_allocate(bus, path);
1486         if (!n)
1487                 return -ENOMEM;
1488
1489         s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata);
1490         if (!s) {
1491                 r = -ENOMEM;
1492                 goto fail;
1493         }
1494
1495         s->node_callback.callback = callback;
1496         s->node_callback.is_fallback = fallback;
1497
1498         s->node_callback.node = n;
1499         LIST_PREPEND(callbacks, n->callbacks, &s->node_callback);
1500         bus->nodes_modified = true;
1501
1502         if (slot)
1503                 *slot = s;
1504
1505         return 0;
1506
1507 fail:
1508         sd_bus_slot_unref(s);
1509         bus_node_gc(bus, n);
1510
1511         return r;
1512 }
1513
1514 _public_ int sd_bus_add_object(
1515                 sd_bus *bus,
1516                 sd_bus_slot **slot,
1517                 const char *path,
1518                 sd_bus_message_handler_t callback,
1519                 void *userdata) {
1520
1521         return bus_add_object(bus, slot, false, path, callback, userdata);
1522 }
1523
1524 _public_ int sd_bus_add_fallback(
1525                 sd_bus *bus,
1526                 sd_bus_slot **slot,
1527                 const char *prefix,
1528                 sd_bus_message_handler_t callback,
1529                 void *userdata) {
1530
1531         return bus_add_object(bus, slot, true, prefix, callback, userdata);
1532 }
1533
1534 static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
1535         const struct vtable_member *m = a;
1536         uint8_t hash_key2[HASH_KEY_SIZE];
1537         unsigned long ret;
1538
1539         assert(m);
1540
1541         ret = string_hash_func(m->path, hash_key);
1542
1543         /* Use a slightly different hash key for the interface */
1544         memcpy(hash_key2, hash_key, HASH_KEY_SIZE);
1545         hash_key2[0]++;
1546         ret ^= string_hash_func(m->interface, hash_key2);
1547
1548         /* And an even different one for the  member */
1549         hash_key2[0]++;
1550         ret ^= string_hash_func(m->member, hash_key2);
1551
1552         return ret;
1553 }
1554
1555 static int vtable_member_compare_func(const void *a, const void *b) {
1556         const struct vtable_member *x = a, *y = b;
1557         int r;
1558
1559         assert(x);
1560         assert(y);
1561
1562         r = strcmp(x->path, y->path);
1563         if (r != 0)
1564                 return r;
1565
1566         r = strcmp(x->interface, y->interface);
1567         if (r != 0)
1568                 return r;
1569
1570         return strcmp(x->member, y->member);
1571 }
1572
1573 static const struct hash_ops vtable_member_hash_ops = {
1574         .hash = vtable_member_hash_func,
1575         .compare = vtable_member_compare_func
1576 };
1577
1578 static int add_object_vtable_internal(
1579                 sd_bus *bus,
1580                 sd_bus_slot **slot,
1581                 const char *path,
1582                 const char *interface,
1583                 const sd_bus_vtable *vtable,
1584                 bool fallback,
1585                 sd_bus_object_find_t find,
1586                 void *userdata) {
1587
1588         sd_bus_slot *s = NULL;
1589         struct node_vtable *i, *existing = NULL;
1590         const sd_bus_vtable *v;
1591         struct node *n;
1592         int r;
1593
1594         assert_return(bus, -EINVAL);
1595         assert_return(object_path_is_valid(path), -EINVAL);
1596         assert_return(interface_name_is_valid(interface), -EINVAL);
1597         assert_return(vtable, -EINVAL);
1598         assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
1599         assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
1600         assert_return(!bus_pid_changed(bus), -ECHILD);
1601         assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
1602                       !streq(interface, "org.freedesktop.DBus.Introspectable") &&
1603                       !streq(interface, "org.freedesktop.DBus.Peer") &&
1604                       !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL);
1605
1606         r = hashmap_ensure_allocated(&bus->vtable_methods, &vtable_member_hash_ops);
1607         if (r < 0)
1608                 return r;
1609
1610         r = hashmap_ensure_allocated(&bus->vtable_properties, &vtable_member_hash_ops);
1611         if (r < 0)
1612                 return r;
1613
1614         n = bus_node_allocate(bus, path);
1615         if (!n)
1616                 return -ENOMEM;
1617
1618         LIST_FOREACH(vtables, i, n->vtables) {
1619                 if (i->is_fallback != fallback) {
1620                         r = -EPROTOTYPE;
1621                         goto fail;
1622                 }
1623
1624                 if (streq(i->interface, interface)) {
1625
1626                         if (i->vtable == vtable) {
1627                                 r = -EEXIST;
1628                                 goto fail;
1629                         }
1630
1631                         existing = i;
1632                 }
1633         }
1634
1635         s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata);
1636         if (!s) {
1637                 r = -ENOMEM;
1638                 goto fail;
1639         }
1640
1641         s->node_vtable.is_fallback = fallback;
1642         s->node_vtable.vtable = vtable;
1643         s->node_vtable.find = find;
1644
1645         s->node_vtable.interface = strdup(interface);
1646         if (!s->node_vtable.interface) {
1647                 r = -ENOMEM;
1648                 goto fail;
1649         }
1650
1651         for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
1652
1653                 switch (v->type) {
1654
1655                 case _SD_BUS_VTABLE_METHOD: {
1656                         struct vtable_member *m;
1657
1658                         if (!member_name_is_valid(v->x.method.member) ||
1659                             !signature_is_valid(strempty(v->x.method.signature), false) ||
1660                             !signature_is_valid(strempty(v->x.method.result), false) ||
1661                             !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) ||
1662                             v->flags & (SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) {
1663                                 r = -EINVAL;
1664                                 goto fail;
1665                         }
1666
1667                         m = new0(struct vtable_member, 1);
1668                         if (!m) {
1669                                 r = -ENOMEM;
1670                                 goto fail;
1671                         }
1672
1673                         m->parent = &s->node_vtable;
1674                         m->path = n->path;
1675                         m->interface = s->node_vtable.interface;
1676                         m->member = v->x.method.member;
1677                         m->vtable = v;
1678
1679                         r = hashmap_put(bus->vtable_methods, m, m);
1680                         if (r < 0) {
1681                                 free(m);
1682                                 goto fail;
1683                         }
1684
1685                         break;
1686                 }
1687
1688                 case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
1689
1690                         if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) {
1691                                 r = -EINVAL;
1692                                 goto fail;
1693                         }
1694
1695                         if (v->flags & SD_BUS_VTABLE_PROPERTY_CONST) {
1696                                 r = -EINVAL;
1697                                 goto fail;
1698                         }
1699
1700                         /* Fall through */
1701
1702                 case _SD_BUS_VTABLE_PROPERTY: {
1703                         struct vtable_member *m;
1704
1705                         if (!member_name_is_valid(v->x.property.member) ||
1706                             !signature_is_single(v->x.property.signature, false) ||
1707                             !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) ||
1708                             v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
1709                             (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 ||
1710                             (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) {
1711                                 r = -EINVAL;
1712                                 goto fail;
1713                         }
1714
1715                         m = new0(struct vtable_member, 1);
1716                         if (!m) {
1717                                 r = -ENOMEM;
1718                                 goto fail;
1719                         }
1720
1721                         m->parent = &s->node_vtable;
1722                         m->path = n->path;
1723                         m->interface = s->node_vtable.interface;
1724                         m->member = v->x.property.member;
1725                         m->vtable = v;
1726
1727                         r = hashmap_put(bus->vtable_properties, m, m);
1728                         if (r < 0) {
1729                                 free(m);
1730                                 goto fail;
1731                         }
1732
1733                         break;
1734                 }
1735
1736                 case _SD_BUS_VTABLE_SIGNAL:
1737
1738                         if (!member_name_is_valid(v->x.signal.member) ||
1739                             !signature_is_valid(strempty(v->x.signal.signature), false) ||
1740                             v->flags & SD_BUS_VTABLE_UNPRIVILEGED) {
1741                                 r = -EINVAL;
1742                                 goto fail;
1743                         }
1744
1745                         break;
1746
1747                 default:
1748                         r = -EINVAL;
1749                         goto fail;
1750                 }
1751         }
1752
1753         s->node_vtable.node = n;
1754         LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable);
1755         bus->nodes_modified = true;
1756
1757         if (slot)
1758                 *slot = s;
1759
1760         return 0;
1761
1762 fail:
1763         sd_bus_slot_unref(s);
1764         bus_node_gc(bus, n);
1765
1766         return r;
1767 }
1768
1769 _public_ int sd_bus_add_object_vtable(
1770                 sd_bus *bus,
1771                 sd_bus_slot **slot,
1772                 const char *path,
1773                 const char *interface,
1774                 const sd_bus_vtable *vtable,
1775                 void *userdata) {
1776
1777         return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata);
1778 }
1779
1780 _public_ int sd_bus_add_fallback_vtable(
1781                 sd_bus *bus,
1782                 sd_bus_slot **slot,
1783                 const char *prefix,
1784                 const char *interface,
1785                 const sd_bus_vtable *vtable,
1786                 sd_bus_object_find_t find,
1787                 void *userdata) {
1788
1789         return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata);
1790 }
1791
1792 _public_ int sd_bus_add_node_enumerator(
1793                 sd_bus *bus,
1794                 sd_bus_slot **slot,
1795                 const char *path,
1796                 sd_bus_node_enumerator_t callback,
1797                 void *userdata) {
1798
1799         sd_bus_slot *s;
1800         struct node *n;
1801         int r;
1802
1803         assert_return(bus, -EINVAL);
1804         assert_return(object_path_is_valid(path), -EINVAL);
1805         assert_return(callback, -EINVAL);
1806         assert_return(!bus_pid_changed(bus), -ECHILD);
1807
1808         n = bus_node_allocate(bus, path);
1809         if (!n)
1810                 return -ENOMEM;
1811
1812         s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata);
1813         if (!s) {
1814                 r = -ENOMEM;
1815                 goto fail;
1816         }
1817
1818         s->node_enumerator.callback = callback;
1819
1820         s->node_enumerator.node = n;
1821         LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator);
1822         bus->nodes_modified = true;
1823
1824         if (slot)
1825                 *slot = s;
1826
1827         return 0;
1828
1829 fail:
1830         sd_bus_slot_unref(s);
1831         bus_node_gc(bus, n);
1832
1833         return r;
1834 }
1835
1836 static int emit_properties_changed_on_interface(
1837                 sd_bus *bus,
1838                 const char *prefix,
1839                 const char *path,
1840                 const char *interface,
1841                 bool require_fallback,
1842                 bool *found_interface,
1843                 char **names) {
1844
1845         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1846         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1847         bool has_invalidating = false, has_changing = false;
1848         struct vtable_member key = {};
1849         struct node_vtable *c;
1850         struct node *n;
1851         char **property;
1852         void *u = NULL;
1853         int r;
1854
1855         assert(bus);
1856         assert(prefix);
1857         assert(path);
1858         assert(interface);
1859         assert(found_interface);
1860
1861         n = hashmap_get(bus->nodes, prefix);
1862         if (!n)
1863                 return 0;
1864
1865         r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
1866         if (r < 0)
1867                 return r;
1868
1869         r = sd_bus_message_append(m, "s", interface);
1870         if (r < 0)
1871                 return r;
1872
1873         r = sd_bus_message_open_container(m, 'a', "{sv}");
1874         if (r < 0)
1875                 return r;
1876
1877         key.path = prefix;
1878         key.interface = interface;
1879
1880         LIST_FOREACH(vtables, c, n->vtables) {
1881                 if (require_fallback && !c->is_fallback)
1882                         continue;
1883
1884                 if (!streq(c->interface, interface))
1885                         continue;
1886
1887                 r = node_vtable_get_userdata(bus, path, c, &u, &error);
1888                 if (r < 0)
1889                         return r;
1890                 if (bus->nodes_modified)
1891                         return 0;
1892                 if (r == 0)
1893                         continue;
1894
1895                 *found_interface = true;
1896
1897                 if (names) {
1898                         /* If the caller specified a list of
1899                          * properties we include exactly those in the
1900                          * PropertiesChanged message */
1901
1902                         STRV_FOREACH(property, names) {
1903                                 struct vtable_member *v;
1904
1905                                 assert_return(member_name_is_valid(*property), -EINVAL);
1906
1907                                 key.member = *property;
1908                                 v = hashmap_get(bus->vtable_properties, &key);
1909                                 if (!v)
1910                                         return -ENOENT;
1911
1912                                 /* If there are two vtables for the same
1913                                  * interface, let's handle this property when
1914                                  * we come to that vtable. */
1915                                 if (c != v->parent)
1916                                         continue;
1917
1918                                 assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE ||
1919                                               v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION, -EDOM);
1920
1921                                 assert_return(!(v->vtable->flags & SD_BUS_VTABLE_HIDDEN), -EDOM);
1922
1923                                 if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
1924                                         has_invalidating = true;
1925                                         continue;
1926                                 }
1927
1928                                 has_changing = true;
1929
1930                                 r = vtable_append_one_property(bus, m, m->path, c, v->vtable, u, &error);
1931                                 if (r < 0)
1932                                         return r;
1933                                 if (bus->nodes_modified)
1934                                         return 0;
1935                         }
1936                 } else {
1937                         const sd_bus_vtable *v;
1938
1939                         /* If the caller specified no properties list
1940                          * we include all properties that are marked
1941                          * as changing in the message. */
1942
1943                         for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
1944                                 if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
1945                                         continue;
1946
1947                                 if (v->flags & SD_BUS_VTABLE_HIDDEN)
1948                                         continue;
1949
1950                                 if (v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
1951                                         has_invalidating = true;
1952                                         continue;
1953                                 }
1954
1955                                 if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
1956                                         continue;
1957
1958                                 has_changing = true;
1959
1960                                 r = vtable_append_one_property(bus, m, m->path, c, v, u, &error);
1961                                 if (r < 0)
1962                                         return r;
1963                                 if (bus->nodes_modified)
1964                                         return 0;
1965                         }
1966                 }
1967         }
1968
1969         if (!has_invalidating && !has_changing)
1970                 return 0;
1971
1972         r = sd_bus_message_close_container(m);
1973         if (r < 0)
1974                 return r;
1975
1976         r = sd_bus_message_open_container(m, 'a', "s");
1977         if (r < 0)
1978                 return r;
1979
1980         if (has_invalidating) {
1981                 LIST_FOREACH(vtables, c, n->vtables) {
1982                         if (require_fallback && !c->is_fallback)
1983                                 continue;
1984
1985                         if (!streq(c->interface, interface))
1986                                 continue;
1987
1988                         r = node_vtable_get_userdata(bus, path, c, &u, &error);
1989                         if (r < 0)
1990                                 return r;
1991                         if (bus->nodes_modified)
1992                                 return 0;
1993                         if (r == 0)
1994                                 continue;
1995
1996                         if (names) {
1997                                 STRV_FOREACH(property, names) {
1998                                         struct vtable_member *v;
1999
2000                                         key.member = *property;
2001                                         assert_se(v = hashmap_get(bus->vtable_properties, &key));
2002                                         assert(c == v->parent);
2003
2004                                         if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
2005                                                 continue;
2006
2007                                         r = sd_bus_message_append(m, "s", *property);
2008                                         if (r < 0)
2009                                                 return r;
2010                                 }
2011                         } else {
2012                                 const sd_bus_vtable *v;
2013
2014                                 for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
2015                                         if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
2016                                                 continue;
2017
2018                                         if (v->flags & SD_BUS_VTABLE_HIDDEN)
2019                                                 continue;
2020
2021                                         if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
2022                                                 continue;
2023
2024                                         r = sd_bus_message_append(m, "s", v->x.property.member);
2025                                         if (r < 0)
2026                                                 return r;
2027                                 }
2028                         }
2029                 }
2030         }
2031
2032         r = sd_bus_message_close_container(m);
2033         if (r < 0)
2034                 return r;
2035
2036         r = sd_bus_send(bus, m, NULL);
2037         if (r < 0)
2038                 return r;
2039
2040         return 1;
2041 }
2042
2043 _public_ int sd_bus_emit_properties_changed_strv(
2044                 sd_bus *bus,
2045                 const char *path,
2046                 const char *interface,
2047                 char **names) {
2048
2049         BUS_DONT_DESTROY(bus);
2050         bool found_interface = false;
2051         char *prefix;
2052         int r;
2053
2054         assert_return(bus, -EINVAL);
2055         assert_return(object_path_is_valid(path), -EINVAL);
2056         assert_return(interface_name_is_valid(interface), -EINVAL);
2057         assert_return(!bus_pid_changed(bus), -ECHILD);
2058
2059         if (!BUS_IS_OPEN(bus->state))
2060                 return -ENOTCONN;
2061
2062         /* A non-NULL but empty names list means nothing needs to be
2063            generated. A NULL list OTOH indicates that all properties
2064            that are set to EMITS_CHANGE or EMITS_INVALIDATION shall be
2065            included in the PropertiesChanged message. */
2066         if (names && names[0] == NULL)
2067                 return 0;
2068
2069         do {
2070                 bus->nodes_modified = false;
2071
2072                 r = emit_properties_changed_on_interface(bus, path, path, interface, false, &found_interface, names);
2073                 if (r != 0)
2074                         return r;
2075                 if (bus->nodes_modified)
2076                         continue;
2077
2078                 prefix = alloca(strlen(path) + 1);
2079                 OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
2080                         r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names);
2081                         if (r != 0)
2082                                 return r;
2083                         if (bus->nodes_modified)
2084                                 break;
2085                 }
2086
2087         } while (bus->nodes_modified);
2088
2089         return found_interface ? 0 : -ENOENT;
2090 }
2091
2092 _public_ int sd_bus_emit_properties_changed(
2093                 sd_bus *bus,
2094                 const char *path,
2095                 const char *interface,
2096                 const char *name, ...)  {
2097
2098         char **names;
2099
2100         assert_return(bus, -EINVAL);
2101         assert_return(object_path_is_valid(path), -EINVAL);
2102         assert_return(interface_name_is_valid(interface), -EINVAL);
2103         assert_return(!bus_pid_changed(bus), -ECHILD);
2104
2105         if (!BUS_IS_OPEN(bus->state))
2106                 return -ENOTCONN;
2107
2108         if (!name)
2109                 return 0;
2110
2111         names = strv_from_stdarg_alloca(name);
2112
2113         return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
2114 }
2115
2116 static int interfaces_added_append_one_prefix(
2117                 sd_bus *bus,
2118                 sd_bus_message *m,
2119                 const char *prefix,
2120                 const char *path,
2121                 const char *interface,
2122                 bool require_fallback) {
2123
2124         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2125         bool found_interface = false;
2126         struct node_vtable *c;
2127         struct node *n;
2128         void *u = NULL;
2129         int r;
2130
2131         assert(bus);
2132         assert(m);
2133         assert(prefix);
2134         assert(path);
2135         assert(interface);
2136
2137         n = hashmap_get(bus->nodes, prefix);
2138         if (!n)
2139                 return 0;
2140
2141         LIST_FOREACH(vtables, c, n->vtables) {
2142                 if (require_fallback && !c->is_fallback)
2143                         continue;
2144
2145                 if (!streq(c->interface, interface))
2146                         continue;
2147
2148                 r = node_vtable_get_userdata(bus, path, c, &u, &error);
2149                 if (r < 0)
2150                         return r;
2151                 if (bus->nodes_modified)
2152                         return 0;
2153                 if (r == 0)
2154                         continue;
2155
2156                 if (!found_interface) {
2157                         r = sd_bus_message_append_basic(m, 's', interface);
2158                         if (r < 0)
2159                                 return r;
2160
2161                         r = sd_bus_message_open_container(m, 'a', "{sv}");
2162                         if (r < 0)
2163                                 return r;
2164
2165                         found_interface = true;
2166                 }
2167
2168                 r = vtable_append_all_properties(bus, m, path, c, u, &error);
2169                 if (r < 0)
2170                         return r;
2171                 if (bus->nodes_modified)
2172                         return 0;
2173         }
2174
2175         if (found_interface) {
2176                 r = sd_bus_message_close_container(m);
2177                 if (r < 0)
2178                         return r;
2179         }
2180
2181         return found_interface;
2182 }
2183
2184 static int interfaces_added_append_one(
2185                 sd_bus *bus,
2186                 sd_bus_message *m,
2187                 const char *path,
2188                 const char *interface) {
2189
2190         char *prefix;
2191         int r;
2192
2193         assert(bus);
2194         assert(m);
2195         assert(path);
2196         assert(interface);
2197
2198         r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false);
2199         if (r != 0)
2200                 return r;
2201         if (bus->nodes_modified)
2202                 return 0;
2203
2204         prefix = alloca(strlen(path) + 1);
2205         OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
2206                 r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
2207                 if (r != 0)
2208                         return r;
2209                 if (bus->nodes_modified)
2210                         return 0;
2211         }
2212
2213         return -ENOENT;
2214 }
2215
2216 _public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
2217         BUS_DONT_DESTROY(bus);
2218
2219         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2220         char **i;
2221         int r;
2222
2223         assert_return(bus, -EINVAL);
2224         assert_return(object_path_is_valid(path), -EINVAL);
2225         assert_return(!bus_pid_changed(bus), -ECHILD);
2226
2227         if (!BUS_IS_OPEN(bus->state))
2228                 return -ENOTCONN;
2229
2230         if (strv_isempty(interfaces))
2231                 return 0;
2232
2233         do {
2234                 bus->nodes_modified = false;
2235                 m = sd_bus_message_unref(m);
2236
2237                 r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
2238                 if (r < 0)
2239                         return r;
2240
2241                 r = sd_bus_message_append_basic(m, 'o', path);
2242                 if (r < 0)
2243                         return r;
2244
2245                 r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
2246                 if (r < 0)
2247                         return r;
2248
2249                 STRV_FOREACH(i, interfaces) {
2250                         assert_return(interface_name_is_valid(*i), -EINVAL);
2251
2252                         r = sd_bus_message_open_container(m, 'e', "sa{sv}");
2253                         if (r < 0)
2254                                 return r;
2255
2256                         r = interfaces_added_append_one(bus, m, path, *i);
2257                         if (r < 0)
2258                                 return r;
2259
2260                         if (bus->nodes_modified)
2261                                 break;
2262
2263                         r = sd_bus_message_close_container(m);
2264                         if (r < 0)
2265                                 return r;
2266                 }
2267
2268                 if (bus->nodes_modified)
2269                         continue;
2270
2271                 r = sd_bus_message_close_container(m);
2272                 if (r < 0)
2273                         return r;
2274
2275         } while (bus->nodes_modified);
2276
2277         return sd_bus_send(bus, m, NULL);
2278 }
2279
2280 _public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
2281         char **interfaces;
2282
2283         assert_return(bus, -EINVAL);
2284         assert_return(object_path_is_valid(path), -EINVAL);
2285         assert_return(!bus_pid_changed(bus), -ECHILD);
2286
2287         if (!BUS_IS_OPEN(bus->state))
2288                 return -ENOTCONN;
2289
2290         interfaces = strv_from_stdarg_alloca(interface);
2291
2292         return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
2293 }
2294
2295 _public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
2296         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2297         int r;
2298
2299         assert_return(bus, -EINVAL);
2300         assert_return(object_path_is_valid(path), -EINVAL);
2301         assert_return(!bus_pid_changed(bus), -ECHILD);
2302
2303         if (!BUS_IS_OPEN(bus->state))
2304                 return -ENOTCONN;
2305
2306         if (strv_isempty(interfaces))
2307                 return 0;
2308
2309         r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
2310         if (r < 0)
2311                 return r;
2312
2313         r = sd_bus_message_append_basic(m, 'o', path);
2314         if (r < 0)
2315                 return r;
2316
2317         r = sd_bus_message_append_strv(m, interfaces);
2318         if (r < 0)
2319                 return r;
2320
2321         return sd_bus_send(bus, m, NULL);
2322 }
2323
2324 _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
2325         char **interfaces;
2326
2327         assert_return(bus, -EINVAL);
2328         assert_return(object_path_is_valid(path), -EINVAL);
2329         assert_return(!bus_pid_changed(bus), -ECHILD);
2330
2331         if (!BUS_IS_OPEN(bus->state))
2332                 return -ENOTCONN;
2333
2334         interfaces = strv_from_stdarg_alloca(interface);
2335
2336         return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
2337 }
2338
2339 _public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) {
2340         sd_bus_slot *s;
2341         struct node *n;
2342         int r;
2343
2344         assert_return(bus, -EINVAL);
2345         assert_return(object_path_is_valid(path), -EINVAL);
2346         assert_return(!bus_pid_changed(bus), -ECHILD);
2347
2348         n = bus_node_allocate(bus, path);
2349         if (!n)
2350                 return -ENOMEM;
2351
2352         s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL);
2353         if (!s) {
2354                 r = -ENOMEM;
2355                 goto fail;
2356         }
2357
2358         s->node_object_manager.node = n;
2359         LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager);
2360         bus->nodes_modified = true;
2361
2362         if (slot)
2363                 *slot = s;
2364
2365         return 0;
2366
2367 fail:
2368         sd_bus_slot_unref(s);
2369         bus_node_gc(bus, n);
2370
2371         return r;
2372 }