chiark / gitweb /
sd-bus: don't access invalid memory if a signal matcher was freed from its own callback
[elogind.git] / src / libsystemd / sd-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                         if (bus && bus->match_callbacks_modified)
298                                 return 0;
299                 }
300
301                 return bus_match_run(bus, node->next, m);
302
303         case BUS_MATCH_MESSAGE_TYPE:
304                 test_u8 = m->header->type;
305                 break;
306
307         case BUS_MATCH_SENDER:
308                 test_str = m->sender;
309                 /* FIXME: resolve test_str from a well-known to a unique name first */
310                 break;
311
312         case BUS_MATCH_DESTINATION:
313                 test_str = m->destination;
314                 break;
315
316         case BUS_MATCH_INTERFACE:
317                 test_str = m->interface;
318                 break;
319
320         case BUS_MATCH_MEMBER:
321                 test_str = m->member;
322                 break;
323
324         case BUS_MATCH_PATH:
325         case BUS_MATCH_PATH_NAMESPACE:
326                 test_str = m->path;
327                 break;
328
329         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
330                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG);
331                 break;
332
333         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
334                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH);
335                 break;
336
337         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
338                 test_str = bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE);
339                 break;
340
341         default:
342                 assert_not_reached("Unknown match type.");
343         }
344
345         if (BUS_MATCH_CAN_HASH(node->type)) {
346                 struct bus_match_node *found;
347
348                 /* Lookup via hash table, nice! So let's jump directly. */
349
350                 if (test_str)
351                         found = hashmap_get(node->compare.children, test_str);
352                 else if (node->type == BUS_MATCH_MESSAGE_TYPE)
353                         found = hashmap_get(node->compare.children, UINT_TO_PTR(test_u8));
354                 else
355                         found = NULL;
356
357                 if (found) {
358                         r = bus_match_run(bus, found, m);
359                         if (r != 0)
360                                 return r;
361                 }
362         } else {
363                 struct bus_match_node *c;
364
365                 /* No hash table, so let's iterate manually... */
366
367                 for (c = node->child; c; c = c->next) {
368                         if (!value_node_test(c, node->type, test_u8, test_str, m))
369                                 continue;
370
371                         r = bus_match_run(bus, c, m);
372                         if (r != 0)
373                                 return r;
374                 }
375         }
376
377         if (bus && bus->match_callbacks_modified)
378                 return 0;
379
380         /* And now, let's invoke our siblings */
381         return bus_match_run(bus, node->next, m);
382 }
383
384 static int bus_match_add_compare_value(
385                 struct bus_match_node *where,
386                 enum bus_match_node_type t,
387                 uint8_t value_u8,
388                 const char *value_str,
389                 struct bus_match_node **ret) {
390
391         struct bus_match_node *c = NULL, *n = NULL;
392         int r;
393
394         assert(where);
395         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
396         assert(BUS_MATCH_IS_COMPARE(t));
397         assert(ret);
398
399         for (c = where->child; c && c->type != t; c = c->next)
400                 ;
401
402         if (c) {
403                 /* Comparison node already exists? Then let's see if
404                  * the value node exists too. */
405
406                 if (t == BUS_MATCH_MESSAGE_TYPE)
407                         n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
408                 else if (BUS_MATCH_CAN_HASH(t))
409                         n = hashmap_get(c->compare.children, value_str);
410                 else {
411                         for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
412                                 ;
413                 }
414
415                 if (n) {
416                         *ret = n;
417                         return 0;
418                 }
419         } else {
420                 /* Comparison node, doesn't exist yet? Then let's
421                  * create it. */
422
423                 c = new0(struct bus_match_node, 1);
424                 if (!c) {
425                         r = -ENOMEM;
426                         goto fail;
427                 }
428
429                 c->type = t;
430                 c->parent = where;
431                 c->next = where->child;
432                 if (c->next)
433                         c->next->prev = c;
434                 where->child = c;
435
436                 if (t == BUS_MATCH_MESSAGE_TYPE) {
437                         c->compare.children = hashmap_new(trivial_hash_func, trivial_compare_func);
438                         if (!c->compare.children) {
439                                 r = -ENOMEM;
440                                 goto fail;
441                         }
442                 } else if (BUS_MATCH_CAN_HASH(t)) {
443                         c->compare.children = hashmap_new(string_hash_func, string_compare_func);
444                         if (!c->compare.children) {
445                                 r = -ENOMEM;
446                                 goto fail;
447                         }
448                 }
449         }
450
451         n = new0(struct bus_match_node, 1);
452         if (!n) {
453                 r = -ENOMEM;
454                 goto fail;
455         }
456
457         n->type = BUS_MATCH_VALUE;
458         n->value.u8 = value_u8;
459         if (value_str) {
460                 n->value.str = strdup(value_str);
461                 if (!n->value.str) {
462                         r = -ENOMEM;
463                         goto fail;
464                 }
465         }
466
467         n->parent = c;
468         if (c->compare.children) {
469
470                 if (t == BUS_MATCH_MESSAGE_TYPE)
471                         r = hashmap_put(c->compare.children, UINT_TO_PTR(value_u8), n);
472                 else
473                         r = hashmap_put(c->compare.children, n->value.str, n);
474
475                 if (r < 0)
476                         goto fail;
477         } else {
478                 n->next = c->child;
479                 if (n->next)
480                         n->next->prev = n;
481                 c->child = n;
482         }
483
484         *ret = n;
485         return 1;
486
487 fail:
488         if (c)
489                 bus_match_node_maybe_free(c);
490
491         if (n) {
492                 free(n->value.str);
493                 free(n);
494         }
495
496         return r;
497 }
498
499 static int bus_match_find_compare_value(
500                 struct bus_match_node *where,
501                 enum bus_match_node_type t,
502                 uint8_t value_u8,
503                 const char *value_str,
504                 struct bus_match_node **ret) {
505
506         struct bus_match_node *c, *n;
507
508         assert(where);
509         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
510         assert(BUS_MATCH_IS_COMPARE(t));
511         assert(ret);
512
513         for (c = where->child; c && c->type != t; c = c->next)
514                 ;
515
516         if (!c)
517                 return 0;
518
519         if (t == BUS_MATCH_MESSAGE_TYPE)
520                 n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
521         else if (BUS_MATCH_CAN_HASH(t))
522                 n = hashmap_get(c->compare.children, value_str);
523         else {
524                 for (n = c->child; !value_node_same(n, t, value_u8, value_str); n = n->next)
525                         ;
526         }
527
528         if (n) {
529                 *ret = n;
530                 return 1;
531         }
532
533         return 0;
534 }
535
536 static int bus_match_add_leaf(
537                 struct bus_match_node *where,
538                 sd_bus_message_handler_t callback,
539                 void *userdata,
540                 uint64_t cookie,
541                 struct bus_match_node **ret) {
542
543         struct bus_match_node *n;
544
545         assert(where);
546         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
547         assert(ret);
548
549         n = new0(struct bus_match_node, 1);
550         if (!n)
551                 return -ENOMEM;
552
553         n->type = BUS_MATCH_LEAF;
554         n->parent = where;
555         n->next = where->child;
556         if (n->next)
557                 n->next->prev = n;
558         n->leaf.callback = callback;
559         n->leaf.userdata = userdata;
560         n->leaf.cookie = cookie;
561
562         where->child = n;
563
564         *ret = n;
565         return 1;
566 }
567
568 static int bus_match_find_leaf(
569                 struct bus_match_node *where,
570                 sd_bus_message_handler_t callback,
571                 void *userdata,
572                 struct bus_match_node **ret) {
573
574         struct bus_match_node *c;
575
576         assert(where);
577         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
578         assert(ret);
579
580         for (c = where->child; c; c = c->next) {
581                 if (c->type == BUS_MATCH_LEAF &&
582                     c->leaf.callback == callback &&
583                     c->leaf.userdata == userdata) {
584                         *ret = c;
585                         return 1;
586                 }
587         }
588
589         return 0;
590 }
591
592 enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) {
593         assert(k);
594
595         if (n == 4 && startswith(k, "type"))
596                 return BUS_MATCH_MESSAGE_TYPE;
597         if (n == 6 && startswith(k, "sender"))
598                 return BUS_MATCH_SENDER;
599         if (n == 11 && startswith(k, "destination"))
600                 return BUS_MATCH_DESTINATION;
601         if (n == 9 && startswith(k, "interface"))
602                 return BUS_MATCH_INTERFACE;
603         if (n == 6 && startswith(k, "member"))
604                 return BUS_MATCH_MEMBER;
605         if (n == 4 && startswith(k, "path"))
606                 return BUS_MATCH_PATH;
607         if (n == 14 && startswith(k, "path_namespace"))
608                 return BUS_MATCH_PATH_NAMESPACE;
609
610         if (n == 4 && startswith(k, "arg")) {
611                 int j;
612
613                 j = undecchar(k[3]);
614                 if (j < 0)
615                         return -EINVAL;
616
617                 return BUS_MATCH_ARG + j;
618         }
619
620         if (n == 5 && startswith(k, "arg")) {
621                 int a, b;
622                 enum bus_match_node_type t;
623
624                 a = undecchar(k[3]);
625                 b = undecchar(k[4]);
626                 if (a <= 0 || b < 0)
627                         return -EINVAL;
628
629                 t = BUS_MATCH_ARG + a * 10 + b;
630                 if (t > BUS_MATCH_ARG_LAST)
631                         return -EINVAL;
632
633                 return t;
634         }
635
636         if (n == 8 && startswith(k, "arg") && startswith(k + 4, "path")) {
637                 int j;
638
639                 j = undecchar(k[3]);
640                 if (j < 0)
641                         return -EINVAL;
642
643                 return BUS_MATCH_ARG_PATH + j;
644         }
645
646         if (n == 9 && startswith(k, "arg") && startswith(k + 5, "path")) {
647                 enum bus_match_node_type t;
648                 int a, b;
649
650                 a = undecchar(k[3]);
651                 b = undecchar(k[4]);
652                 if (a <= 0 || b < 0)
653                         return -EINVAL;
654
655                 t = BUS_MATCH_ARG_PATH + a * 10 + b;
656                 if (t > BUS_MATCH_ARG_PATH_LAST)
657                         return -EINVAL;
658
659                 return t;
660         }
661
662         if (n == 13 && startswith(k, "arg") && startswith(k + 4, "namespace")) {
663                 int j;
664
665                 j = undecchar(k[3]);
666                 if (j < 0)
667                         return -EINVAL;
668
669                 return BUS_MATCH_ARG_NAMESPACE + j;
670         }
671
672         if (n == 14 && startswith(k, "arg") && startswith(k + 5, "namespace")) {
673                 enum bus_match_node_type t;
674                 int a, b;
675
676                 a = undecchar(k[3]);
677                 b = undecchar(k[4]);
678                 if (a <= 0 || b < 0)
679                         return -EINVAL;
680
681                 t = BUS_MATCH_ARG_NAMESPACE + a * 10 + b;
682                 if (t > BUS_MATCH_ARG_NAMESPACE_LAST)
683                         return -EINVAL;
684
685                 return t;
686         }
687
688         return -EINVAL;
689 }
690
691 static int match_component_compare(const void *a, const void *b) {
692         const struct bus_match_component *x = a, *y = b;
693
694         if (x->type < y->type)
695                 return -1;
696         if (x->type > y->type)
697                 return 1;
698
699         return 0;
700 }
701
702 void bus_match_parse_free(struct bus_match_component *components, unsigned n_components) {
703         unsigned i;
704
705         for (i = 0; i < n_components; i++)
706                 free(components[i].value_str);
707
708         free(components);
709 }
710
711 int bus_match_parse(
712                 const char *match,
713                 struct bus_match_component **_components,
714                 unsigned *_n_components) {
715
716         const char *p = match;
717         struct bus_match_component *components = NULL;
718         size_t components_allocated = 0;
719         unsigned n_components = 0, i;
720         _cleanup_free_ char *value = NULL;
721         int r;
722
723         assert(match);
724         assert(_components);
725         assert(_n_components);
726
727         while (*p != 0) {
728                 const char *eq, *q;
729                 enum bus_match_node_type t;
730                 unsigned j = 0;
731                 size_t value_allocated = 0;
732                 bool escaped = false, quoted;
733                 uint8_t u;
734
735                 eq = strchr(p, '=');
736                 if (!eq)
737                         return -EINVAL;
738
739                 t = bus_match_node_type_from_string(p, eq - p);
740                 if (t < 0)
741                         return -EINVAL;
742
743                 quoted = eq[1] == '\'';
744
745                 for (q = eq + 1 + quoted;; q++) {
746
747                         if (*q == 0) {
748
749                                 if (quoted) {
750                                         r = -EINVAL;
751                                         goto fail;
752                                 } else {
753                                         if (value)
754                                                 value[j] = 0;
755                                         break;
756                                 }
757                         }
758
759                         if (!escaped) {
760                                 if (*q == '\\') {
761                                         escaped = true;
762                                         continue;
763                                 }
764
765                                 if (quoted) {
766                                         if (*q == '\'') {
767                                                 if (value)
768                                                         value[j] = 0;
769                                                 break;
770                                         }
771                                 } else {
772                                         if (*q == ',') {
773                                                 if (value)
774                                                         value[j] = 0;
775
776                                                 break;
777                                         }
778                                 }
779                         }
780
781                         if (!GREEDY_REALLOC(value, value_allocated, j + 2)) {
782                                 r = -ENOMEM;
783                                 goto fail;
784                         }
785
786                         value[j++] = *q;
787                         escaped = false;
788                 }
789
790                 if (!value) {
791                         value = strdup("");
792                         if (!value) {
793                                 r = -ENOMEM;
794                                 goto fail;
795                         }
796                 }
797
798                 if (t == BUS_MATCH_MESSAGE_TYPE) {
799                         r = bus_message_type_from_string(value, &u);
800                         if (r < 0)
801                                 goto fail;
802
803                         free(value);
804                         value = NULL;
805                 } else
806                         u = 0;
807
808                 if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) {
809                         r = -ENOMEM;
810                         goto fail;
811                 }
812
813                 components[n_components].type = t;
814                 components[n_components].value_str = value;
815                 components[n_components].value_u8 = u;
816                 n_components++;
817
818                 value = NULL;
819
820                 if (q[quoted] == 0)
821                         break;
822
823                 if (q[quoted] != ',') {
824                         r = -EINVAL;
825                         goto fail;
826                 }
827
828                 p = q + 1 + quoted;
829         }
830
831         /* Order the whole thing, so that we always generate the same tree */
832         qsort_safe(components, n_components, sizeof(struct bus_match_component), match_component_compare);
833
834         /* Check for duplicates */
835         for (i = 0; i+1 < n_components; i++)
836                 if (components[i].type == components[i+1].type) {
837                         r = -EINVAL;
838                         goto fail;
839                 }
840
841         *_components = components;
842         *_n_components = n_components;
843
844         return 0;
845
846 fail:
847         bus_match_parse_free(components, n_components);
848         return r;
849 }
850
851 char *bus_match_to_string(struct bus_match_component *components, unsigned n_components) {
852         _cleanup_free_ FILE *f = NULL;
853         char *buffer = NULL;
854         size_t size = 0;
855         unsigned i;
856
857         if (n_components <= 0)
858                 return strdup("");
859
860         assert(components);
861
862         f = open_memstream(&buffer, &size);
863         if (!f)
864                 return NULL;
865
866         for (i = 0; i < n_components; i++) {
867                 char buf[32];
868
869                 if (i != 0)
870                         fputc(',', f);
871
872                 fputs(bus_match_node_type_to_string(components[i].type, buf, sizeof(buf)), f);
873                 fputc('=', f);
874                 fputc('\'', f);
875
876                 if (components[i].type == BUS_MATCH_MESSAGE_TYPE)
877                         fputs(bus_message_type_to_string(components[i].value_u8), f);
878                 else
879                         fputs(components[i].value_str, f);
880
881                 fputc('\'', f);
882         }
883
884         fflush(f);
885         if (ferror(f))
886                 return NULL;
887
888         return buffer;
889 }
890
891 int bus_match_add(
892                 struct bus_match_node *root,
893                 struct bus_match_component *components,
894                 unsigned n_components,
895                 sd_bus_message_handler_t callback,
896                 void *userdata,
897                 uint64_t cookie,
898                 struct bus_match_node **ret) {
899
900         unsigned i;
901         struct bus_match_node *n;
902         int r;
903
904         assert(root);
905
906         n = root;
907         for (i = 0; i < n_components; i++) {
908                 r = bus_match_add_compare_value(
909                                 n, components[i].type,
910                                 components[i].value_u8, components[i].value_str, &n);
911                 if (r < 0)
912                         return r;
913         }
914
915         r = bus_match_add_leaf(n, callback, userdata, cookie, &n);
916         if (r < 0)
917                 return r;
918
919         if (ret)
920                 *ret = n;
921
922         return 0;
923 }
924
925 int bus_match_remove(
926                 struct bus_match_node *root,
927                 struct bus_match_component *components,
928                 unsigned n_components,
929                 sd_bus_message_handler_t callback,
930                 void *userdata,
931                 uint64_t *cookie) {
932
933         unsigned i;
934         struct bus_match_node *n, **gc;
935         int r;
936
937         assert(root);
938
939         gc = newa(struct bus_match_node*, n_components);
940
941         n = root;
942         for (i = 0; i < n_components; i++) {
943                 r = bus_match_find_compare_value(
944                                 n, components[i].type,
945                                 components[i].value_u8, components[i].value_str,
946                                 &n);
947                 if (r <= 0)
948                         return r;
949
950                 gc[i] = n;
951         }
952
953         r = bus_match_find_leaf(n, callback, userdata, &n);
954         if (r <= 0)
955                 return r;
956
957         if (cookie)
958                 *cookie = n->leaf.cookie;
959
960         /* Free the leaf */
961         bus_match_node_free(n);
962
963         /* Prune the tree above */
964         for (i = n_components; i > 0; i --) {
965                 struct bus_match_node *p = gc[i-1]->parent;
966
967                 if (!bus_match_node_maybe_free(gc[i-1]))
968                         break;
969
970                 if (!bus_match_node_maybe_free(p))
971                         break;
972         }
973
974         return r;
975 }
976
977 void bus_match_free(struct bus_match_node *node) {
978         struct bus_match_node *c;
979
980         if (!node)
981                 return;
982
983         if (BUS_MATCH_CAN_HASH(node->type)) {
984                 Iterator i;
985
986                 HASHMAP_FOREACH(c, node->compare.children, i)
987                         bus_match_free(c);
988
989                 assert(hashmap_isempty(node->compare.children));
990         }
991
992         while ((c = node->child))
993                 bus_match_free(c);
994
995         if (node->type != BUS_MATCH_ROOT)
996                 bus_match_node_free(node);
997 }
998
999 const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l) {
1000         switch (t) {
1001
1002         case BUS_MATCH_ROOT:
1003                 return "root";
1004
1005         case BUS_MATCH_VALUE:
1006                 return "value";
1007
1008         case BUS_MATCH_LEAF:
1009                 return "leaf";
1010
1011         case BUS_MATCH_MESSAGE_TYPE:
1012                 return "type";
1013
1014         case BUS_MATCH_SENDER:
1015                 return "sender";
1016
1017         case BUS_MATCH_DESTINATION:
1018                 return "destination";
1019
1020         case BUS_MATCH_INTERFACE:
1021                 return "interface";
1022
1023         case BUS_MATCH_MEMBER:
1024                 return "member";
1025
1026         case BUS_MATCH_PATH:
1027                 return "path";
1028
1029         case BUS_MATCH_PATH_NAMESPACE:
1030                 return "path_namespace";
1031
1032         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
1033                 snprintf(buf, l, "arg%i", t - BUS_MATCH_ARG);
1034                 return buf;
1035
1036         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
1037                 snprintf(buf, l, "arg%ipath", t - BUS_MATCH_ARG_PATH);
1038                 return buf;
1039
1040         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
1041                 snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE);
1042                 return buf;
1043
1044         default:
1045                 return NULL;
1046         }
1047 }
1048
1049 void bus_match_dump(struct bus_match_node *node, unsigned level) {
1050         struct bus_match_node *c;
1051         _cleanup_free_ char *pfx = NULL;
1052         char buf[32];
1053
1054         if (!node)
1055                 return;
1056
1057         pfx = strrep("  ", level);
1058         printf("%s[%s]", strempty(pfx), bus_match_node_type_to_string(node->type, buf, sizeof(buf)));
1059
1060         if (node->type == BUS_MATCH_VALUE) {
1061                 if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
1062                         printf(" <%u>\n", node->value.u8);
1063                 else
1064                         printf(" <%s>\n", node->value.str);
1065         } else if (node->type == BUS_MATCH_ROOT)
1066                 puts(" root");
1067         else if (node->type == BUS_MATCH_LEAF)
1068                 printf(" %p/%p\n", node->leaf.callback, node->leaf.userdata);
1069         else
1070                 putchar('\n');
1071
1072         if (BUS_MATCH_CAN_HASH(node->type)) {
1073                 Iterator i;
1074
1075                 HASHMAP_FOREACH(c, node->compare.children, i)
1076                         bus_match_dump(c, level + 1);
1077         }
1078
1079         for (c = node->child; c; c = c->next)
1080                 bus_match_dump(c, level + 1);
1081 }