chiark / gitweb /
bus: when filtering by sender take well known names lest from attached creds into...
[elogind.git] / src / libsystemd-bus / bus-match.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 "bus-internal.h"
23 #include "bus-message.h"
24 #include "bus-match.h"
25 #include "bus-error.h"
26 #include "bus-util.h"
27 #include "strv.h"
28
29 /* Example:
30  *
31  *  A: type=signal,sender=foo,interface=bar
32  *  B: type=signal,sender=quux,interface=fips
33  *  C: type=signal,sender=quux,interface=waldo
34  *  D: type=signal,member=test
35  *  E: sender=miau
36  *  F: type=signal
37  *  G: type=signal
38  *
39  *  results in this tree:
40  *
41  *  BUS_MATCH_ROOT
42  *  + BUS_MATCH_MESSAGE_TYPE
43  *  | ` BUS_MATCH_VALUE: value == signal
44  *  |   + DBUS_MATCH_SENDER
45  *  |   | + BUS_MATCH_VALUE: value == foo
46  *  |   | | ` DBUS_MATCH_INTERFACE
47  *  |   | |   ` BUS_MATCH_VALUE: value == bar
48  *  |   | |     ` BUS_MATCH_LEAF: A
49  *  |   | ` BUS_MATCH_VALUE: value == quux
50  *  |   |   ` DBUS_MATCH_INTERFACE
51  *  |   |     | BUS_MATCH_VALUE: value == fips
52  *  |   |     | ` BUS_MATCH_LEAF: B
53  *  |   |     ` BUS_MATCH_VALUE: value == waldo
54  *  |   |       ` BUS_MATCH_LEAF: C
55  *  |   + DBUS_MATCH_MEMBER
56  *  |   | ` BUS_MATCH_VALUE: value == test
57  *  |   |   ` BUS_MATCH_LEAF: D
58  *  |   + BUS_MATCH_LEAF: F
59  *  |   ` BUS_MATCH_LEAF: G
60  *  ` BUS_MATCH_SENDER
61  *    ` BUS_MATCH_VALUE: value == miau
62  *      ` BUS_MATCH_LEAF: E
63  */
64
65 static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) {
66         return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_NAMESPACE_LAST;
67 }
68
69 static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) {
70         return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) ||
71                 (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST);
72 }
73
74 static void bus_match_node_free(struct bus_match_node *node) {
75         assert(node);
76         assert(node->parent);
77         assert(!node->child);
78         assert(node->type != BUS_MATCH_ROOT);
79         assert(node->type < _BUS_MATCH_NODE_TYPE_MAX);
80
81         if (node->parent->child) {
82                 /* We are apparently linked into the parent's child
83                  * list. Let's remove us from there. */
84                 if (node->prev) {
85                         assert(node->prev->next == node);
86                         node->prev->next = node->next;
87                 } else {
88                         assert(node->parent->child == node);
89                         node->parent->child = node->next;
90                 }
91
92                 if (node->next)
93                         node->next->prev = node->prev;
94         }
95
96         if (node->type == BUS_MATCH_VALUE) {
97                 /* We might be in the parent's hash table, so clean
98                  * this up */
99
100                 if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
101                         hashmap_remove(node->parent->compare.children, UINT_TO_PTR(node->value.u8));
102                 else if (BUS_MATCH_CAN_HASH(node->parent->type) && node->value.str)
103                         hashmap_remove(node->parent->compare.children, node->value.str);
104
105                 free(node->value.str);
106         }
107
108         if (BUS_MATCH_IS_COMPARE(node->type)) {
109                 assert(hashmap_isempty(node->compare.children));
110                 hashmap_free(node->compare.children);
111         }
112
113         free(node);
114 }
115
116 static bool bus_match_node_maybe_free(struct bus_match_node *node) {
117         assert(node);
118
119         if (node->child)
120                 return false;
121
122         if (BUS_MATCH_IS_COMPARE(node->type) && !hashmap_isempty(node->compare.children))
123                 return true;
124
125         bus_match_node_free(node);
126         return true;
127 }
128
129 static bool value_node_test(
130                 struct bus_match_node *node,
131                 enum bus_match_node_type parent_type,
132                 uint8_t value_u8,
133                 const char *value_str,
134                 sd_bus_message *m) {
135
136         assert(node);
137         assert(node->type == BUS_MATCH_VALUE);
138
139         /* Tests parameters against this value node, doing prefix
140          * magic and stuff. */
141
142         switch (parent_type) {
143
144         case BUS_MATCH_MESSAGE_TYPE:
145                 return node->value.u8 == value_u8;
146
147         case BUS_MATCH_SENDER:
148                 if (streq_ptr(node->value.str, value_str))
149                         return true;
150
151                 if (m->creds.mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
152                         char **i;
153
154                         /* on kdbus we have the well known names list
155                          * in the credentials, let's make use of that
156                          * for an accurate match */
157
158                         STRV_FOREACH(i, m->creds.well_known_names)
159                                 if (streq_ptr(node->value.str, *i))
160                                         return true;
161
162                 } else {
163
164                         /* If we don't have kdbus, we don't know the
165                          * well-known names of the senders. In that,
166                          * let's just hope that dbus-daemon doesn't
167                          * send us stuff we didn't want. */
168
169                         if (node->value.str[0] != ':' && value_str && value_str[0] == ':')
170                                 return true;
171                 }
172
173                 return false;
174
175         case BUS_MATCH_DESTINATION:
176         case BUS_MATCH_INTERFACE:
177         case BUS_MATCH_MEMBER:
178         case BUS_MATCH_PATH:
179         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
180                 return streq_ptr(node->value.str, value_str);
181
182         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
183                 return namespace_simple_pattern(node->value.str, value_str);
184
185         case BUS_MATCH_PATH_NAMESPACE:
186                 return path_simple_pattern(node->value.str, value_str);
187
188         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
189                 return path_complex_pattern(node->value.str, value_str);
190
191         default:
192                 assert_not_reached("Invalid node type");
193         }
194 }
195
196 static bool value_node_same(
197                 struct bus_match_node *node,
198                 enum bus_match_node_type parent_type,
199                 uint8_t value_u8,
200                 const char *value_str) {
201
202         /* Tests parameters against this value node, not doing prefix
203          * magic and stuff, i.e. this one actually compares the match
204          * itself.*/
205
206         assert(node);
207         assert(node->type == BUS_MATCH_VALUE);
208
209         switch (parent_type) {
210
211         case BUS_MATCH_MESSAGE_TYPE:
212                 return node->value.u8 == value_u8;
213
214         case BUS_MATCH_SENDER:
215         case BUS_MATCH_DESTINATION:
216         case BUS_MATCH_INTERFACE:
217         case BUS_MATCH_MEMBER:
218         case BUS_MATCH_PATH:
219         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
220         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
221         case BUS_MATCH_PATH_NAMESPACE:
222         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
223                 return streq(node->value.str, value_str);
224
225         default:
226                 assert_not_reached("Invalid node type");
227         }
228 }
229
230 int bus_match_run(
231                 sd_bus *bus,
232                 struct bus_match_node *node,
233                 sd_bus_message *m) {
234
235
236         const char *test_str = NULL;
237         uint8_t test_u8 = 0;
238         int r;
239
240         assert(m);
241
242         if (!node)
243                 return 0;
244
245         if (bus && bus->match_callbacks_modified)
246                 return 0;
247
248         /* Not these special semantics: when traversing the tree we
249          * usually let bus_match_run() when called for a node
250          * recursively invoke bus_match_run(). There's are two
251          * exceptions here though, which are BUS_NODE_ROOT (which
252          * cannot have a sibling), and BUS_NODE_VALUE (whose siblings
253          * are invoked anyway by its parent. */
254
255         switch (node->type) {
256
257         case BUS_MATCH_ROOT:
258
259                 /* Run all children. Since we cannot have any siblings
260                  * we won't call any. The children of the root node
261                  * are compares or leaves, they will automatically
262                  * call their siblings. */
263                 return bus_match_run(bus, node->child, m);
264
265         case BUS_MATCH_VALUE:
266
267                 /* Run all children. We don't execute any siblings, we
268                  * assume our caller does that. The children of value
269                  * nodes are compares or leaves, they will
270                  * automatically call their siblings */
271
272                 assert(node->child);
273                 return bus_match_run(bus, node->child, m);
274
275         case BUS_MATCH_LEAF:
276
277                 if (bus) {
278                         if (node->leaf.last_iteration == bus->iteration_counter)
279                                 return 0;
280
281                         node->leaf.last_iteration = bus->iteration_counter;
282                 }
283
284                 r = sd_bus_message_rewind(m, true);
285                 if (r < 0)
286                         return r;
287
288                 /* Run the callback. And then invoke siblings. */
289                 if (node->leaf.callback) {
290                         _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
291
292                         r = node->leaf.callback(bus, m, node->leaf.userdata, &error_buffer);
293                         r = bus_maybe_reply_error(m, r, &error_buffer);
294                         if (r != 0)
295                                 return r;
296                 }
297
298                 return bus_match_run(bus, node->next, m);
299
300         case BUS_MATCH_MESSAGE_TYPE:
301                 test_u8 = m->header->type;
302                 break;
303
304         case BUS_MATCH_SENDER:
305                 test_str = m->sender;
306                 /* FIXME: resolve test_str from a well-known to a unique name first */
307                 break;
308
309         case BUS_MATCH_DESTINATION:
310                 test_str = m->destination;
311                 break;
312
313         case BUS_MATCH_INTERFACE:
314                 test_str = m->interface;
315                 break;
316
317         case BUS_MATCH_MEMBER:
318                 test_str = m->member;
319                 break;
320
321         case BUS_MATCH_PATH:
322         case BUS_MATCH_PATH_NAMESPACE:
323                 test_str = m->path;
324                 break;
325
326         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
327                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG);
328                 break;
329
330         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
331                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH);
332                 break;
333
334         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
335                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE);
336                 break;
337
338         default:
339                 assert_not_reached("Unknown match type.");
340         }
341
342         if (BUS_MATCH_CAN_HASH(node->type)) {
343                 struct bus_match_node *found;
344
345                 /* Lookup via hash table, nice! So let's jump directly. */
346
347                 if (test_str)
348                         found = hashmap_get(node->compare.children, test_str);
349                 else if (node->type == BUS_MATCH_MESSAGE_TYPE)
350                         found = hashmap_get(node->compare.children, UINT_TO_PTR(test_u8));
351                 else
352                         found = NULL;
353
354                 if (found) {
355                         r = bus_match_run(bus, found, m);
356                         if (r != 0)
357                                 return r;
358                 }
359         } else {
360                 struct bus_match_node *c;
361
362                 /* No hash table, so let's iterate manually... */
363
364                 for (c = node->child; c; c = c->next) {
365                         if (!value_node_test(c, node->type, test_u8, test_str, m))
366                                 continue;
367
368                         r = bus_match_run(bus, c, m);
369                         if (r != 0)
370                                 return r;
371                 }
372         }
373
374         if (bus && bus->match_callbacks_modified)
375                 return 0;
376
377         /* And now, let's invoke our siblings */
378         return bus_match_run(bus, node->next, m);
379 }
380
381 static int bus_match_add_compare_value(
382                 struct bus_match_node *where,
383                 enum bus_match_node_type t,
384                 uint8_t value_u8,
385                 const char *value_str,
386                 struct bus_match_node **ret) {
387
388         struct bus_match_node *c = NULL, *n = NULL;
389         int r;
390
391         assert(where);
392         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
393         assert(BUS_MATCH_IS_COMPARE(t));
394         assert(ret);
395
396         for (c = where->child; c && c->type != t; c = c->next)
397                 ;
398
399         if (c) {
400                 /* Comparison node already exists? Then let's see if
401                  * the value node exists too. */
402
403                 if (t == BUS_MATCH_MESSAGE_TYPE)
404                         n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
405                 else if (BUS_MATCH_CAN_HASH(t))
406                         n = hashmap_get(c->compare.children, value_str);
407                 else {
408                         for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
409                                 ;
410                 }
411
412                 if (n) {
413                         *ret = n;
414                         return 0;
415                 }
416         } else {
417                 /* Comparison node, doesn't exist yet? Then let's
418                  * create it. */
419
420                 c = new0(struct bus_match_node, 1);
421                 if (!c) {
422                         r = -ENOMEM;
423                         goto fail;
424                 }
425
426                 c->type = t;
427                 c->parent = where;
428                 c->next = where->child;
429                 if (c->next)
430                         c->next->prev = c;
431                 where->child = c;
432
433                 if (t == BUS_MATCH_MESSAGE_TYPE) {
434                         c->compare.children = hashmap_new(trivial_hash_func, trivial_compare_func);
435                         if (!c->compare.children) {
436                                 r = -ENOMEM;
437                                 goto fail;
438                         }
439                 } else if (BUS_MATCH_CAN_HASH(t)) {
440                         c->compare.children = hashmap_new(string_hash_func, string_compare_func);
441                         if (!c->compare.children) {
442                                 r = -ENOMEM;
443                                 goto fail;
444                         }
445                 }
446         }
447
448         n = new0(struct bus_match_node, 1);
449         if (!n) {
450                 r = -ENOMEM;
451                 goto fail;
452         }
453
454         n->type = BUS_MATCH_VALUE;
455         n->value.u8 = value_u8;
456         if (value_str) {
457                 n->value.str = strdup(value_str);
458                 if (!n->value.str) {
459                         r = -ENOMEM;
460                         goto fail;
461                 }
462         }
463
464         n->parent = c;
465         if (c->compare.children) {
466
467                 if (t == BUS_MATCH_MESSAGE_TYPE)
468                         r = hashmap_put(c->compare.children, UINT_TO_PTR(value_u8), n);
469                 else
470                         r = hashmap_put(c->compare.children, n->value.str, n);
471
472                 if (r < 0)
473                         goto fail;
474         } else {
475                 n->next = c->child;
476                 if (n->next)
477                         n->next->prev = n;
478                 c->child = n;
479         }
480
481         *ret = n;
482         return 1;
483
484 fail:
485         if (c)
486                 bus_match_node_maybe_free(c);
487
488         if (n) {
489                 free(n->value.str);
490                 free(n);
491         }
492
493         return r;
494 }
495
496 static int bus_match_find_compare_value(
497                 struct bus_match_node *where,
498                 enum bus_match_node_type t,
499                 uint8_t value_u8,
500                 const char *value_str,
501                 struct bus_match_node **ret) {
502
503         struct bus_match_node *c, *n;
504
505         assert(where);
506         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
507         assert(BUS_MATCH_IS_COMPARE(t));
508         assert(ret);
509
510         for (c = where->child; c && c->type != t; c = c->next)
511                 ;
512
513         if (!c)
514                 return 0;
515
516         if (t == BUS_MATCH_MESSAGE_TYPE)
517                 n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
518         else if (BUS_MATCH_CAN_HASH(t))
519                 n = hashmap_get(c->compare.children, value_str);
520         else {
521                 for (n = c->child; !value_node_same(n, t, value_u8, value_str); n = n->next)
522                         ;
523         }
524
525         if (n) {
526                 *ret = n;
527                 return 1;
528         }
529
530         return 0;
531 }
532
533 static int bus_match_add_leaf(
534                 struct bus_match_node *where,
535                 sd_bus_message_handler_t callback,
536                 void *userdata,
537                 uint64_t cookie,
538                 struct bus_match_node **ret) {
539
540         struct bus_match_node *n;
541
542         assert(where);
543         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
544         assert(ret);
545
546         n = new0(struct bus_match_node, 1);
547         if (!n)
548                 return -ENOMEM;
549
550         n->type = BUS_MATCH_LEAF;
551         n->parent = where;
552         n->next = where->child;
553         if (n->next)
554                 n->next->prev = n;
555         n->leaf.callback = callback;
556         n->leaf.userdata = userdata;
557         n->leaf.cookie = cookie;
558
559         where->child = n;
560
561         *ret = n;
562         return 1;
563 }
564
565 static int bus_match_find_leaf(
566                 struct bus_match_node *where,
567                 sd_bus_message_handler_t callback,
568                 void *userdata,
569                 struct bus_match_node **ret) {
570
571         struct bus_match_node *c;
572
573         assert(where);
574         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
575         assert(ret);
576
577         for (c = where->child; c; c = c->next) {
578                 if (c->type == BUS_MATCH_LEAF &&
579                     c->leaf.callback == callback &&
580                     c->leaf.userdata == userdata) {
581                         *ret = c;
582                         return 1;
583                 }
584         }
585
586         return 0;
587 }
588
589 enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) {
590         assert(k);
591
592         if (n == 4 && startswith(k, "type"))
593                 return BUS_MATCH_MESSAGE_TYPE;
594         if (n == 6 && startswith(k, "sender"))
595                 return BUS_MATCH_SENDER;
596         if (n == 11 && startswith(k, "destination"))
597                 return BUS_MATCH_DESTINATION;
598         if (n == 9 && startswith(k, "interface"))
599                 return BUS_MATCH_INTERFACE;
600         if (n == 6 && startswith(k, "member"))
601                 return BUS_MATCH_MEMBER;
602         if (n == 4 && startswith(k, "path"))
603                 return BUS_MATCH_PATH;
604         if (n == 14 && startswith(k, "path_namespace"))
605                 return BUS_MATCH_PATH_NAMESPACE;
606
607         if (n == 4 && startswith(k, "arg")) {
608                 int j;
609
610                 j = undecchar(k[3]);
611                 if (j < 0)
612                         return -EINVAL;
613
614                 return BUS_MATCH_ARG + j;
615         }
616
617         if (n == 5 && startswith(k, "arg")) {
618                 int a, b;
619                 enum bus_match_node_type t;
620
621                 a = undecchar(k[3]);
622                 b = undecchar(k[4]);
623                 if (a <= 0 || b < 0)
624                         return -EINVAL;
625
626                 t = BUS_MATCH_ARG + a * 10 + b;
627                 if (t > BUS_MATCH_ARG_LAST)
628                         return -EINVAL;
629
630                 return t;
631         }
632
633         if (n == 8 && startswith(k, "arg") && startswith(k + 4, "path")) {
634                 int j;
635
636                 j = undecchar(k[3]);
637                 if (j < 0)
638                         return -EINVAL;
639
640                 return BUS_MATCH_ARG_PATH + j;
641         }
642
643         if (n == 9 && startswith(k, "arg") && startswith(k + 5, "path")) {
644                 enum bus_match_node_type t;
645                 int a, b;
646
647                 a = undecchar(k[3]);
648                 b = undecchar(k[4]);
649                 if (a <= 0 || b < 0)
650                         return -EINVAL;
651
652                 t = BUS_MATCH_ARG_PATH + a * 10 + b;
653                 if (t > BUS_MATCH_ARG_PATH_LAST)
654                         return -EINVAL;
655
656                 return t;
657         }
658
659         if (n == 13 && startswith(k, "arg") && startswith(k + 4, "namespace")) {
660                 int j;
661
662                 j = undecchar(k[3]);
663                 if (j < 0)
664                         return -EINVAL;
665
666                 return BUS_MATCH_ARG_NAMESPACE + j;
667         }
668
669         if (n == 14 && startswith(k, "arg") && startswith(k + 5, "namespace")) {
670                 enum bus_match_node_type t;
671                 int a, b;
672
673                 a = undecchar(k[3]);
674                 b = undecchar(k[4]);
675                 if (a <= 0 || b < 0)
676                         return -EINVAL;
677
678                 t = BUS_MATCH_ARG_NAMESPACE + a * 10 + b;
679                 if (t > BUS_MATCH_ARG_NAMESPACE_LAST)
680                         return -EINVAL;
681
682                 return t;
683         }
684
685         return -EINVAL;
686 }
687
688 static int match_component_compare(const void *a, const void *b) {
689         const struct bus_match_component *x = a, *y = b;
690
691         if (x->type < y->type)
692                 return -1;
693         if (x->type > y->type)
694                 return 1;
695
696         return 0;
697 }
698
699 void bus_match_parse_free(struct bus_match_component *components, unsigned n_components) {
700         unsigned i;
701
702         for (i = 0; i < n_components; i++)
703                 free(components[i].value_str);
704
705         free(components);
706 }
707
708 int bus_match_parse(
709                 const char *match,
710                 struct bus_match_component **_components,
711                 unsigned *_n_components) {
712
713         const char *p = match;
714         struct bus_match_component *components = NULL;
715         size_t components_allocated = 0;
716         unsigned n_components = 0, i;
717         _cleanup_free_ char *value = NULL;
718         int r;
719
720         assert(match);
721         assert(_components);
722         assert(_n_components);
723
724         while (*p != 0) {
725                 const char *eq, *q;
726                 enum bus_match_node_type t;
727                 unsigned j = 0;
728                 size_t value_allocated = 0;
729                 bool escaped = false;
730                 uint8_t u;
731
732                 eq = strchr(p, '=');
733                 if (!eq)
734                         return -EINVAL;
735
736                 if (eq[1] != '\'')
737                         return -EINVAL;
738
739                 t = bus_match_node_type_from_string(p, eq - p);
740                 if (t < 0)
741                         return -EINVAL;
742
743                 for (q = eq + 2;; q++) {
744
745                         if (*q == 0) {
746                                 r = -EINVAL;
747                                 goto fail;
748                         }
749
750                         if (!escaped) {
751                                 if (*q == '\\') {
752                                         escaped = true;
753                                         continue;
754                                 }
755                                 if (*q == '\'') {
756                                         if (value)
757                                                 value[j] = 0;
758                                         break;
759                                 }
760                         }
761
762                         if (!GREEDY_REALLOC(value, value_allocated, j + 2)) {
763                                 r = -ENOMEM;
764                                 goto fail;
765                         }
766
767                         value[j++] = *q;
768                         escaped = false;
769                 }
770
771                 if (!value) {
772                         value = strdup("");
773                         if (!value) {
774                                 r = -ENOMEM;
775                                 goto fail;
776                         }
777                 }
778
779                 if (t == BUS_MATCH_MESSAGE_TYPE) {
780                         r = bus_message_type_from_string(value, &u);
781                         if (r < 0)
782                                 goto fail;
783
784                         free(value);
785                         value = NULL;
786                 } else
787                         u = 0;
788
789                 if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) {
790                         r = -ENOMEM;
791                         goto fail;
792                 }
793
794                 components[n_components].type = t;
795                 components[n_components].value_str = value;
796                 components[n_components].value_u8 = u;
797                 n_components++;
798
799                 value = NULL;
800
801                 if (q[1] == 0)
802                         break;
803
804                 if (q[1] != ',') {
805                         r = -EINVAL;
806                         goto fail;
807                 }
808
809                 p = q + 2;
810         }
811
812         /* Order the whole thing, so that we always generate the same tree */
813         qsort_safe(components, n_components, sizeof(struct bus_match_component), match_component_compare);
814
815         /* Check for duplicates */
816         for (i = 0; i+1 < n_components; i++)
817                 if (components[i].type == components[i+1].type) {
818                         r = -EINVAL;
819                         goto fail;
820                 }
821
822         *_components = components;
823         *_n_components = n_components;
824
825         return 0;
826
827 fail:
828         bus_match_parse_free(components, n_components);
829         return r;
830 }
831
832 char *bus_match_to_string(struct bus_match_component *components, unsigned n_components) {
833         _cleanup_free_ FILE *f = NULL;
834         char *buffer = NULL;
835         size_t size = 0;
836         unsigned i;
837
838         if (n_components <= 0)
839                 return strdup("");
840
841         assert(components);
842
843         f = open_memstream(&buffer, &size);
844         if (!f)
845                 return NULL;
846
847         for (i = 0; i < n_components; i++) {
848                 char buf[32];
849
850                 if (i != 0)
851                         fputc(',', f);
852
853                 fputs(bus_match_node_type_to_string(components[i].type, buf, sizeof(buf)), f);
854                 fputc('=', f);
855                 fputc('\'', f);
856
857                 if (components[i].type == BUS_MATCH_MESSAGE_TYPE)
858                         fputs(bus_message_type_to_string(components[i].value_u8), f);
859                 else
860                         fputs(components[i].value_str, f);
861
862                 fputc('\'', f);
863         }
864
865         fflush(f);
866         if (ferror(f))
867                 return NULL;
868
869         return buffer;
870 }
871
872 int bus_match_add(
873                 struct bus_match_node *root,
874                 struct bus_match_component *components,
875                 unsigned n_components,
876                 sd_bus_message_handler_t callback,
877                 void *userdata,
878                 uint64_t cookie,
879                 struct bus_match_node **ret) {
880
881         unsigned i;
882         struct bus_match_node *n;
883         int r;
884
885         assert(root);
886
887         n = root;
888         for (i = 0; i < n_components; i++) {
889                 r = bus_match_add_compare_value(
890                                 n, components[i].type,
891                                 components[i].value_u8, components[i].value_str, &n);
892                 if (r < 0)
893                         return r;
894         }
895
896         r = bus_match_add_leaf(n, callback, userdata, cookie, &n);
897         if (r < 0)
898                 return r;
899
900         if (ret)
901                 *ret = n;
902
903         return 0;
904 }
905
906 int bus_match_remove(
907                 struct bus_match_node *root,
908                 struct bus_match_component *components,
909                 unsigned n_components,
910                 sd_bus_message_handler_t callback,
911                 void *userdata,
912                 uint64_t *cookie) {
913
914         unsigned i;
915         struct bus_match_node *n, **gc;
916         int r;
917
918         assert(root);
919
920         gc = newa(struct bus_match_node*, n_components);
921
922         n = root;
923         for (i = 0; i < n_components; i++) {
924                 r = bus_match_find_compare_value(
925                                 n, components[i].type,
926                                 components[i].value_u8, components[i].value_str,
927                                 &n);
928                 if (r <= 0)
929                         return r;
930
931                 gc[i] = n;
932         }
933
934         r = bus_match_find_leaf(n, callback, userdata, &n);
935         if (r <= 0)
936                 return r;
937
938         if (cookie)
939                 *cookie = n->leaf.cookie;
940
941         /* Free the leaf */
942         bus_match_node_free(n);
943
944         /* Prune the tree above */
945         for (i = n_components; i > 0; i --) {
946                 struct bus_match_node *p = gc[i-1]->parent;
947
948                 if (!bus_match_node_maybe_free(gc[i-1]))
949                         break;
950
951                 if (!bus_match_node_maybe_free(p))
952                         break;
953         }
954
955         return r;
956 }
957
958 void bus_match_free(struct bus_match_node *node) {
959         struct bus_match_node *c;
960
961         if (!node)
962                 return;
963
964         if (BUS_MATCH_CAN_HASH(node->type)) {
965                 Iterator i;
966
967                 HASHMAP_FOREACH(c, node->compare.children, i)
968                         bus_match_free(c);
969
970                 assert(hashmap_isempty(node->compare.children));
971         }
972
973         while ((c = node->child))
974                 bus_match_free(c);
975
976         if (node->type != BUS_MATCH_ROOT)
977                 bus_match_node_free(node);
978 }
979
980 const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l) {
981         switch (t) {
982
983         case BUS_MATCH_ROOT:
984                 return "root";
985
986         case BUS_MATCH_VALUE:
987                 return "value";
988
989         case BUS_MATCH_LEAF:
990                 return "leaf";
991
992         case BUS_MATCH_MESSAGE_TYPE:
993                 return "type";
994
995         case BUS_MATCH_SENDER:
996                 return "sender";
997
998         case BUS_MATCH_DESTINATION:
999                 return "destination";
1000
1001         case BUS_MATCH_INTERFACE:
1002                 return "interface";
1003
1004         case BUS_MATCH_MEMBER:
1005                 return "member";
1006
1007         case BUS_MATCH_PATH:
1008                 return "path";
1009
1010         case BUS_MATCH_PATH_NAMESPACE:
1011                 return "path_namespace";
1012
1013         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
1014                 snprintf(buf, l, "arg%i", t - BUS_MATCH_ARG);
1015                 return buf;
1016
1017         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
1018                 snprintf(buf, l, "arg%ipath", t - BUS_MATCH_ARG_PATH);
1019                 return buf;
1020
1021         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
1022                 snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE);
1023                 return buf;
1024
1025         default:
1026                 return NULL;
1027         }
1028 }
1029
1030 void bus_match_dump(struct bus_match_node *node, unsigned level) {
1031         struct bus_match_node *c;
1032         _cleanup_free_ char *pfx = NULL;
1033         char buf[32];
1034
1035         if (!node)
1036                 return;
1037
1038         pfx = strrep("  ", level);
1039         printf("%s[%s]", strempty(pfx), bus_match_node_type_to_string(node->type, buf, sizeof(buf)));
1040
1041         if (node->type == BUS_MATCH_VALUE) {
1042                 if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
1043                         printf(" <%u>\n", node->value.u8);
1044                 else
1045                         printf(" <%s>\n", node->value.str);
1046         } else if (node->type == BUS_MATCH_ROOT)
1047                 puts(" root");
1048         else if (node->type == BUS_MATCH_LEAF)
1049                 printf(" %p/%p\n", node->leaf.callback, node->leaf.userdata);
1050         else
1051                 putchar('\n');
1052
1053         if (BUS_MATCH_CAN_HASH(node->type)) {
1054                 Iterator i;
1055
1056                 HASHMAP_FOREACH(c, node->compare.children, i)
1057                         bus_match_dump(c, level + 1);
1058         }
1059
1060         for (c = node->child; c; c = c->next)
1061                 bus_match_dump(c, level + 1);
1062 }