chiark / gitweb /
libsystemd-bus: sd_bus_request_name: use kdbus_translate_request_name_flags()
[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_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 static int kdbus_name_query(
591                 sd_bus *bus,
592                 const char *name,
593                 uint64_t mask,
594                 char **owner,
595                 sd_bus_creds **creds) {
596
597         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
598         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
599         _cleanup_free_ char *unique = NULL;
600         struct kdbus_cmd_name_info *name_info = NULL;
601         struct kdbus_item *item;
602         uint64_t attach_flags, m;
603         size_t slen, size;
604         int r;
605
606         r = kdbus_translate_attach_flags(mask, &attach_flags);
607         if (r < 0)
608                 return r;
609
610         slen = strlen(name) + 1;
611
612         /*
613          * The structure is used for both directions. Start with 8k buffer size and
614          * expand to the size kdbus reports in case we fail.
615          */
616         size = slen + 8192;
617
618         for(;;) {
619                 name_info = realloc(name_info, size);
620                 if (!name_info)
621                         return -ENOMEM;
622
623                 memset(name_info, 0, size);
624
625                 name_info->size = size;
626                 name_info->attach_flags = attach_flags;
627
628                 item = name_info->items;
629                 item->type = KDBUS_NAME_INFO_ITEM_NAME;
630                 item->size = KDBUS_ITEM_SIZE(slen);
631                 strcpy(item->str, name);
632
633                 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_QUERY, name_info);
634                 if (r < 0) {
635                         if (errno == ENOBUFS && size != name_info->size) {
636                                 size = name_info->size;
637                                 continue;
638                         }
639
640                         return -errno;
641                 }
642
643                 break;
644         }
645
646         asprintf(&unique, ":1.%llu", (unsigned long long) name_info->id);
647
648         c = bus_creds_new();
649         if (!c)
650                 return -ENOMEM;
651
652         KDBUS_PART_FOREACH(item, name_info, items) {
653                 switch (item->type) {
654                 case KDBUS_ITEM_CREDS:
655                         m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID |
656                              SD_BUS_CREDS_TID | SD_BUS_CREDS_PID_STARTTIME) & mask;
657
658                         if (m) {
659                                 c->uid = item->creds.uid;
660                                 c->pid = item->creds.pid;
661                                 c->gid = item->creds.gid;
662                                 c->tid = item->creds.tid;
663                                 c->pid_starttime = item->creds.starttime;
664                                 c->mask |= m;
665                         }
666                         break;
667
668                 case KDBUS_ITEM_PID_COMM:
669                         if (mask & SD_BUS_CREDS_COMM) {
670                                 c->comm = strdup(item->str);
671                                 if (!c->comm)
672                                         return -ENOMEM;
673
674                                 c->mask |= SD_BUS_CREDS_COMM;
675                         }
676                         break;
677
678                 case KDBUS_ITEM_TID_COMM:
679                         if (mask & SD_BUS_CREDS_TID_COMM) {
680                                 c->tid_comm = strdup(item->str);
681                                 if (!c->tid_comm)
682                                         return -ENOMEM;
683
684                                 c->mask |= SD_BUS_CREDS_TID_COMM;
685                         }
686                         break;
687
688                 case KDBUS_ITEM_EXE:
689                         if (mask & SD_BUS_CREDS_EXE) {
690                                 c->exe = strdup(item->str);
691                                 if (!c->exe)
692                                         return -ENOMEM;
693
694                                 c->mask |= SD_BUS_CREDS_EXE;
695                         }
696                         break;
697
698                 case KDBUS_ITEM_CMDLINE:
699                         if (mask & SD_BUS_CREDS_CMDLINE) {
700                                 c->cmdline_length = item->size - KDBUS_PART_HEADER_SIZE;
701                                 c->cmdline = memdup(item->data, c->cmdline_length);
702                                 if (!c->cmdline)
703                                         return -ENOMEM;
704
705                                 c->mask |= SD_BUS_CREDS_CMDLINE;
706                         }
707                         break;
708
709                 case KDBUS_ITEM_CGROUP:
710                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
711                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
712                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
713
714                         if (m) {
715                                 c->cgroup = strdup(item->str);
716                                 if (!c->cgroup)
717                                         return -ENOMEM;
718
719                                 c->mask |= m;
720                         }
721                         break;
722
723                 case KDBUS_ITEM_CAPS:
724                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
725                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
726
727                         if (m) {
728                                 c->capability_size = item->size - KDBUS_PART_HEADER_SIZE;
729                                 c->capability = memdup(item->data, c->capability_size);
730                                 if (!c->capability)
731                                         return -ENOMEM;
732
733                                 c->mask |= m;
734                         }
735                         break;
736
737                 case KDBUS_ITEM_SECLABEL:
738                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
739                                 c->label = strdup(item->str);
740                                 if (!c->label)
741                                         return -ENOMEM;
742
743                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
744                         }
745                         break;
746
747                 case KDBUS_ITEM_AUDIT:
748                         m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
749
750                         if (m) {
751                                 c->audit_session_id = item->audit.sessionid;
752                                 c->audit_login_uid = item->audit.loginuid;
753                                 c->mask |= m;
754                         }
755                         break;
756                 }
757         }
758
759         if (creds) {
760                 *creds = c;
761                 c = NULL;
762         }
763
764         if (owner) {
765                 *owner = unique;
766                 unique = NULL;
767         }
768
769         return 0;
770 }
771
772 _public_ int sd_bus_get_owner(
773                 sd_bus *bus,
774                 const char *name,
775                 uint64_t mask,
776                 char **owner,
777                 sd_bus_creds **creds) {
778
779         assert_return(bus, -EINVAL);
780         assert_return(name, -EINVAL);
781         assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
782         assert_return(mask == 0 || creds, -EINVAL);
783         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
784         assert_return(!bus_pid_changed(bus), -ECHILD);
785
786         if (bus->is_kernel)
787                 return kdbus_name_query(bus, name, mask, owner, creds);
788
789         return sd_bus_get_owner_dbus(bus, name, mask, owner, creds);
790 }
791
792 int bus_add_match_internal(
793                 sd_bus *bus,
794                 const char *match,
795                 struct bus_match_component *components,
796                 unsigned n_components,
797                 uint64_t cookie) {
798
799         int r;
800
801         assert(bus);
802         assert(match);
803
804         if (bus->is_kernel) {
805                 struct kdbus_cmd_match *m;
806                 struct kdbus_item *item;
807                 uint64_t bloom[BLOOM_SIZE/8];
808                 size_t sz;
809                 const char *sender = NULL;
810                 size_t sender_length = 0;
811                 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
812                 bool using_bloom = false;
813                 unsigned i;
814                 bool matches_name_change = true;
815                 const char *name_change_arg[3] = {};
816
817                 zero(bloom);
818
819                 sz = offsetof(struct kdbus_cmd_match, items);
820
821                 for (i = 0; i < n_components; i++) {
822                         struct bus_match_component *c = &components[i];
823
824                         switch (c->type) {
825
826                         case BUS_MATCH_SENDER:
827                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
828                                         matches_name_change = false;
829
830                                 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
831                                 if (r < 0)
832                                         return r;
833
834                                 if (r > 0) {
835                                         sender = c->value_str;
836                                         sender_length = strlen(sender);
837                                         sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
838                                 }
839
840                                 break;
841
842                         case BUS_MATCH_MESSAGE_TYPE:
843                                 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
844                                         matches_name_change = false;
845
846                                 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
847                                 using_bloom = true;
848                                 break;
849
850                         case BUS_MATCH_INTERFACE:
851                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
852                                         matches_name_change = false;
853
854                                 bloom_add_pair(bloom, "interface", c->value_str);
855                                 using_bloom = true;
856                                 break;
857
858                         case BUS_MATCH_MEMBER:
859                                 if (!streq(c->value_str, "NameOwnerChanged"))
860                                         matches_name_change = false;
861
862                                 bloom_add_pair(bloom, "member", c->value_str);
863                                 using_bloom = true;
864                                 break;
865
866                         case BUS_MATCH_PATH:
867                                 if (!streq(c->value_str, "/org/freedesktop/DBus"))
868                                         matches_name_change = false;
869
870                                 bloom_add_pair(bloom, "path", c->value_str);
871                                 using_bloom = true;
872                                 break;
873
874                         case BUS_MATCH_PATH_NAMESPACE:
875                                 if (!streq(c->value_str, "/")) {
876                                         bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
877                                         using_bloom = true;
878                                 }
879                                 break;
880
881                         case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
882                                 char buf[sizeof("arg")-1 + 2 + 1];
883
884                                 if (c->type - BUS_MATCH_ARG < 3)
885                                         name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
886
887                                 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
888                                 bloom_add_pair(bloom, buf, c->value_str);
889                                 using_bloom = true;
890                                 break;
891                         }
892
893                         case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
894                                 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
895
896                                 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
897                                 bloom_add_pair(bloom, buf, c->value_str);
898                                 using_bloom = true;
899                                 break;
900                         }
901
902                         case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
903                                 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
904
905                                 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
906                                 bloom_add_pair(bloom, buf, c->value_str);
907                                 using_bloom = true;
908                                 break;
909                         }
910
911                         case BUS_MATCH_DESTINATION:
912                                 /* The bloom filter does not include
913                                    the destination, since it is only
914                                    available for broadcast messages
915                                    which do not carry a destination
916                                    since they are undirected. */
917                                 break;
918
919                         case BUS_MATCH_ROOT:
920                         case BUS_MATCH_VALUE:
921                         case BUS_MATCH_LEAF:
922                         case _BUS_MATCH_NODE_TYPE_MAX:
923                         case _BUS_MATCH_NODE_TYPE_INVALID:
924                                 assert_not_reached("Invalid match type?");
925                         }
926                 }
927
928                 if (using_bloom)
929                         sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
930
931                 m = alloca0(sz);
932                 m->size = sz;
933                 m->cookie = cookie;
934                 m->src_id = src_id;
935
936                 item = m->items;
937
938                 if (using_bloom) {
939                         item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
940                         item->type = KDBUS_MATCH_BLOOM;
941                         memcpy(item->data64, bloom, BLOOM_SIZE);
942
943                         item = KDBUS_PART_NEXT(item);
944                 }
945
946                 if (sender) {
947                         item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
948                         item->type = KDBUS_MATCH_SRC_NAME;
949                         memcpy(item->str, sender, sender_length + 1);
950                 }
951
952                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
953                 if (r < 0)
954                         return -errno;
955
956                 if (matches_name_change) {
957
958                         /* If this match could theoretically match
959                          * NameOwnerChanged messages, we need to
960                          * install a second non-bloom filter explitly
961                          * for it */
962
963                         r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
964                         if (r < 0)
965                                 return r;
966                 }
967
968                 return 0;
969         } else
970                 return sd_bus_call_method(
971                                 bus,
972                                 "org.freedesktop.DBus",
973                                 "/",
974                                 "org.freedesktop.DBus",
975                                 "AddMatch",
976                                 NULL,
977                                 NULL,
978                                 "s",
979                                 match);
980 }
981
982 int bus_remove_match_internal(
983                 sd_bus *bus,
984                 const char *match,
985                 uint64_t cookie) {
986
987         int r;
988
989         assert(bus);
990         assert(match);
991
992         if (bus->is_kernel) {
993                 struct kdbus_cmd_match m;
994
995                 zero(m);
996                 m.size = offsetof(struct kdbus_cmd_match, items);
997                 m.cookie = cookie;
998
999                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1000                 if (r < 0)
1001                         return -errno;
1002
1003                 return 0;
1004
1005         } else {
1006                 return sd_bus_call_method(
1007                                 bus,
1008                                 "org.freedesktop.DBus",
1009                                 "/",
1010                                 "org.freedesktop.DBus",
1011                                 "RemoveMatch",
1012                                 NULL,
1013                                 NULL,
1014                                 "s",
1015                                 match);
1016         }
1017 }
1018
1019 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1020         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1021         const char *mid;
1022         int r;
1023
1024         assert_return(bus, -EINVAL);
1025         assert_return(name, -EINVAL);
1026         assert_return(machine, -EINVAL);
1027         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1028         assert_return(!bus_pid_changed(bus), -ECHILD);
1029
1030         if (streq_ptr(name, bus->unique_name))
1031                 return sd_id128_get_machine(machine);
1032
1033         r = sd_bus_message_new_method_call(
1034                         bus,
1035                         name,
1036                         "/",
1037                         "org.freedesktop.DBus.Peer",
1038                         "GetMachineId", &m);
1039         if (r < 0)
1040                 return r;
1041
1042         r = sd_bus_message_set_no_auto_start(m, true);
1043         if (r < 0)
1044                 return r;
1045
1046         r = sd_bus_call(bus, m, 0, NULL, &reply);
1047         if (r < 0)
1048                 return r;
1049
1050         r = sd_bus_message_read(reply, "s", &mid);
1051         if (r < 0)
1052                 return r;
1053
1054         return sd_id128_from_string(mid, machine);
1055 }