chiark / gitweb /
5f218c17ea0f5ad38eba33e74e325231e30be2f5
[elogind.git] / src / libsystemd-bus / bus-control.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 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <stddef.h>
27 #include <errno.h>
28
29 #include "strv.h"
30
31 #include "sd-bus.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-control.h"
35 #include "bus-bloom.h"
36 #include "bus-util.h"
37
38 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
39         int r;
40
41         assert_return(bus, -EINVAL);
42         assert_return(unique, -EINVAL);
43         assert_return(!bus_pid_changed(bus), -ECHILD);
44
45         r = bus_ensure_running(bus);
46         if (r < 0)
47                 return r;
48
49         *unique = bus->unique_name;
50         return 0;
51 }
52
53 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
54         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
55         uint32_t ret;
56         int r;
57
58         assert_return(bus, -EINVAL);
59         assert_return(name, -EINVAL);
60         assert_return(bus->bus_client, -EINVAL);
61         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
62         assert_return(!bus_pid_changed(bus), -ECHILD);
63
64         if (bus->is_kernel) {
65                 struct kdbus_cmd_name *n;
66                 size_t l;
67
68                 l = strlen(name);
69                 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
70                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
71                 n->flags = flags;
72                 memcpy(n->name, name, l+1);
73
74 #ifdef HAVE_VALGRIND_MEMCHECK_H
75                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
76 #endif
77
78                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
79                 if (r < 0) {
80                         if (errno == -EALREADY)
81                                 return SD_BUS_NAME_ALREADY_OWNER;
82
83                         if (errno == -EEXIST)
84                                 return SD_BUS_NAME_EXISTS;
85
86                         return -errno;
87                 }
88
89                 if (n->flags & KDBUS_NAME_IN_QUEUE)
90                         return SD_BUS_NAME_IN_QUEUE;
91
92                 return SD_BUS_NAME_PRIMARY_OWNER;
93         } else {
94                 r = sd_bus_call_method(
95                                 bus,
96                                 "org.freedesktop.DBus",
97                                 "/",
98                                 "org.freedesktop.DBus",
99                                 "RequestName",
100                                 NULL,
101                                 &reply,
102                                 "su",
103                                 name,
104                                 flags);
105                 if (r < 0)
106                         return r;
107
108                 r = sd_bus_message_read(reply, "u", &ret);
109                 if (r < 0)
110                         return r;
111
112                 return ret;
113         }
114 }
115
116 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
117         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
118         uint32_t ret;
119         int r;
120
121         assert_return(bus, -EINVAL);
122         assert_return(name, -EINVAL);
123         assert_return(bus->bus_client, -EINVAL);
124         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
125         assert_return(!bus_pid_changed(bus), -ECHILD);
126
127         if (bus->is_kernel) {
128                 struct kdbus_cmd_name *n;
129                 size_t l;
130
131                 l = strlen(name);
132                 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
133                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
134                 memcpy(n->name, name, l+1);
135
136 #ifdef HAVE_VALGRIND_MEMCHECK_H
137                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
138 #endif
139                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
140                 if (r < 0)
141                         return -errno;
142
143                 return n->flags;
144         } else {
145                 r = sd_bus_call_method(
146                                 bus,
147                                 "org.freedesktop.DBus",
148                                 "/",
149                                 "org.freedesktop.DBus",
150                                 "ReleaseName",
151                                 NULL,
152                                 &reply,
153                                 "s",
154                                 name);
155                 if (r < 0)
156                         return r;
157
158                 r = sd_bus_message_read(reply, "u", &ret);
159                 if (r < 0)
160                         return r;
161         }
162
163         return ret;
164 }
165
166 _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
167         _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
168         char **x = NULL;
169         int r;
170
171         assert_return(bus, -EINVAL);
172         assert_return(l, -EINVAL);
173         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
174         assert_return(!bus_pid_changed(bus), -ECHILD);
175
176         if (bus->is_kernel) {
177                 _cleanup_free_ struct kdbus_cmd_names *names = NULL;
178                 struct kdbus_cmd_name *name;
179                 size_t size;
180
181                 /* assume 8k size first. If that doesn't suffice, kdbus will tell us
182                  * how big the buffer needs to be.  */
183                 size = 8192;
184
185                 for(;;) {
186                         names = realloc(names, size);
187                         if (!names)
188                                 return -ENOMEM;
189
190                         names->size = size;
191                         names->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
192
193                         r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
194                         if (r < 0) {
195                                 if (errno == ENOBUFS && size != names->size) {
196                                         size = names->size;
197                                         continue;
198                                 }
199
200                                 return -errno;
201                         }
202
203                         break;
204                 }
205
206                 KDBUS_PART_FOREACH(name, names, names) {
207                         char *n;
208
209                         if (name->size > sizeof(*name))
210                                 n = name->name;
211                         else
212                                 asprintf(&n, ":1.%llu", (unsigned long long) name->id);
213
214                         r = strv_extend(&x, n);
215                         if (r < 0)
216                                 return -ENOMEM;
217                 }
218
219                 *l = x;
220         } else {
221                 r = sd_bus_call_method(
222                                 bus,
223                                 "org.freedesktop.DBus",
224                                 "/",
225                                 "org.freedesktop.DBus",
226                                 "ListNames",
227                                 NULL,
228                                 &reply1,
229                                 NULL);
230                 if (r < 0)
231                         return r;
232
233                 r = sd_bus_call_method(
234                                 bus,
235                                 "org.freedesktop.DBus",
236                                 "/",
237                                 "org.freedesktop.DBus",
238                                 "ListActivatableNames",
239                                 NULL,
240                                 &reply2,
241                                 NULL);
242                 if (r < 0)
243                         return r;
244
245                 r = bus_message_read_strv_extend(reply1, &x);
246                 if (r < 0) {
247                         strv_free(x);
248                         return r;
249                 }
250
251                 r = bus_message_read_strv_extend(reply2, &x);
252                 if (r < 0) {
253                         strv_free(x);
254                         return r;
255                 }
256
257                 *l = strv_uniq(x);
258         }
259
260         return 0;
261 }
262
263 _public_ int sd_bus_get_owner(
264                 sd_bus *bus,
265                 const char *name,
266                 uint64_t mask,
267                 char **owner,
268                 sd_bus_creds **creds) {
269
270         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
271         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
272         _cleanup_free_ char *unique = NULL;
273         pid_t pid = 0;
274         int r;
275
276         assert_return(bus, -EINVAL);
277         assert_return(name, -EINVAL);
278         assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
279         assert_return(mask == 0 || creds, -EINVAL);
280         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
281         assert_return(!bus_pid_changed(bus), -ECHILD);
282
283         /* Only query the owner if the caller wants to know it or if
284          * the caller just wants to check whether a name exists */
285         if (owner || mask == 0) {
286                 const char *found;
287
288                 r = sd_bus_call_method(
289                                 bus,
290                                 "org.freedesktop.DBus",
291                                 "/",
292                                 "org.freedesktop.DBus",
293                                 "GetNameOwner",
294                                 NULL,
295                                 &reply,
296                                 "s",
297                                 name);
298                 if (r < 0)
299                         return r;
300
301                 r = sd_bus_message_read(reply, "s", &found);
302                 if (r < 0)
303                         return r;
304
305                 unique = strdup(found);
306                 if (!unique)
307                         return -ENOMEM;
308
309                 reply = sd_bus_message_unref(reply);
310         }
311
312         if (mask != 0) {
313                 c = bus_creds_new();
314                 if (!c)
315                         return -ENOMEM;
316
317                 if ((mask & SD_BUS_CREDS_PID) ||
318                     mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
319                         uint32_t u;
320
321                         r = sd_bus_call_method(
322                                         bus,
323                                         "org.freedesktop.DBus",
324                                         "/",
325                                         "org.freedesktop.DBus",
326                                         "GetConnectionUnixProcessID",
327                                         NULL,
328                                         &reply,
329                                         "s",
330                                         name);
331                         if (r < 0)
332                                 return r;
333
334                         r = sd_bus_message_read(reply, "u", &u);
335                         if (r < 0)
336                                 return r;
337
338                         pid = u;
339                         if (mask & SD_BUS_CREDS_PID) {
340                                 c->pid = u;
341                                 c->mask |= SD_BUS_CREDS_PID;
342                         }
343
344                         reply = sd_bus_message_unref(reply);
345                 }
346
347                 if (mask & SD_BUS_CREDS_UID) {
348                         uint32_t u;
349
350                         r = sd_bus_call_method(
351                                         bus,
352                                         "org.freedesktop.DBus",
353                                         "/",
354                                         "org.freedesktop.DBus",
355                                         "GetConnectionUnixUser",
356                                         NULL,
357                                         &reply,
358                                         "s",
359                                         name);
360                         if (r < 0)
361                                 return r;
362
363                         r = sd_bus_message_read(reply, "u", &u);
364                         if (r < 0)
365                                 return r;
366
367                         c->uid = u;
368                         c->mask |= SD_BUS_CREDS_UID;
369
370                         reply = sd_bus_message_unref(reply);
371                 }
372
373                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
374                         const void *p;
375                         size_t sz;
376
377                         r = sd_bus_call_method(
378                                         bus,
379                                         "org.freedesktop.DBus",
380                                         "/",
381                                         "org.freedesktop.DBus",
382                                         "GetConnectionSELinuxSecurityContext",
383                                         NULL,
384                                         &reply,
385                                         "s",
386                                         name);
387                         if (r < 0)
388                                 return r;
389
390                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
391                         if (r < 0)
392                                 return r;
393
394                         c->label = strndup(p, sz);
395                         if (!c->label)
396                                 return -ENOMEM;
397
398                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
399                 }
400
401                 r = bus_creds_add_more(c, mask, pid, 0);
402                 if (r < 0)
403                         return r;
404         }
405
406         if (creds) {
407                 *creds = c;
408                 c = NULL;
409         }
410
411         if (owner) {
412                 *owner = unique;
413                 unique = NULL;
414         }
415
416         return 0;
417 }
418
419 static int add_name_change_match(sd_bus *bus,
420                                  uint64_t cookie,
421                                  const char *name,
422                                  const char *old_owner,
423                                  const char *new_owner) {
424
425         uint64_t name_id = 0, old_owner_id = 0, new_owner_id = 0;
426         int is_name_id = -1, r;
427         struct kdbus_item *item;
428
429         assert(bus);
430
431         /* If we encounter a match that could match against
432          * NameOwnerChanged messages, then we need to create
433          * KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE} and
434          * KDBUS_MATCH_ID_{ADD,REMOVE} matches for it, possibly
435          * multiple if the match is underspecified.
436          *
437          * The NameOwnerChanged signals take three parameters with
438          * unique or well-known names, but only some forms actually
439          * exist:
440          *
441          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_MATCH_NAME_ADD
442          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_MATCH_NAME_REMOVE
443          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_MATCH_NAME_CHANGE
444          * UNIQUE, "", UNIQUE          â†’ KDBUS_MATCH_ID_ADD
445          * UNIQUE, UNIQUE, ""          â†’ KDBUS_MATCH_ID_REMOVE
446          *
447          * For the latter two the two unique names must be identical.
448          *
449          * */
450
451         if (name) {
452                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
453                 if (is_name_id < 0)
454                         return 0;
455         }
456
457         if (old_owner) {
458                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
459                 if (r < 0)
460                         return 0;
461                 if (r == 0)
462                         return 0;
463                 if (is_name_id > 0 && old_owner_id != name_id)
464                         return 0;
465         }
466
467         if (new_owner) {
468                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
469                 if (r < 0)
470                         return r;
471                 if (r == 0)
472                         return 0;
473                 if (is_name_id > 0 && new_owner_id != name_id)
474                         return 0;
475         }
476
477         if (is_name_id <= 0) {
478                 size_t sz, l;
479
480                 /* If the name argument is missing or is a well-known
481                  * name, then add KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE}
482                  * matches for it */
483
484                 l = name ? strlen(name) : 0;
485
486                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
487                             offsetof(struct kdbus_item, name_change) +
488                             offsetof(struct kdbus_notify_name_change, name) +
489                             l+1);
490
491                 {
492                         union {
493                                 uint8_t buffer[sz];
494                                 struct kdbus_cmd_match match;
495                         } m;
496
497                         memzero(&m, sz);
498
499                         m.match.size = sz;
500                         m.match.cookie = cookie;
501                         m.match.src_id = KDBUS_SRC_ID_KERNEL;
502
503                         item = m.match.items;
504                         item->size =
505                                 offsetof(struct kdbus_item, name_change) +
506                                 offsetof(struct kdbus_notify_name_change, name) +
507                                 l+1;
508
509                         item->name_change.old_id = old_owner_id;
510                         item->name_change.new_id = new_owner_id;
511
512                         if (name)
513                                 strcpy(item->name_change.name, name);
514
515                         /* If the old name is unset or empty, then
516                          * this can match against added names */
517                         if (!old_owner || old_owner[0] == 0) {
518                                 item->type = KDBUS_MATCH_NAME_ADD;
519
520                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
521                                 if (r < 0)
522                                         return -errno;
523                         }
524
525                         /* If the new name is unset or empty, then
526                          * this can match against removed names */
527                         if (!new_owner || new_owner[0] == 0) {
528                                 item->type = KDBUS_MATCH_NAME_REMOVE;
529
530                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
531                                 if (r < 0)
532                                         return -errno;
533                         }
534
535                         /* If the neither name is explicitly set to
536                          * the empty string, then this can match
537                          * agains changed names */
538                         if (!(old_owner && old_owner[0] == 0) &&
539                             !(new_owner && new_owner[0] == 0)) {
540                                 item->type = KDBUS_MATCH_NAME_CHANGE;
541
542                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
543                                 if (r < 0)
544                                         return -errno;
545                         }
546                 }
547         }
548
549         if (is_name_id != 0) {
550                 uint64_t sz =
551                         ALIGN8(offsetof(struct kdbus_cmd_match, items) +
552                                offsetof(struct kdbus_item, id_change) +
553                                sizeof(struct kdbus_notify_id_change));
554                 union {
555                         uint8_t buffer[sz];
556                         struct kdbus_cmd_match match;
557                 } m;
558
559                 /* If the name argument is missing or is a unique
560                  * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
561                  * for it */
562
563                 memzero(&m, sz);
564
565                 m.match.size = sz;
566                 m.match.cookie = cookie;
567                 m.match.src_id = KDBUS_SRC_ID_KERNEL;
568
569                 item = m.match.items;
570                 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
571                 item->id_change.id = name_id;
572
573                 /* If the old name is unset or empty, then this can
574                  * match against added ids */
575                 if (!old_owner || old_owner[0] == 0) {
576                         item->type = KDBUS_MATCH_ID_ADD;
577
578                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
579                         if (r < 0)
580                                 return -errno;
581                 }
582
583                 /* If thew new name is unset or empty, then this can
584                 match against removed ids */
585                 if (!new_owner || new_owner[0] == 0) {
586                         item->type = KDBUS_MATCH_ID_REMOVE;
587
588                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
589                         if (r < 0)
590                                 return -errno;
591                 }
592         }
593
594         return 0;
595 }
596
597 int bus_add_match_internal(
598                 sd_bus *bus,
599                 const char *match,
600                 struct bus_match_component *components,
601                 unsigned n_components,
602                 uint64_t cookie) {
603
604         int r;
605
606         assert(bus);
607         assert(match);
608
609         if (bus->is_kernel) {
610                 struct kdbus_cmd_match *m;
611                 struct kdbus_item *item;
612                 uint64_t bloom[BLOOM_SIZE/8];
613                 size_t sz;
614                 const char *sender = NULL;
615                 size_t sender_length = 0;
616                 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
617                 bool using_bloom = false;
618                 unsigned i;
619                 bool matches_name_change = true;
620                 const char *name_change_arg[3] = {};
621
622                 zero(bloom);
623
624                 sz = offsetof(struct kdbus_cmd_match, items);
625
626                 for (i = 0; i < n_components; i++) {
627                         struct bus_match_component *c = &components[i];
628
629                         switch (c->type) {
630
631                         case BUS_MATCH_SENDER:
632                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
633                                         matches_name_change = false;
634
635                                 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
636                                 if (r < 0)
637                                         return r;
638
639                                 if (r > 0) {
640                                         sender = c->value_str;
641                                         sender_length = strlen(sender);
642                                         sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
643                                 }
644
645                                 break;
646
647                         case BUS_MATCH_MESSAGE_TYPE:
648                                 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
649                                         matches_name_change = false;
650
651                                 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
652                                 using_bloom = true;
653                                 break;
654
655                         case BUS_MATCH_INTERFACE:
656                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
657                                         matches_name_change = false;
658
659                                 bloom_add_pair(bloom, "interface", c->value_str);
660                                 using_bloom = true;
661                                 break;
662
663                         case BUS_MATCH_MEMBER:
664                                 if (!streq(c->value_str, "NameOwnerChanged"))
665                                         matches_name_change = false;
666
667                                 bloom_add_pair(bloom, "member", c->value_str);
668                                 using_bloom = true;
669                                 break;
670
671                         case BUS_MATCH_PATH:
672                                 if (!streq(c->value_str, "/org/freedesktop/DBus"))
673                                         matches_name_change = false;
674
675                                 bloom_add_pair(bloom, "path", c->value_str);
676                                 using_bloom = true;
677                                 break;
678
679                         case BUS_MATCH_PATH_NAMESPACE:
680                                 if (!streq(c->value_str, "/")) {
681                                         bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
682                                         using_bloom = true;
683                                 }
684                                 break;
685
686                         case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
687                                 char buf[sizeof("arg")-1 + 2 + 1];
688
689                                 if (c->type - BUS_MATCH_ARG < 3)
690                                         name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
691
692                                 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
693                                 bloom_add_pair(bloom, buf, c->value_str);
694                                 using_bloom = true;
695                                 break;
696                         }
697
698                         case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
699                                 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
700
701                                 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
702                                 bloom_add_pair(bloom, buf, c->value_str);
703                                 using_bloom = true;
704                                 break;
705                         }
706
707                         case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
708                                 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
709
710                                 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
711                                 bloom_add_pair(bloom, buf, c->value_str);
712                                 using_bloom = true;
713                                 break;
714                         }
715
716                         case BUS_MATCH_DESTINATION:
717                                 /* The bloom filter does not include
718                                    the destination, since it is only
719                                    available for broadcast messages
720                                    which do not carry a destination
721                                    since they are undirected. */
722                                 break;
723
724                         case BUS_MATCH_ROOT:
725                         case BUS_MATCH_VALUE:
726                         case BUS_MATCH_LEAF:
727                         case _BUS_MATCH_NODE_TYPE_MAX:
728                         case _BUS_MATCH_NODE_TYPE_INVALID:
729                                 assert_not_reached("Invalid match type?");
730                         }
731                 }
732
733                 if (using_bloom)
734                         sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
735
736                 m = alloca0(sz);
737                 m->size = sz;
738                 m->cookie = cookie;
739                 m->src_id = src_id;
740
741                 item = m->items;
742
743                 if (using_bloom) {
744                         item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
745                         item->type = KDBUS_MATCH_BLOOM;
746                         memcpy(item->data64, bloom, BLOOM_SIZE);
747
748                         item = KDBUS_PART_NEXT(item);
749                 }
750
751                 if (sender) {
752                         item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
753                         item->type = KDBUS_MATCH_SRC_NAME;
754                         memcpy(item->str, sender, sender_length + 1);
755                 }
756
757                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
758                 if (r < 0)
759                         return -errno;
760
761                 if (matches_name_change) {
762
763                         /* If this match could theoretically match
764                          * NameOwnerChanged messages, we need to
765                          * install a second non-bloom filter explitly
766                          * for it */
767
768                         r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
769                         if (r < 0)
770                                 return r;
771                 }
772
773                 return 0;
774         } else
775                 return sd_bus_call_method(
776                                 bus,
777                                 "org.freedesktop.DBus",
778                                 "/",
779                                 "org.freedesktop.DBus",
780                                 "AddMatch",
781                                 NULL,
782                                 NULL,
783                                 "s",
784                                 match);
785 }
786
787 int bus_remove_match_internal(
788                 sd_bus *bus,
789                 const char *match,
790                 uint64_t cookie) {
791
792         int r;
793
794         assert(bus);
795         assert(match);
796
797         if (bus->is_kernel) {
798                 struct kdbus_cmd_match m;
799
800                 zero(m);
801                 m.size = offsetof(struct kdbus_cmd_match, items);
802                 m.cookie = cookie;
803
804                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
805                 if (r < 0)
806                         return -errno;
807
808                 return 0;
809
810         } else {
811                 return sd_bus_call_method(
812                                 bus,
813                                 "org.freedesktop.DBus",
814                                 "/",
815                                 "org.freedesktop.DBus",
816                                 "RemoveMatch",
817                                 NULL,
818                                 NULL,
819                                 "s",
820                                 match);
821         }
822 }
823
824 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
825         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
826         const char *mid;
827         int r;
828
829         assert_return(bus, -EINVAL);
830         assert_return(name, -EINVAL);
831         assert_return(machine, -EINVAL);
832         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
833         assert_return(!bus_pid_changed(bus), -ECHILD);
834
835         if (streq_ptr(name, bus->unique_name))
836                 return sd_id128_get_machine(machine);
837
838         r = sd_bus_message_new_method_call(
839                         bus,
840                         name,
841                         "/",
842                         "org.freedesktop.DBus.Peer",
843                         "GetMachineId", &m);
844         if (r < 0)
845                 return r;
846
847         r = sd_bus_message_set_no_auto_start(m, true);
848         if (r < 0)
849                 return r;
850
851         r = sd_bus_call(bus, m, 0, NULL, &reply);
852         if (r < 0)
853                 return r;
854
855         r = sd_bus_message_read(reply, "s", &mid);
856         if (r < 0)
857                 return r;
858
859         return sd_id128_from_string(mid, machine);
860 }