chiark / gitweb /
libsystemd-bus: factor out DBus bits out of sd_bus_get_owner()
[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 static int sd_bus_get_owner_dbus(
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         /* Only query the owner if the caller wants to know it or if
277          * the caller just wants to check whether a name exists */
278         if (owner || mask == 0) {
279                 const char *found;
280
281                 r = sd_bus_call_method(
282                                 bus,
283                                 "org.freedesktop.DBus",
284                                 "/",
285                                 "org.freedesktop.DBus",
286                                 "GetNameOwner",
287                                 NULL,
288                                 &reply,
289                                 "s",
290                                 name);
291                 if (r < 0)
292                         return r;
293
294                 r = sd_bus_message_read(reply, "s", &found);
295                 if (r < 0)
296                         return r;
297
298                 unique = strdup(found);
299                 if (!unique)
300                         return -ENOMEM;
301
302                 reply = sd_bus_message_unref(reply);
303         }
304
305         if (mask != 0) {
306                 c = bus_creds_new();
307                 if (!c)
308                         return -ENOMEM;
309
310                 if ((mask & SD_BUS_CREDS_PID) ||
311                     mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
312                         uint32_t u;
313
314                         r = sd_bus_call_method(
315                                         bus,
316                                         "org.freedesktop.DBus",
317                                         "/",
318                                         "org.freedesktop.DBus",
319                                         "GetConnectionUnixProcessID",
320                                         NULL,
321                                         &reply,
322                                         "s",
323                                         name);
324                         if (r < 0)
325                                 return r;
326
327                         r = sd_bus_message_read(reply, "u", &u);
328                         if (r < 0)
329                                 return r;
330
331                         pid = u;
332                         if (mask & SD_BUS_CREDS_PID) {
333                                 c->pid = u;
334                                 c->mask |= SD_BUS_CREDS_PID;
335                         }
336
337                         reply = sd_bus_message_unref(reply);
338                 }
339
340                 if (mask & SD_BUS_CREDS_UID) {
341                         uint32_t u;
342
343                         r = sd_bus_call_method(
344                                         bus,
345                                         "org.freedesktop.DBus",
346                                         "/",
347                                         "org.freedesktop.DBus",
348                                         "GetConnectionUnixUser",
349                                         NULL,
350                                         &reply,
351                                         "s",
352                                         name);
353                         if (r < 0)
354                                 return r;
355
356                         r = sd_bus_message_read(reply, "u", &u);
357                         if (r < 0)
358                                 return r;
359
360                         c->uid = u;
361                         c->mask |= SD_BUS_CREDS_UID;
362
363                         reply = sd_bus_message_unref(reply);
364                 }
365
366                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
367                         const void *p;
368                         size_t sz;
369
370                         r = sd_bus_call_method(
371                                         bus,
372                                         "org.freedesktop.DBus",
373                                         "/",
374                                         "org.freedesktop.DBus",
375                                         "GetConnectionSELinuxSecurityContext",
376                                         NULL,
377                                         &reply,
378                                         "s",
379                                         name);
380                         if (r < 0)
381                                 return r;
382
383                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
384                         if (r < 0)
385                                 return r;
386
387                         c->label = strndup(p, sz);
388                         if (!c->label)
389                                 return -ENOMEM;
390
391                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
392                 }
393
394                 r = bus_creds_add_more(c, mask, pid, 0);
395                 if (r < 0)
396                         return r;
397         }
398
399         if (creds) {
400                 *creds = c;
401                 c = NULL;
402         }
403
404         if (owner) {
405                 *owner = unique;
406                 unique = NULL;
407         }
408
409         return 0;
410 }
411
412 static int add_name_change_match(sd_bus *bus,
413                                  uint64_t cookie,
414                                  const char *name,
415                                  const char *old_owner,
416                                  const char *new_owner) {
417
418         uint64_t name_id = 0, old_owner_id = 0, new_owner_id = 0;
419         int is_name_id = -1, r;
420         struct kdbus_item *item;
421
422         assert(bus);
423
424         /* If we encounter a match that could match against
425          * NameOwnerChanged messages, then we need to create
426          * KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE} and
427          * KDBUS_MATCH_ID_{ADD,REMOVE} matches for it, possibly
428          * multiple if the match is underspecified.
429          *
430          * The NameOwnerChanged signals take three parameters with
431          * unique or well-known names, but only some forms actually
432          * exist:
433          *
434          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_MATCH_NAME_ADD
435          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_MATCH_NAME_REMOVE
436          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_MATCH_NAME_CHANGE
437          * UNIQUE, "", UNIQUE          â†’ KDBUS_MATCH_ID_ADD
438          * UNIQUE, UNIQUE, ""          â†’ KDBUS_MATCH_ID_REMOVE
439          *
440          * For the latter two the two unique names must be identical.
441          *
442          * */
443
444         if (name) {
445                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
446                 if (is_name_id < 0)
447                         return 0;
448         }
449
450         if (old_owner) {
451                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
452                 if (r < 0)
453                         return 0;
454                 if (r == 0)
455                         return 0;
456                 if (is_name_id > 0 && old_owner_id != name_id)
457                         return 0;
458         }
459
460         if (new_owner) {
461                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
462                 if (r < 0)
463                         return r;
464                 if (r == 0)
465                         return 0;
466                 if (is_name_id > 0 && new_owner_id != name_id)
467                         return 0;
468         }
469
470         if (is_name_id <= 0) {
471                 size_t sz, l;
472
473                 /* If the name argument is missing or is a well-known
474                  * name, then add KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE}
475                  * matches for it */
476
477                 l = name ? strlen(name) : 0;
478
479                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
480                             offsetof(struct kdbus_item, name_change) +
481                             offsetof(struct kdbus_notify_name_change, name) +
482                             l+1);
483
484                 {
485                         union {
486                                 uint8_t buffer[sz];
487                                 struct kdbus_cmd_match match;
488                         } m;
489
490                         memzero(&m, sz);
491
492                         m.match.size = sz;
493                         m.match.cookie = cookie;
494                         m.match.src_id = KDBUS_SRC_ID_KERNEL;
495
496                         item = m.match.items;
497                         item->size =
498                                 offsetof(struct kdbus_item, name_change) +
499                                 offsetof(struct kdbus_notify_name_change, name) +
500                                 l+1;
501
502                         item->name_change.old_id = old_owner_id;
503                         item->name_change.new_id = new_owner_id;
504
505                         if (name)
506                                 strcpy(item->name_change.name, name);
507
508                         /* If the old name is unset or empty, then
509                          * this can match against added names */
510                         if (!old_owner || old_owner[0] == 0) {
511                                 item->type = KDBUS_MATCH_NAME_ADD;
512
513                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
514                                 if (r < 0)
515                                         return -errno;
516                         }
517
518                         /* If the new name is unset or empty, then
519                          * this can match against removed names */
520                         if (!new_owner || new_owner[0] == 0) {
521                                 item->type = KDBUS_MATCH_NAME_REMOVE;
522
523                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
524                                 if (r < 0)
525                                         return -errno;
526                         }
527
528                         /* If the neither name is explicitly set to
529                          * the empty string, then this can match
530                          * agains changed names */
531                         if (!(old_owner && old_owner[0] == 0) &&
532                             !(new_owner && new_owner[0] == 0)) {
533                                 item->type = KDBUS_MATCH_NAME_CHANGE;
534
535                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
536                                 if (r < 0)
537                                         return -errno;
538                         }
539                 }
540         }
541
542         if (is_name_id != 0) {
543                 uint64_t sz =
544                         ALIGN8(offsetof(struct kdbus_cmd_match, items) +
545                                offsetof(struct kdbus_item, id_change) +
546                                sizeof(struct kdbus_notify_id_change));
547                 union {
548                         uint8_t buffer[sz];
549                         struct kdbus_cmd_match match;
550                 } m;
551
552                 /* If the name argument is missing or is a unique
553                  * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
554                  * for it */
555
556                 memzero(&m, sz);
557
558                 m.match.size = sz;
559                 m.match.cookie = cookie;
560                 m.match.src_id = KDBUS_SRC_ID_KERNEL;
561
562                 item = m.match.items;
563                 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
564                 item->id_change.id = name_id;
565
566                 /* If the old name is unset or empty, then this can
567                  * match against added ids */
568                 if (!old_owner || old_owner[0] == 0) {
569                         item->type = KDBUS_MATCH_ID_ADD;
570
571                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
572                         if (r < 0)
573                                 return -errno;
574                 }
575
576                 /* If thew new name is unset or empty, then this can
577                 match against removed ids */
578                 if (!new_owner || new_owner[0] == 0) {
579                         item->type = KDBUS_MATCH_ID_REMOVE;
580
581                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
582                         if (r < 0)
583                                 return -errno;
584                 }
585         }
586
587         return 0;
588 }
589
590 _public_ int sd_bus_get_owner(
591                 sd_bus *bus,
592                 const char *name,
593                 uint64_t mask,
594                 char **owner,
595                 sd_bus_creds **creds) {
596
597         assert_return(bus, -EINVAL);
598         assert_return(name, -EINVAL);
599         assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
600         assert_return(mask == 0 || creds, -EINVAL);
601         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
602         assert_return(!bus_pid_changed(bus), -ECHILD);
603
604         return sd_bus_get_owner_dbus(bus, name, mask, owner, creds);
605 }
606
607 int bus_add_match_internal(
608                 sd_bus *bus,
609                 const char *match,
610                 struct bus_match_component *components,
611                 unsigned n_components,
612                 uint64_t cookie) {
613
614         int r;
615
616         assert(bus);
617         assert(match);
618
619         if (bus->is_kernel) {
620                 struct kdbus_cmd_match *m;
621                 struct kdbus_item *item;
622                 uint64_t bloom[BLOOM_SIZE/8];
623                 size_t sz;
624                 const char *sender = NULL;
625                 size_t sender_length = 0;
626                 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
627                 bool using_bloom = false;
628                 unsigned i;
629                 bool matches_name_change = true;
630                 const char *name_change_arg[3] = {};
631
632                 zero(bloom);
633
634                 sz = offsetof(struct kdbus_cmd_match, items);
635
636                 for (i = 0; i < n_components; i++) {
637                         struct bus_match_component *c = &components[i];
638
639                         switch (c->type) {
640
641                         case BUS_MATCH_SENDER:
642                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
643                                         matches_name_change = false;
644
645                                 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
646                                 if (r < 0)
647                                         return r;
648
649                                 if (r > 0) {
650                                         sender = c->value_str;
651                                         sender_length = strlen(sender);
652                                         sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
653                                 }
654
655                                 break;
656
657                         case BUS_MATCH_MESSAGE_TYPE:
658                                 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
659                                         matches_name_change = false;
660
661                                 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
662                                 using_bloom = true;
663                                 break;
664
665                         case BUS_MATCH_INTERFACE:
666                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
667                                         matches_name_change = false;
668
669                                 bloom_add_pair(bloom, "interface", c->value_str);
670                                 using_bloom = true;
671                                 break;
672
673                         case BUS_MATCH_MEMBER:
674                                 if (!streq(c->value_str, "NameOwnerChanged"))
675                                         matches_name_change = false;
676
677                                 bloom_add_pair(bloom, "member", c->value_str);
678                                 using_bloom = true;
679                                 break;
680
681                         case BUS_MATCH_PATH:
682                                 if (!streq(c->value_str, "/org/freedesktop/DBus"))
683                                         matches_name_change = false;
684
685                                 bloom_add_pair(bloom, "path", c->value_str);
686                                 using_bloom = true;
687                                 break;
688
689                         case BUS_MATCH_PATH_NAMESPACE:
690                                 if (!streq(c->value_str, "/")) {
691                                         bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
692                                         using_bloom = true;
693                                 }
694                                 break;
695
696                         case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
697                                 char buf[sizeof("arg")-1 + 2 + 1];
698
699                                 if (c->type - BUS_MATCH_ARG < 3)
700                                         name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
701
702                                 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
703                                 bloom_add_pair(bloom, buf, c->value_str);
704                                 using_bloom = true;
705                                 break;
706                         }
707
708                         case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
709                                 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
710
711                                 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
712                                 bloom_add_pair(bloom, buf, c->value_str);
713                                 using_bloom = true;
714                                 break;
715                         }
716
717                         case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
718                                 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
719
720                                 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
721                                 bloom_add_pair(bloom, buf, c->value_str);
722                                 using_bloom = true;
723                                 break;
724                         }
725
726                         case BUS_MATCH_DESTINATION:
727                                 /* The bloom filter does not include
728                                    the destination, since it is only
729                                    available for broadcast messages
730                                    which do not carry a destination
731                                    since they are undirected. */
732                                 break;
733
734                         case BUS_MATCH_ROOT:
735                         case BUS_MATCH_VALUE:
736                         case BUS_MATCH_LEAF:
737                         case _BUS_MATCH_NODE_TYPE_MAX:
738                         case _BUS_MATCH_NODE_TYPE_INVALID:
739                                 assert_not_reached("Invalid match type?");
740                         }
741                 }
742
743                 if (using_bloom)
744                         sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
745
746                 m = alloca0(sz);
747                 m->size = sz;
748                 m->cookie = cookie;
749                 m->src_id = src_id;
750
751                 item = m->items;
752
753                 if (using_bloom) {
754                         item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
755                         item->type = KDBUS_MATCH_BLOOM;
756                         memcpy(item->data64, bloom, BLOOM_SIZE);
757
758                         item = KDBUS_PART_NEXT(item);
759                 }
760
761                 if (sender) {
762                         item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
763                         item->type = KDBUS_MATCH_SRC_NAME;
764                         memcpy(item->str, sender, sender_length + 1);
765                 }
766
767                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
768                 if (r < 0)
769                         return -errno;
770
771                 if (matches_name_change) {
772
773                         /* If this match could theoretically match
774                          * NameOwnerChanged messages, we need to
775                          * install a second non-bloom filter explitly
776                          * for it */
777
778                         r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
779                         if (r < 0)
780                                 return r;
781                 }
782
783                 return 0;
784         } else
785                 return sd_bus_call_method(
786                                 bus,
787                                 "org.freedesktop.DBus",
788                                 "/",
789                                 "org.freedesktop.DBus",
790                                 "AddMatch",
791                                 NULL,
792                                 NULL,
793                                 "s",
794                                 match);
795 }
796
797 int bus_remove_match_internal(
798                 sd_bus *bus,
799                 const char *match,
800                 uint64_t cookie) {
801
802         int r;
803
804         assert(bus);
805         assert(match);
806
807         if (bus->is_kernel) {
808                 struct kdbus_cmd_match m;
809
810                 zero(m);
811                 m.size = offsetof(struct kdbus_cmd_match, items);
812                 m.cookie = cookie;
813
814                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
815                 if (r < 0)
816                         return -errno;
817
818                 return 0;
819
820         } else {
821                 return sd_bus_call_method(
822                                 bus,
823                                 "org.freedesktop.DBus",
824                                 "/",
825                                 "org.freedesktop.DBus",
826                                 "RemoveMatch",
827                                 NULL,
828                                 NULL,
829                                 "s",
830                                 match);
831         }
832 }
833
834 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
835         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
836         const char *mid;
837         int r;
838
839         assert_return(bus, -EINVAL);
840         assert_return(name, -EINVAL);
841         assert_return(machine, -EINVAL);
842         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
843         assert_return(!bus_pid_changed(bus), -ECHILD);
844
845         if (streq_ptr(name, bus->unique_name))
846                 return sd_id128_get_machine(machine);
847
848         r = sd_bus_message_new_method_call(
849                         bus,
850                         name,
851                         "/",
852                         "org.freedesktop.DBus.Peer",
853                         "GetMachineId", &m);
854         if (r < 0)
855                 return r;
856
857         r = sd_bus_message_set_no_auto_start(m, true);
858         if (r < 0)
859                 return r;
860
861         r = sd_bus_call(bus, m, 0, NULL, &reply);
862         if (r < 0)
863                 return r;
864
865         r = sd_bus_message_read(reply, "s", &mid);
866         if (r < 0)
867                 return r;
868
869         return sd_id128_from_string(mid, machine);
870 }