chiark / gitweb /
libsystemd-bus: catch up with latest kdbus changes
[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                 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->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_name_list *cmd = NULL;
178                 struct kdbus_name_list *name_list;
179                 struct kdbus_cmd_name *name;
180
181                 cmd = malloc0(sizeof(struct kdbus_cmd_name_list *));
182                 if (!cmd)
183                         return -ENOMEM;
184
185                 cmd->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
186
187                 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, cmd);
188                 if (r < 0)
189                         return -errno;
190
191                 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
192
193                 KDBUS_PART_FOREACH(name, name_list, names) {
194                         char *n;
195
196                         if (name->size > sizeof(*name))
197                                 n = name->name;
198                         else
199                                 asprintf(&n, ":1.%llu", (unsigned long long) name->id);
200
201                         r = strv_extend(&x, n);
202                         if (r < 0)
203                                 return -ENOMEM;
204                 }
205
206                 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
207                 if (r < 0)
208                         return -errno;
209
210                 *l = x;
211         } else {
212                 r = sd_bus_call_method(
213                                 bus,
214                                 "org.freedesktop.DBus",
215                                 "/",
216                                 "org.freedesktop.DBus",
217                                 "ListNames",
218                                 NULL,
219                                 &reply1,
220                                 NULL);
221                 if (r < 0)
222                         return r;
223
224                 r = sd_bus_call_method(
225                                 bus,
226                                 "org.freedesktop.DBus",
227                                 "/",
228                                 "org.freedesktop.DBus",
229                                 "ListActivatableNames",
230                                 NULL,
231                                 &reply2,
232                                 NULL);
233                 if (r < 0)
234                         return r;
235
236                 r = bus_message_read_strv_extend(reply1, &x);
237                 if (r < 0) {
238                         strv_free(x);
239                         return r;
240                 }
241
242                 r = bus_message_read_strv_extend(reply2, &x);
243                 if (r < 0) {
244                         strv_free(x);
245                         return r;
246                 }
247
248                 *l = strv_uniq(x);
249         }
250
251         return 0;
252 }
253
254 static int sd_bus_get_owner_dbus(
255                 sd_bus *bus,
256                 const char *name,
257                 uint64_t mask,
258                 char **owner,
259                 sd_bus_creds **creds) {
260
261         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
262         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
263         _cleanup_free_ char *unique = NULL;
264         pid_t pid = 0;
265         int r;
266
267         /* Only query the owner if the caller wants to know it or if
268          * the caller just wants to check whether a name exists */
269         if (owner || mask == 0) {
270                 const char *found;
271
272                 r = sd_bus_call_method(
273                                 bus,
274                                 "org.freedesktop.DBus",
275                                 "/",
276                                 "org.freedesktop.DBus",
277                                 "GetNameOwner",
278                                 NULL,
279                                 &reply,
280                                 "s",
281                                 name);
282                 if (r < 0)
283                         return r;
284
285                 r = sd_bus_message_read(reply, "s", &found);
286                 if (r < 0)
287                         return r;
288
289                 unique = strdup(found);
290                 if (!unique)
291                         return -ENOMEM;
292
293                 reply = sd_bus_message_unref(reply);
294         }
295
296         if (mask != 0) {
297                 c = bus_creds_new();
298                 if (!c)
299                         return -ENOMEM;
300
301                 if ((mask & SD_BUS_CREDS_PID) ||
302                     mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
303                         uint32_t u;
304
305                         r = sd_bus_call_method(
306                                         bus,
307                                         "org.freedesktop.DBus",
308                                         "/",
309                                         "org.freedesktop.DBus",
310                                         "GetConnectionUnixProcessID",
311                                         NULL,
312                                         &reply,
313                                         "s",
314                                         name);
315                         if (r < 0)
316                                 return r;
317
318                         r = sd_bus_message_read(reply, "u", &u);
319                         if (r < 0)
320                                 return r;
321
322                         pid = u;
323                         if (mask & SD_BUS_CREDS_PID) {
324                                 c->pid = u;
325                                 c->mask |= SD_BUS_CREDS_PID;
326                         }
327
328                         reply = sd_bus_message_unref(reply);
329                 }
330
331                 if (mask & SD_BUS_CREDS_UID) {
332                         uint32_t u;
333
334                         r = sd_bus_call_method(
335                                         bus,
336                                         "org.freedesktop.DBus",
337                                         "/",
338                                         "org.freedesktop.DBus",
339                                         "GetConnectionUnixUser",
340                                         NULL,
341                                         &reply,
342                                         "s",
343                                         name);
344                         if (r < 0)
345                                 return r;
346
347                         r = sd_bus_message_read(reply, "u", &u);
348                         if (r < 0)
349                                 return r;
350
351                         c->uid = u;
352                         c->mask |= SD_BUS_CREDS_UID;
353
354                         reply = sd_bus_message_unref(reply);
355                 }
356
357                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
358                         const void *p;
359                         size_t sz;
360
361                         r = sd_bus_call_method(
362                                         bus,
363                                         "org.freedesktop.DBus",
364                                         "/",
365                                         "org.freedesktop.DBus",
366                                         "GetConnectionSELinuxSecurityContext",
367                                         NULL,
368                                         &reply,
369                                         "s",
370                                         name);
371                         if (r < 0)
372                                 return r;
373
374                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
375                         if (r < 0)
376                                 return r;
377
378                         c->label = strndup(p, sz);
379                         if (!c->label)
380                                 return -ENOMEM;
381
382                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
383                 }
384
385                 r = bus_creds_add_more(c, mask, pid, 0);
386                 if (r < 0)
387                         return r;
388         }
389
390         if (creds) {
391                 *creds = c;
392                 c = NULL;
393         }
394
395         if (owner) {
396                 *owner = unique;
397                 unique = NULL;
398         }
399
400         return 0;
401 }
402
403 static int add_name_change_match(sd_bus *bus,
404                                  uint64_t cookie,
405                                  const char *name,
406                                  const char *old_owner,
407                                  const char *new_owner) {
408
409         uint64_t name_id = 0, old_owner_id = 0, new_owner_id = 0;
410         int is_name_id = -1, r;
411         struct kdbus_item *item;
412
413         assert(bus);
414
415         /* If we encounter a match that could match against
416          * NameOwnerChanged messages, then we need to create
417          * KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE} and
418          * KDBUS_MATCH_ID_{ADD,REMOVE} matches for it, possibly
419          * multiple if the match is underspecified.
420          *
421          * The NameOwnerChanged signals take three parameters with
422          * unique or well-known names, but only some forms actually
423          * exist:
424          *
425          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_MATCH_NAME_ADD
426          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_MATCH_NAME_REMOVE
427          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_MATCH_NAME_CHANGE
428          * UNIQUE, "", UNIQUE          â†’ KDBUS_MATCH_ID_ADD
429          * UNIQUE, UNIQUE, ""          â†’ KDBUS_MATCH_ID_REMOVE
430          *
431          * For the latter two the two unique names must be identical.
432          *
433          * */
434
435         if (name) {
436                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
437                 if (is_name_id < 0)
438                         return 0;
439         }
440
441         if (old_owner) {
442                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
443                 if (r < 0)
444                         return 0;
445                 if (r == 0)
446                         return 0;
447                 if (is_name_id > 0 && old_owner_id != name_id)
448                         return 0;
449         }
450
451         if (new_owner) {
452                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
453                 if (r < 0)
454                         return r;
455                 if (r == 0)
456                         return 0;
457                 if (is_name_id > 0 && new_owner_id != name_id)
458                         return 0;
459         }
460
461         if (is_name_id <= 0) {
462                 size_t sz, l;
463
464                 /* If the name argument is missing or is a well-known
465                  * name, then add KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE}
466                  * matches for it */
467
468                 l = name ? strlen(name) : 0;
469
470                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
471                             offsetof(struct kdbus_item, name_change) +
472                             offsetof(struct kdbus_notify_name_change, name) +
473                             l+1);
474
475                 {
476                         union {
477                                 uint8_t buffer[sz];
478                                 struct kdbus_cmd_match match;
479                         } m;
480
481                         memzero(&m, sz);
482
483                         m.match.size = sz;
484                         m.match.cookie = cookie;
485                         m.match.src_id = KDBUS_SRC_ID_KERNEL;
486
487                         item = m.match.items;
488                         item->size =
489                                 offsetof(struct kdbus_item, name_change) +
490                                 offsetof(struct kdbus_notify_name_change, name) +
491                                 l+1;
492
493                         item->name_change.old_id = old_owner_id;
494                         item->name_change.new_id = new_owner_id;
495
496                         if (name)
497                                 strcpy(item->name_change.name, name);
498
499                         /* If the old name is unset or empty, then
500                          * this can match against added names */
501                         if (!old_owner || old_owner[0] == 0) {
502                                 item->type = KDBUS_MATCH_NAME_ADD;
503
504                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
505                                 if (r < 0)
506                                         return -errno;
507                         }
508
509                         /* If the new name is unset or empty, then
510                          * this can match against removed names */
511                         if (!new_owner || new_owner[0] == 0) {
512                                 item->type = KDBUS_MATCH_NAME_REMOVE;
513
514                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
515                                 if (r < 0)
516                                         return -errno;
517                         }
518
519                         /* If the neither name is explicitly set to
520                          * the empty string, then this can match
521                          * agains changed names */
522                         if (!(old_owner && old_owner[0] == 0) &&
523                             !(new_owner && new_owner[0] == 0)) {
524                                 item->type = KDBUS_MATCH_NAME_CHANGE;
525
526                                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
527                                 if (r < 0)
528                                         return -errno;
529                         }
530                 }
531         }
532
533         if (is_name_id != 0) {
534                 uint64_t sz =
535                         ALIGN8(offsetof(struct kdbus_cmd_match, items) +
536                                offsetof(struct kdbus_item, id_change) +
537                                sizeof(struct kdbus_notify_id_change));
538                 union {
539                         uint8_t buffer[sz];
540                         struct kdbus_cmd_match match;
541                 } m;
542
543                 /* If the name argument is missing or is a unique
544                  * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
545                  * for it */
546
547                 memzero(&m, sz);
548
549                 m.match.size = sz;
550                 m.match.cookie = cookie;
551                 m.match.src_id = KDBUS_SRC_ID_KERNEL;
552
553                 item = m.match.items;
554                 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
555                 item->id_change.id = name_id;
556
557                 /* If the old name is unset or empty, then this can
558                  * match against added ids */
559                 if (!old_owner || old_owner[0] == 0) {
560                         item->type = KDBUS_MATCH_ID_ADD;
561
562                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
563                         if (r < 0)
564                                 return -errno;
565                 }
566
567                 /* If thew new name is unset or empty, then this can
568                 match against removed ids */
569                 if (!new_owner || new_owner[0] == 0) {
570                         item->type = KDBUS_MATCH_ID_REMOVE;
571
572                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
573                         if (r < 0)
574                                 return -errno;
575                 }
576         }
577
578         return 0;
579 }
580
581 static int kdbus_name_info(
582                 sd_bus *bus,
583                 const char *name,
584                 uint64_t mask,
585                 char **owner,
586                 sd_bus_creds **creds) {
587
588         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
589         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
590         _cleanup_free_ struct kdbus_cmd_name_info *cmd = NULL;
591         _cleanup_free_ char *unique = NULL;
592         struct kdbus_name_info *name_info;
593         struct kdbus_item *item;
594         uint64_t attach_flags, m;
595         size_t size;
596         int r;
597
598         r = kdbus_translate_attach_flags(mask, &attach_flags);
599         if (r < 0)
600                 return r;
601
602         size = sizeof(struct kdbus_cmd_name_info) + strlen(name) + 1;
603         cmd = malloc0(size);
604         if (!cmd)
605                 return -ENOMEM;
606
607         cmd ->size = size;
608         cmd->attach_flags = attach_flags;
609         strcpy(cmd->name, name);
610
611         r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_INFO, cmd);
612         if (r < 0)
613                 return -errno;
614
615         name_info = (struct kdbus_name_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
616
617         asprintf(&unique, ":1.%llu", (unsigned long long) name_info->id);
618
619         c = bus_creds_new();
620         if (!c)
621                 return -ENOMEM;
622
623         KDBUS_PART_FOREACH(item, name_info, items) {
624                 switch (item->type) {
625                 case KDBUS_ITEM_CREDS:
626                         m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID |
627                              SD_BUS_CREDS_TID | SD_BUS_CREDS_PID_STARTTIME) & mask;
628
629                         if (m) {
630                                 c->uid = item->creds.uid;
631                                 c->pid = item->creds.pid;
632                                 c->gid = item->creds.gid;
633                                 c->tid = item->creds.tid;
634                                 c->pid_starttime = item->creds.starttime;
635                                 c->mask |= m;
636                         }
637                         break;
638
639                 case KDBUS_ITEM_PID_COMM:
640                         if (mask & SD_BUS_CREDS_COMM) {
641                                 c->comm = strdup(item->str);
642                                 if (!c->comm)
643                                         return -ENOMEM;
644
645                                 c->mask |= SD_BUS_CREDS_COMM;
646                         }
647                         break;
648
649                 case KDBUS_ITEM_TID_COMM:
650                         if (mask & SD_BUS_CREDS_TID_COMM) {
651                                 c->tid_comm = strdup(item->str);
652                                 if (!c->tid_comm)
653                                         return -ENOMEM;
654
655                                 c->mask |= SD_BUS_CREDS_TID_COMM;
656                         }
657                         break;
658
659                 case KDBUS_ITEM_EXE:
660                         if (mask & SD_BUS_CREDS_EXE) {
661                                 c->exe = strdup(item->str);
662                                 if (!c->exe)
663                                         return -ENOMEM;
664
665                                 c->mask |= SD_BUS_CREDS_EXE;
666                         }
667                         break;
668
669                 case KDBUS_ITEM_CMDLINE:
670                         if (mask & SD_BUS_CREDS_CMDLINE) {
671                                 c->cmdline_length = item->size - KDBUS_PART_HEADER_SIZE;
672                                 c->cmdline = memdup(item->data, c->cmdline_length);
673                                 if (!c->cmdline)
674                                         return -ENOMEM;
675
676                                 c->mask |= SD_BUS_CREDS_CMDLINE;
677                         }
678                         break;
679
680                 case KDBUS_ITEM_CGROUP:
681                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
682                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
683                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
684
685                         if (m) {
686                                 c->cgroup = strdup(item->str);
687                                 if (!c->cgroup)
688                                         return -ENOMEM;
689
690                                 c->mask |= m;
691                         }
692                         break;
693
694                 case KDBUS_ITEM_CAPS:
695                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
696                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
697
698                         if (m) {
699                                 c->capability_size = item->size - KDBUS_PART_HEADER_SIZE;
700                                 c->capability = memdup(item->data, c->capability_size);
701                                 if (!c->capability)
702                                         return -ENOMEM;
703
704                                 c->mask |= m;
705                         }
706                         break;
707
708                 case KDBUS_ITEM_SECLABEL:
709                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
710                                 c->label = strdup(item->str);
711                                 if (!c->label)
712                                         return -ENOMEM;
713
714                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
715                         }
716                         break;
717
718                 case KDBUS_ITEM_AUDIT:
719                         m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
720
721                         if (m) {
722                                 c->audit_session_id = item->audit.sessionid;
723                                 c->audit_login_uid = item->audit.loginuid;
724                                 c->mask |= m;
725                         }
726                         break;
727                 }
728         }
729
730         r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
731         if (r < 0)
732                 return -errno;
733
734         if (creds) {
735                 *creds = c;
736                 c = NULL;
737         }
738
739         if (owner) {
740                 *owner = unique;
741                 unique = NULL;
742         }
743
744         return 0;
745 }
746
747 _public_ int sd_bus_get_owner(
748                 sd_bus *bus,
749                 const char *name,
750                 uint64_t mask,
751                 char **owner,
752                 sd_bus_creds **creds) {
753
754         assert_return(bus, -EINVAL);
755         assert_return(name, -EINVAL);
756         assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
757         assert_return(mask == 0 || creds, -EINVAL);
758         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
759         assert_return(!bus_pid_changed(bus), -ECHILD);
760
761         if (bus->is_kernel)
762                 return kdbus_name_info(bus, name, mask, owner, creds);
763
764         return sd_bus_get_owner_dbus(bus, name, mask, owner, creds);
765 }
766
767 int bus_add_match_internal(
768                 sd_bus *bus,
769                 const char *match,
770                 struct bus_match_component *components,
771                 unsigned n_components,
772                 uint64_t cookie) {
773
774         int r;
775
776         assert(bus);
777         assert(match);
778
779         if (bus->is_kernel) {
780                 struct kdbus_cmd_match *m;
781                 struct kdbus_item *item;
782                 uint64_t bloom[BLOOM_SIZE/8];
783                 size_t sz;
784                 const char *sender = NULL;
785                 size_t sender_length = 0;
786                 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
787                 bool using_bloom = false;
788                 unsigned i;
789                 bool matches_name_change = true;
790                 const char *name_change_arg[3] = {};
791
792                 zero(bloom);
793
794                 sz = offsetof(struct kdbus_cmd_match, items);
795
796                 for (i = 0; i < n_components; i++) {
797                         struct bus_match_component *c = &components[i];
798
799                         switch (c->type) {
800
801                         case BUS_MATCH_SENDER:
802                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
803                                         matches_name_change = false;
804
805                                 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
806                                 if (r < 0)
807                                         return r;
808
809                                 if (r > 0) {
810                                         sender = c->value_str;
811                                         sender_length = strlen(sender);
812                                         sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
813                                 }
814
815                                 break;
816
817                         case BUS_MATCH_MESSAGE_TYPE:
818                                 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
819                                         matches_name_change = false;
820
821                                 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
822                                 using_bloom = true;
823                                 break;
824
825                         case BUS_MATCH_INTERFACE:
826                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
827                                         matches_name_change = false;
828
829                                 bloom_add_pair(bloom, "interface", c->value_str);
830                                 using_bloom = true;
831                                 break;
832
833                         case BUS_MATCH_MEMBER:
834                                 if (!streq(c->value_str, "NameOwnerChanged"))
835                                         matches_name_change = false;
836
837                                 bloom_add_pair(bloom, "member", c->value_str);
838                                 using_bloom = true;
839                                 break;
840
841                         case BUS_MATCH_PATH:
842                                 if (!streq(c->value_str, "/org/freedesktop/DBus"))
843                                         matches_name_change = false;
844
845                                 bloom_add_pair(bloom, "path", c->value_str);
846                                 using_bloom = true;
847                                 break;
848
849                         case BUS_MATCH_PATH_NAMESPACE:
850                                 if (!streq(c->value_str, "/")) {
851                                         bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
852                                         using_bloom = true;
853                                 }
854                                 break;
855
856                         case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
857                                 char buf[sizeof("arg")-1 + 2 + 1];
858
859                                 if (c->type - BUS_MATCH_ARG < 3)
860                                         name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
861
862                                 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
863                                 bloom_add_pair(bloom, buf, c->value_str);
864                                 using_bloom = true;
865                                 break;
866                         }
867
868                         case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
869                                 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
870
871                                 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
872                                 bloom_add_pair(bloom, buf, c->value_str);
873                                 using_bloom = true;
874                                 break;
875                         }
876
877                         case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
878                                 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
879
880                                 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
881                                 bloom_add_pair(bloom, buf, c->value_str);
882                                 using_bloom = true;
883                                 break;
884                         }
885
886                         case BUS_MATCH_DESTINATION:
887                                 /* The bloom filter does not include
888                                    the destination, since it is only
889                                    available for broadcast messages
890                                    which do not carry a destination
891                                    since they are undirected. */
892                                 break;
893
894                         case BUS_MATCH_ROOT:
895                         case BUS_MATCH_VALUE:
896                         case BUS_MATCH_LEAF:
897                         case _BUS_MATCH_NODE_TYPE_MAX:
898                         case _BUS_MATCH_NODE_TYPE_INVALID:
899                                 assert_not_reached("Invalid match type?");
900                         }
901                 }
902
903                 if (using_bloom)
904                         sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
905
906                 m = alloca0(sz);
907                 m->size = sz;
908                 m->cookie = cookie;
909                 m->src_id = src_id;
910
911                 item = m->items;
912
913                 if (using_bloom) {
914                         item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
915                         item->type = KDBUS_MATCH_BLOOM;
916                         memcpy(item->data64, bloom, BLOOM_SIZE);
917
918                         item = KDBUS_PART_NEXT(item);
919                 }
920
921                 if (sender) {
922                         item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
923                         item->type = KDBUS_MATCH_SRC_NAME;
924                         memcpy(item->str, sender, sender_length + 1);
925                 }
926
927                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
928                 if (r < 0)
929                         return -errno;
930
931                 if (matches_name_change) {
932
933                         /* If this match could theoretically match
934                          * NameOwnerChanged messages, we need to
935                          * install a second non-bloom filter explitly
936                          * for it */
937
938                         r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
939                         if (r < 0)
940                                 return r;
941                 }
942
943                 return 0;
944         } else
945                 return sd_bus_call_method(
946                                 bus,
947                                 "org.freedesktop.DBus",
948                                 "/",
949                                 "org.freedesktop.DBus",
950                                 "AddMatch",
951                                 NULL,
952                                 NULL,
953                                 "s",
954                                 match);
955 }
956
957 int bus_remove_match_internal(
958                 sd_bus *bus,
959                 const char *match,
960                 uint64_t cookie) {
961
962         int r;
963
964         assert(bus);
965         assert(match);
966
967         if (bus->is_kernel) {
968                 struct kdbus_cmd_match m;
969
970                 zero(m);
971                 m.size = offsetof(struct kdbus_cmd_match, items);
972                 m.cookie = cookie;
973
974                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
975                 if (r < 0)
976                         return -errno;
977
978                 return 0;
979
980         } else {
981                 return sd_bus_call_method(
982                                 bus,
983                                 "org.freedesktop.DBus",
984                                 "/",
985                                 "org.freedesktop.DBus",
986                                 "RemoveMatch",
987                                 NULL,
988                                 NULL,
989                                 "s",
990                                 match);
991         }
992 }
993
994 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
995         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
996         const char *mid;
997         int r;
998
999         assert_return(bus, -EINVAL);
1000         assert_return(name, -EINVAL);
1001         assert_return(machine, -EINVAL);
1002         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1003         assert_return(!bus_pid_changed(bus), -ECHILD);
1004
1005         if (streq_ptr(name, bus->unique_name))
1006                 return sd_id128_get_machine(machine);
1007
1008         r = sd_bus_message_new_method_call(
1009                         bus,
1010                         name,
1011                         "/",
1012                         "org.freedesktop.DBus.Peer",
1013                         "GetMachineId", &m);
1014         if (r < 0)
1015                 return r;
1016
1017         r = sd_bus_message_set_no_auto_start(m, true);
1018         if (r < 0)
1019                 return r;
1020
1021         r = sd_bus_call(bus, m, 0, NULL, &reply);
1022         if (r < 0)
1023                 return r;
1024
1025         r = sd_bus_message_read(reply, "s", &mid);
1026         if (r < 0)
1027                 return r;
1028
1029         return sd_id128_from_string(mid, machine);
1030 }