chiark / gitweb /
988d4265ffaf3beb94fdf14c36d5a5d8daefbb44
[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                 union {
554                         uint8_t buffer[sz];
555                         struct kdbus_cmd_match match;
556                 } m;
557
558                 /* If the name argument is missing or is a unique
559                  * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
560                  * for it */
561
562                 memzero(&m, sz);
563
564                 m.match.size = sz;
565                 m.match.cookie = cookie;
566                 m.match.src_id = KDBUS_SRC_ID_KERNEL;
567
568                 item = m.match.items;
569                 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
570                 item->id_change.id = name_id;
571
572                 /* If the old name is unset or empty, then this can
573                  * match against added ids */
574                 if (!old_owner || old_owner[0] == 0) {
575                         item->type = KDBUS_MATCH_ID_ADD;
576
577                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
578                         if (r < 0)
579                                 return -errno;
580                 }
581
582                 /* If thew new name is unset or empty, then this can
583                 match against removed ids */
584                 if (!new_owner || new_owner[0] == 0) {
585                         item->type = KDBUS_MATCH_ID_REMOVE;
586
587                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
588                         if (r < 0)
589                                 return -errno;
590                 }
591         }
592
593         return 0;
594 }
595
596 int bus_add_match_internal(
597                 sd_bus *bus,
598                 const char *match,
599                 struct bus_match_component *components,
600                 unsigned n_components,
601                 uint64_t cookie) {
602
603         int r;
604
605         assert(bus);
606         assert(match);
607
608         if (bus->is_kernel) {
609                 struct kdbus_cmd_match *m;
610                 struct kdbus_item *item;
611                 uint64_t bloom[BLOOM_SIZE/8];
612                 size_t sz;
613                 const char *sender = NULL;
614                 size_t sender_length = 0;
615                 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
616                 bool using_bloom = false;
617                 unsigned i;
618                 bool matches_name_change = true;
619                 const char *name_change_arg[3] = {};
620
621                 zero(bloom);
622
623                 sz = offsetof(struct kdbus_cmd_match, items);
624
625                 for (i = 0; i < n_components; i++) {
626                         struct bus_match_component *c = &components[i];
627
628                         switch (c->type) {
629
630                         case BUS_MATCH_SENDER:
631                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
632                                         matches_name_change = false;
633
634                                 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
635                                 if (r < 0)
636                                         return r;
637
638                                 if (r > 0) {
639                                         sender = c->value_str;
640                                         sender_length = strlen(sender);
641                                         sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
642                                 }
643
644                                 break;
645
646                         case BUS_MATCH_MESSAGE_TYPE:
647                                 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
648                                         matches_name_change = false;
649
650                                 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
651                                 using_bloom = true;
652                                 break;
653
654                         case BUS_MATCH_INTERFACE:
655                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
656                                         matches_name_change = false;
657
658                                 bloom_add_pair(bloom, "interface", c->value_str);
659                                 using_bloom = true;
660                                 break;
661
662                         case BUS_MATCH_MEMBER:
663                                 if (!streq(c->value_str, "NameOwnerChanged"))
664                                         matches_name_change = false;
665
666                                 bloom_add_pair(bloom, "member", c->value_str);
667                                 using_bloom = true;
668                                 break;
669
670                         case BUS_MATCH_PATH:
671                                 if (!streq(c->value_str, "/org/freedesktop/DBus"))
672                                         matches_name_change = false;
673
674                                 bloom_add_pair(bloom, "path", c->value_str);
675                                 using_bloom = true;
676                                 break;
677
678                         case BUS_MATCH_PATH_NAMESPACE:
679                                 if (!streq(c->value_str, "/")) {
680                                         bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
681                                         using_bloom = true;
682                                 }
683                                 break;
684
685                         case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
686                                 char buf[sizeof("arg")-1 + 2 + 1];
687
688                                 if (c->type - BUS_MATCH_ARG < 3)
689                                         name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
690
691                                 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
692                                 bloom_add_pair(bloom, buf, c->value_str);
693                                 using_bloom = true;
694                                 break;
695                         }
696
697                         case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
698                                 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
699
700                                 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
701                                 bloom_add_pair(bloom, buf, c->value_str);
702                                 using_bloom = true;
703                                 break;
704                         }
705
706                         case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
707                                 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
708
709                                 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
710                                 bloom_add_pair(bloom, buf, c->value_str);
711                                 using_bloom = true;
712                                 break;
713                         }
714
715                         case BUS_MATCH_DESTINATION:
716                                 /* The bloom filter does not include
717                                    the destination, since it is only
718                                    available for broadcast messages
719                                    which do not carry a destination
720                                    since they are undirected. */
721                                 break;
722
723                         case BUS_MATCH_ROOT:
724                         case BUS_MATCH_VALUE:
725                         case BUS_MATCH_LEAF:
726                         case _BUS_MATCH_NODE_TYPE_MAX:
727                         case _BUS_MATCH_NODE_TYPE_INVALID:
728                                 assert_not_reached("Invalid match type?");
729                         }
730                 }
731
732                 if (using_bloom)
733                         sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
734
735                 m = alloca0(sz);
736                 m->size = sz;
737                 m->cookie = cookie;
738                 m->src_id = src_id;
739
740                 item = m->items;
741
742                 if (using_bloom) {
743                         item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
744                         item->type = KDBUS_MATCH_BLOOM;
745                         memcpy(item->data64, bloom, BLOOM_SIZE);
746
747                         item = KDBUS_PART_NEXT(item);
748                 }
749
750                 if (sender) {
751                         item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
752                         item->type = KDBUS_MATCH_SRC_NAME;
753                         memcpy(item->str, sender, sender_length + 1);
754                 }
755
756                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
757                 if (r < 0)
758                         return -errno;
759
760                 if (matches_name_change) {
761
762                         /* If this match could theoretically match
763                          * NameOwnerChanged messages, we need to
764                          * install a second non-bloom filter explitly
765                          * for it */
766
767                         r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
768                         if (r < 0)
769                                 return r;
770                 }
771
772                 return 0;
773         } else
774                 return sd_bus_call_method(
775                                 bus,
776                                 "org.freedesktop.DBus",
777                                 "/",
778                                 "org.freedesktop.DBus",
779                                 "AddMatch",
780                                 NULL,
781                                 NULL,
782                                 "s",
783                                 match);
784 }
785
786 int bus_remove_match_internal(
787                 sd_bus *bus,
788                 const char *match,
789                 uint64_t cookie) {
790
791         int r;
792
793         assert(bus);
794         assert(match);
795
796         if (bus->is_kernel) {
797                 struct kdbus_cmd_match m;
798
799                 zero(m);
800                 m.size = offsetof(struct kdbus_cmd_match, items);
801                 m.cookie = cookie;
802
803                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
804                 if (r < 0)
805                         return -errno;
806
807                 return 0;
808
809         } else {
810                 return sd_bus_call_method(
811                                 bus,
812                                 "org.freedesktop.DBus",
813                                 "/",
814                                 "org.freedesktop.DBus",
815                                 "RemoveMatch",
816                                 NULL,
817                                 NULL,
818                                 "s",
819                                 match);
820         }
821 }
822
823 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
824         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
825         const char *mid;
826         int r;
827
828         assert_return(bus, -EINVAL);
829         assert_return(name, -EINVAL);
830         assert_return(machine, -EINVAL);
831         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
832         assert_return(!bus_pid_changed(bus), -ECHILD);
833
834         if (streq_ptr(name, bus->unique_name))
835                 return sd_id128_get_machine(machine);
836
837         r = sd_bus_message_new_method_call(
838                         bus,
839                         name,
840                         "/",
841                         "org.freedesktop.DBus.Peer",
842                         "GetMachineId", &m);
843         if (r < 0)
844                 return r;
845
846         r = sd_bus_message_set_no_auto_start(m, true);
847         if (r < 0)
848                 return r;
849
850         r = sd_bus_call(bus, m, 0, NULL, &reply);
851         if (r < 0)
852                 return r;
853
854         r = sd_bus_message_read(reply, "s", &mid);
855         if (r < 0)
856                 return r;
857
858         return sd_id128_from_string(mid, machine);
859 }