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