chiark / gitweb /
Rename more things to elogind
[elogind.git] / src / libelogind / sd-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 #include "sd-bus.h"
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-control.h"
34 #include "bus-bloom.h"
35 #include "bus-util.h"
36 #include "capability.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 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
54         struct kdbus_cmd *n;
55         size_t size, l;
56         int r;
57
58         assert(bus);
59         assert(name);
60
61         l = strlen(name) + 1;
62         size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
63         n = alloca0_align(size, 8);
64         n->size = size;
65         n->flags = request_name_flags_to_kdbus(flags);
66
67         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
68         n->items[0].type = KDBUS_ITEM_NAME;
69         memcpy(n->items[0].str, name, l);
70
71 #ifdef HAVE_VALGRIND_MEMCHECK_H
72         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
73 #endif
74
75         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
76         if (r < 0)
77                 return -errno;
78
79         if (n->return_flags & KDBUS_NAME_IN_QUEUE)
80                 return 0;
81
82         return 1;
83 }
84
85 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
86         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
87         uint32_t ret, param = 0;
88         int r;
89
90         assert(bus);
91         assert(name);
92
93         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
94                 param |= BUS_NAME_ALLOW_REPLACEMENT;
95         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
96                 param |= BUS_NAME_REPLACE_EXISTING;
97         if (!(flags & SD_BUS_NAME_QUEUE))
98                 param |= BUS_NAME_DO_NOT_QUEUE;
99
100         r = sd_bus_call_method(
101                         bus,
102                         "org.freedesktop.DBus",
103                         "/org/freedesktop/DBus",
104                         "org.freedesktop.DBus",
105                         "RequestName",
106                         NULL,
107                         &reply,
108                         "su",
109                         name,
110                         param);
111         if (r < 0)
112                 return r;
113
114         r = sd_bus_message_read(reply, "u", &ret);
115         if (r < 0)
116                 return r;
117
118         if (ret == BUS_NAME_ALREADY_OWNER)
119                 return -EALREADY;
120         else if (ret == BUS_NAME_EXISTS)
121                 return -EEXIST;
122         else if (ret == BUS_NAME_IN_QUEUE)
123                 return 0;
124         else if (ret == BUS_NAME_PRIMARY_OWNER)
125                 return 1;
126
127         return -EIO;
128 }
129
130 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
131         assert_return(bus, -EINVAL);
132         assert_return(name, -EINVAL);
133         assert_return(bus->bus_client, -EINVAL);
134         assert_return(!bus_pid_changed(bus), -ECHILD);
135         assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
136         assert_return(service_name_is_valid(name), -EINVAL);
137         assert_return(name[0] != ':', -EINVAL);
138
139         /* Don't allow requesting the special driver and local names */
140         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
141                 return -EINVAL;
142
143         if (!BUS_IS_OPEN(bus->state))
144                 return -ENOTCONN;
145
146         if (bus->is_kernel)
147                 return bus_request_name_kernel(bus, name, flags);
148         else
149                 return bus_request_name_dbus1(bus, name, flags);
150 }
151
152 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
153         struct kdbus_cmd *n;
154         size_t size, l;
155         int r;
156
157         assert(bus);
158         assert(name);
159
160         l = strlen(name) + 1;
161         size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
162         n = alloca0_align(size, 8);
163         n->size = size;
164
165         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
166         n->items[0].type = KDBUS_ITEM_NAME;
167         memcpy(n->items[0].str, name, l);
168
169 #ifdef HAVE_VALGRIND_MEMCHECK_H
170         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
171 #endif
172         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
173         if (r < 0)
174                 return -errno;
175
176         return 0;
177 }
178
179 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
180         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
181         uint32_t ret;
182         int r;
183
184         assert(bus);
185         assert(name);
186
187         r = sd_bus_call_method(
188                         bus,
189                         "org.freedesktop.DBus",
190                         "/org/freedesktop/DBus",
191                         "org.freedesktop.DBus",
192                         "ReleaseName",
193                         NULL,
194                         &reply,
195                         "s",
196                         name);
197         if (r < 0)
198                 return r;
199
200         r = sd_bus_message_read(reply, "u", &ret);
201         if (r < 0)
202                 return r;
203         if (ret == BUS_NAME_NON_EXISTENT)
204                 return -ESRCH;
205         if (ret == BUS_NAME_NOT_OWNER)
206                 return -EADDRINUSE;
207         if (ret == BUS_NAME_RELEASED)
208                 return 0;
209
210         return -EINVAL;
211 }
212
213 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
214         assert_return(bus, -EINVAL);
215         assert_return(name, -EINVAL);
216         assert_return(bus->bus_client, -EINVAL);
217         assert_return(!bus_pid_changed(bus), -ECHILD);
218         assert_return(service_name_is_valid(name), -EINVAL);
219         assert_return(name[0] != ':', -EINVAL);
220
221         /* Don't allow releasing the special driver and local names */
222         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
223                 return -EINVAL;
224
225         if (!BUS_IS_OPEN(bus->state))
226                 return -ENOTCONN;
227
228         if (bus->is_kernel)
229                 return bus_release_name_kernel(bus, name);
230         else
231                 return bus_release_name_dbus1(bus, name);
232 }
233
234 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
235         struct kdbus_cmd_list cmd = {
236                 .size = sizeof(cmd),
237                 .flags = flags,
238         };
239         struct kdbus_info *name_list, *name;
240         uint64_t previous_id = 0;
241         int r;
242
243         /* Caller will free half-constructed list on failure... */
244
245         r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
246         if (r < 0)
247                 return -errno;
248
249         name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
250
251         KDBUS_FOREACH(name, name_list, cmd.list_size) {
252
253                 struct kdbus_item *item;
254                 const char *entry_name = NULL;
255
256                 if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id) {
257                         char *n;
258
259                         if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
260                                 r = -ENOMEM;
261                                 goto fail;
262                         }
263
264                         r = strv_consume(x, n);
265                         if (r < 0)
266                                 goto fail;
267
268                         previous_id = name->id;
269                 }
270
271                 KDBUS_ITEM_FOREACH(item, name, items)
272                         if (item->type == KDBUS_ITEM_OWNED_NAME)
273                                 entry_name = item->name.name;
274
275                 if (entry_name && service_name_is_valid(entry_name)) {
276                         r = strv_extend(x, entry_name);
277                         if (r < 0) {
278                                 r = -ENOMEM;
279                                 goto fail;
280                         }
281                 }
282         }
283
284         r = 0;
285
286 fail:
287         bus_kernel_cmd_free(bus, cmd.offset);
288         return r;
289 }
290
291 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
292         _cleanup_strv_free_ char **x = NULL, **y = NULL;
293         int r;
294
295         if (acquired) {
296                 r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
297                 if (r < 0)
298                         return r;
299         }
300
301         if (activatable) {
302                 r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
303                 if (r < 0)
304                         return r;
305
306                 *activatable = y;
307                 y = NULL;
308         }
309
310         if (acquired) {
311                 *acquired = x;
312                 x = NULL;
313         }
314
315         return 0;
316 }
317
318 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
319         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
320         _cleanup_strv_free_ char **x = NULL, **y = NULL;
321         int r;
322
323         if (acquired) {
324                 r = sd_bus_call_method(
325                                 bus,
326                                 "org.freedesktop.DBus",
327                                 "/org/freedesktop/DBus",
328                                 "org.freedesktop.DBus",
329                                 "ListNames",
330                                 NULL,
331                                 &reply,
332                                 NULL);
333                 if (r < 0)
334                         return r;
335
336                 r = sd_bus_message_read_strv(reply, &x);
337                 if (r < 0)
338                         return r;
339
340                 reply = sd_bus_message_unref(reply);
341         }
342
343         if (activatable) {
344                 r = sd_bus_call_method(
345                                 bus,
346                                 "org.freedesktop.DBus",
347                                 "/org/freedesktop/DBus",
348                                 "org.freedesktop.DBus",
349                                 "ListActivatableNames",
350                                 NULL,
351                                 &reply,
352                                 NULL);
353                 if (r < 0)
354                         return r;
355
356                 r = sd_bus_message_read_strv(reply, &y);
357                 if (r < 0)
358                         return r;
359
360                 *activatable = y;
361                 y = NULL;
362         }
363
364         if (acquired) {
365                 *acquired = x;
366                 x = NULL;
367         }
368
369         return 0;
370 }
371
372 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
373         assert_return(bus, -EINVAL);
374         assert_return(acquired || activatable, -EINVAL);
375         assert_return(!bus_pid_changed(bus), -ECHILD);
376
377         if (!BUS_IS_OPEN(bus->state))
378                 return -ENOTCONN;
379
380         if (bus->is_kernel)
381                 return bus_list_names_kernel(bus, acquired, activatable);
382         else
383                 return bus_list_names_dbus1(bus, acquired, activatable);
384 }
385
386 static int bus_populate_creds_from_items(
387                 sd_bus *bus,
388                 struct kdbus_info *info,
389                 uint64_t mask,
390                 sd_bus_creds *c) {
391
392         struct kdbus_item *item;
393         uint64_t m;
394         int r;
395
396         assert(bus);
397         assert(info);
398         assert(c);
399
400         KDBUS_ITEM_FOREACH(item, info, items) {
401
402                 switch (item->type) {
403
404                 case KDBUS_ITEM_PIDS:
405
406                         if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
407                                 c->pid = (pid_t) item->pids.pid;
408                                 c->mask |= SD_BUS_CREDS_PID;
409                         }
410
411                         if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
412                                 c->tid = (pid_t) item->pids.tid;
413                                 c->mask |= SD_BUS_CREDS_TID;
414                         }
415
416                         break;
417
418                 case KDBUS_ITEM_CREDS:
419
420                         if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
421                                 c->uid = (uid_t) item->creds.uid;
422                                 c->mask |= SD_BUS_CREDS_UID;
423                         }
424
425                         if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
426                                 c->euid = (uid_t) item->creds.euid;
427                                 c->mask |= SD_BUS_CREDS_EUID;
428                         }
429
430                         if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
431                                 c->suid = (uid_t) item->creds.suid;
432                                 c->mask |= SD_BUS_CREDS_SUID;
433                         }
434
435                         if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
436                                 c->fsuid = (uid_t) item->creds.fsuid;
437                                 c->mask |= SD_BUS_CREDS_FSUID;
438                         }
439
440                         if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
441                                 c->gid = (gid_t) item->creds.gid;
442                                 c->mask |= SD_BUS_CREDS_GID;
443                         }
444
445                         if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
446                                 c->egid = (gid_t) item->creds.egid;
447                                 c->mask |= SD_BUS_CREDS_EGID;
448                         }
449
450                         if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
451                                 c->sgid = (gid_t) item->creds.sgid;
452                                 c->mask |= SD_BUS_CREDS_SGID;
453                         }
454
455                         if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
456                                 c->fsgid = (gid_t) item->creds.fsgid;
457                                 c->mask |= SD_BUS_CREDS_FSGID;
458                         }
459
460                         break;
461
462                 case KDBUS_ITEM_PID_COMM:
463                         if (mask & SD_BUS_CREDS_COMM) {
464                                 r = free_and_strdup(&c->comm, item->str);
465                                 if (r < 0)
466                                         return r;
467
468                                 c->mask |= SD_BUS_CREDS_COMM;
469                         }
470                         break;
471
472                 case KDBUS_ITEM_TID_COMM:
473                         if (mask & SD_BUS_CREDS_TID_COMM) {
474                                 r = free_and_strdup(&c->tid_comm, item->str);
475                                 if (r < 0)
476                                         return r;
477
478                                 c->mask |= SD_BUS_CREDS_TID_COMM;
479                         }
480                         break;
481
482                 case KDBUS_ITEM_EXE:
483                         if (mask & SD_BUS_CREDS_EXE) {
484                                 r = free_and_strdup(&c->exe, item->str);
485                                 if (r < 0)
486                                         return r;
487
488                                 c->mask |= SD_BUS_CREDS_EXE;
489                         }
490                         break;
491
492                 case KDBUS_ITEM_CMDLINE:
493                         if (mask & SD_BUS_CREDS_CMDLINE) {
494                                 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
495                                 c->cmdline = memdup(item->data, c->cmdline_size);
496                                 if (!c->cmdline)
497                                         return -ENOMEM;
498
499                                 c->mask |= SD_BUS_CREDS_CMDLINE;
500                         }
501                         break;
502
503                 case KDBUS_ITEM_CGROUP:
504                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
505                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
506                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
507
508                         if (m) {
509                                 r = free_and_strdup(&c->cgroup, item->str);
510                                 if (r < 0)
511                                         return r;
512
513                                 r = bus_get_root_path(bus);
514                                 if (r < 0)
515                                         return r;
516
517                                 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
518                                 if (r < 0)
519                                         return r;
520
521                                 c->mask |= m;
522                         }
523                         break;
524
525                 case KDBUS_ITEM_CAPS:
526                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
527                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
528
529                         if (m) {
530                                 if (item->caps.last_cap != cap_last_cap() ||
531                                     item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
532                                         return -EBADMSG;
533
534                                 c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
535                                 if (!c->capability)
536                                         return -ENOMEM;
537
538                                 c->mask |= m;
539                         }
540                         break;
541
542                 case KDBUS_ITEM_SECLABEL:
543                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
544                                 r = free_and_strdup(&c->label, item->str);
545                                 if (r < 0)
546                                         return r;
547
548                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
549                         }
550                         break;
551
552                 case KDBUS_ITEM_AUDIT:
553                         if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID && (uint32_t) item->audit.sessionid != (uint32_t) -1) {
554                                 c->audit_session_id = (uint32_t) item->audit.sessionid;
555                                 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
556                         }
557
558                         if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID && (uid_t) item->audit.loginuid != UID_INVALID) {
559                                 c->audit_login_uid = (uid_t) item->audit.loginuid;
560                                 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
561                         }
562                         break;
563
564                 case KDBUS_ITEM_OWNED_NAME:
565                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
566                                 r = strv_extend(&c->well_known_names, item->name.name);
567                                 if (r < 0)
568                                         return r;
569
570                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
571                         }
572                         break;
573
574                 case KDBUS_ITEM_CONN_DESCRIPTION:
575                         if (mask & SD_BUS_CREDS_DESCRIPTION) {
576                                 r = free_and_strdup(&c->description, item->str);
577                                 if (r < 0)
578                                         return r;
579
580                                 c->mask |= SD_BUS_CREDS_DESCRIPTION;
581                         }
582                         break;
583
584                 case KDBUS_ITEM_AUXGROUPS:
585                         if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
586                                 size_t i, n;
587                                 uid_t *g;
588
589                                 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
590                                 g = new(gid_t, n);
591                                 if (!g)
592                                         return -ENOMEM;
593
594                                 for (i = 0; i < n; i++)
595                                         g[i] = item->data64[i];
596
597                                 free(c->supplementary_gids);
598                                 c->supplementary_gids = g;
599                                 c->n_supplementary_gids = n;
600
601                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
602                         }
603                         break;
604                 }
605         }
606
607         return 0;
608 }
609
610 int bus_get_name_creds_kdbus(
611                 sd_bus *bus,
612                 const char *name,
613                 uint64_t mask,
614                 bool allow_activator,
615                 sd_bus_creds **creds) {
616
617         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
618         struct kdbus_cmd_info *cmd;
619         struct kdbus_info *conn_info;
620         size_t size, l;
621         uint64_t id;
622         int r;
623
624         if (streq(name, "org.freedesktop.DBus"))
625                 return -EOPNOTSUPP;
626
627         r = bus_kernel_parse_unique_name(name, &id);
628         if (r < 0)
629                 return r;
630         if (r > 0) {
631                 size = offsetof(struct kdbus_cmd_info, items);
632                 cmd = alloca0_align(size, 8);
633                 cmd->id = id;
634         } else {
635                 l = strlen(name) + 1;
636                 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
637                 cmd = alloca0_align(size, 8);
638                 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
639                 cmd->items[0].type = KDBUS_ITEM_NAME;
640                 memcpy(cmd->items[0].str, name, l);
641         }
642
643         /* If augmentation is on, and the bus didn't provide us
644          * the bits we want, then ask for the PID/TID so that we
645          * can read the rest from /proc. */
646         if ((mask & SD_BUS_CREDS_AUGMENT) &&
647             (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
648                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
649                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
650                      SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
651                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
652                      SD_BUS_CREDS_SELINUX_CONTEXT|
653                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
654                 mask |= SD_BUS_CREDS_PID;
655
656         cmd->size = size;
657         cmd->attach_flags = attach_flags_to_kdbus(mask);
658
659         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
660         if (r < 0)
661                 return -errno;
662
663         conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
664
665         /* Non-activated names are considered not available */
666         if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
667                 if (name[0] == ':')
668                         r = -ENXIO;
669                 else
670                         r = -ESRCH;
671                 goto fail;
672         }
673
674         c = bus_creds_new();
675         if (!c) {
676                 r = -ENOMEM;
677                 goto fail;
678         }
679
680         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
681                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
682                         r = -ENOMEM;
683                         goto fail;
684                 }
685
686                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
687         }
688
689         /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
690            them in case the service has no names. This does not mean
691            however that the list of owned names could not be
692            acquired. Hence, let's explicitly clarify that the data is
693            complete. */
694         c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
695
696         r = bus_populate_creds_from_items(bus, conn_info, mask, c);
697         if (r < 0)
698                 goto fail;
699
700         r = bus_creds_add_more(c, mask, 0, 0);
701         if (r < 0)
702                 goto fail;
703
704         if (creds) {
705                 *creds = c;
706                 c = NULL;
707         }
708
709         r = 0;
710
711 fail:
712         bus_kernel_cmd_free(bus, cmd->offset);
713         return r;
714 }
715
716 static int bus_get_name_creds_dbus1(
717                 sd_bus *bus,
718                 const char *name,
719                 uint64_t mask,
720                 sd_bus_creds **creds) {
721
722         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
723         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
724         const char *unique = NULL;
725         pid_t pid = 0;
726         int r;
727
728         /* Only query the owner if the caller wants to know it or if
729          * the caller just wants to check whether a name exists */
730         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
731                 r = sd_bus_call_method(
732                                 bus,
733                                 "org.freedesktop.DBus",
734                                 "/org/freedesktop/DBus",
735                                 "org.freedesktop.DBus",
736                                 "GetNameOwner",
737                                 NULL,
738                                 &reply_unique,
739                                 "s",
740                                 name);
741                 if (r < 0)
742                         return r;
743
744                 r = sd_bus_message_read(reply_unique, "s", &unique);
745                 if (r < 0)
746                         return r;
747         }
748
749         if (mask != 0) {
750                 c = bus_creds_new();
751                 if (!c)
752                         return -ENOMEM;
753
754                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
755                         c->unique_name = strdup(unique);
756                         if (!c->unique_name)
757                                 return -ENOMEM;
758
759                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
760                 }
761
762                 if ((mask & SD_BUS_CREDS_PID) ||
763                     ((mask & SD_BUS_CREDS_AUGMENT) &&
764                      (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
765                               SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
766                               SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
767                               SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
768                               SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
769                               SD_BUS_CREDS_SELINUX_CONTEXT|
770                               SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
771
772                         uint32_t u;
773
774                         r = sd_bus_call_method(
775                                         bus,
776                                         "org.freedesktop.DBus",
777                                         "/org/freedesktop/DBus",
778                                         "org.freedesktop.DBus",
779                                         "GetConnectionUnixProcessID",
780                                         NULL,
781                                         &reply,
782                                         "s",
783                                         unique ? unique : name);
784                         if (r < 0)
785                                 return r;
786
787                         r = sd_bus_message_read(reply, "u", &u);
788                         if (r < 0)
789                                 return r;
790
791                         pid = u;
792                         if (mask & SD_BUS_CREDS_PID) {
793                                 c->pid = u;
794                                 c->mask |= SD_BUS_CREDS_PID;
795                         }
796
797                         reply = sd_bus_message_unref(reply);
798                 }
799
800                 if (mask & SD_BUS_CREDS_EUID) {
801                         uint32_t u;
802
803                         r = sd_bus_call_method(
804                                         bus,
805                                         "org.freedesktop.DBus",
806                                         "/org/freedesktop/DBus",
807                                         "org.freedesktop.DBus",
808                                         "GetConnectionUnixUser",
809                                         NULL,
810                                         &reply,
811                                         "s",
812                                         unique ? unique : name);
813                         if (r < 0)
814                                 return r;
815
816                         r = sd_bus_message_read(reply, "u", &u);
817                         if (r < 0)
818                                 return r;
819
820                         c->euid = u;
821                         c->mask |= SD_BUS_CREDS_EUID;
822
823                         reply = sd_bus_message_unref(reply);
824                 }
825
826                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
827                         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
828                         const void *p = NULL;
829                         size_t sz = 0;
830
831                         r = sd_bus_call_method(
832                                         bus,
833                                         "org.freedesktop.DBus",
834                                         "/org/freedesktop/DBus",
835                                         "org.freedesktop.DBus",
836                                         "GetConnectionSELinuxSecurityContext",
837                                         &error,
838                                         &reply,
839                                         "s",
840                                         unique ? unique : name);
841                         if (r < 0) {
842                                 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
843                                         return r;
844                         } else {
845                                 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
846                                 if (r < 0)
847                                         return r;
848
849                                 c->label = strndup(p, sz);
850                                 if (!c->label)
851                                         return -ENOMEM;
852
853                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
854                         }
855                 }
856
857                 r = bus_creds_add_more(c, mask, pid, 0);
858                 if (r < 0)
859                         return r;
860         }
861
862         if (creds) {
863                 *creds = c;
864                 c = NULL;
865         }
866
867         return 0;
868 }
869
870 _public_ int sd_bus_get_name_creds(
871                 sd_bus *bus,
872                 const char *name,
873                 uint64_t mask,
874                 sd_bus_creds **creds) {
875
876         assert_return(bus, -EINVAL);
877         assert_return(name, -EINVAL);
878         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
879         assert_return(mask == 0 || creds, -EINVAL);
880         assert_return(!bus_pid_changed(bus), -ECHILD);
881         assert_return(service_name_is_valid(name), -EINVAL);
882         assert_return(bus->bus_client, -ENODATA);
883
884         if (streq(name, "org.freedesktop.DBus.Local"))
885                 return -EINVAL;
886
887         if (!BUS_IS_OPEN(bus->state))
888                 return -ENOTCONN;
889
890         if (bus->is_kernel)
891                 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
892         else
893                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
894 }
895
896 static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
897         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
898         struct kdbus_cmd_info cmd = {
899                 .size = sizeof(struct kdbus_cmd_info),
900         };
901         struct kdbus_info *creator_info;
902         pid_t pid = 0;
903         int r;
904
905         c = bus_creds_new();
906         if (!c)
907                 return -ENOMEM;
908
909         /* If augmentation is on, and the bus doesn't didn't allow us
910          * to get the bits we want, then ask for the PID/TID so that we
911          * can read the rest from /proc. */
912         if ((mask & SD_BUS_CREDS_AUGMENT) &&
913             (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
914                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
915                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
916                      SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
917                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
918                      SD_BUS_CREDS_SELINUX_CONTEXT|
919                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
920                 mask |= SD_BUS_CREDS_PID;
921
922         cmd.attach_flags = attach_flags_to_kdbus(mask);
923
924         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
925         if (r < 0)
926                 return -errno;
927
928         creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
929
930         r = bus_populate_creds_from_items(bus, creator_info, mask, c);
931         bus_kernel_cmd_free(bus, cmd.offset);
932         if (r < 0)
933                 return r;
934
935         r = bus_creds_add_more(c, mask, pid, 0);
936         if (r < 0)
937                 return r;
938
939         *ret = c;
940         c = NULL;
941         return 0;
942 }
943
944 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
945         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
946         pid_t pid = 0;
947         int r;
948
949         if (!bus->ucred_valid && !isempty(bus->label))
950                 return -ENODATA;
951
952         c = bus_creds_new();
953         if (!c)
954                 return -ENOMEM;
955
956         if (bus->ucred_valid) {
957                 if (bus->ucred.pid > 0) {
958                         pid = c->pid = bus->ucred.pid;
959                         c->mask |= SD_BUS_CREDS_PID & mask;
960                 }
961
962                 if (bus->ucred.uid != UID_INVALID) {
963                         c->euid = bus->ucred.uid;
964                         c->mask |= SD_BUS_CREDS_EUID & mask;
965                 }
966
967                 if (bus->ucred.gid != GID_INVALID) {
968                         c->egid = bus->ucred.gid;
969                         c->mask |= SD_BUS_CREDS_EGID & mask;
970                 }
971         }
972
973         if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
974                 c->label = strdup(bus->label);
975                 if (!c->label)
976                         return -ENOMEM;
977
978                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
979         }
980
981         r = bus_creds_add_more(c, mask, pid, 0);
982         if (r < 0)
983                 return r;
984
985         *ret = c;
986         c = NULL;
987         return 0;
988 }
989
990 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
991         assert_return(bus, -EINVAL);
992         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
993         assert_return(ret, -EINVAL);
994         assert_return(!bus_pid_changed(bus), -ECHILD);
995
996         if (!BUS_IS_OPEN(bus->state))
997                 return -ENOTCONN;
998
999         if (bus->is_kernel)
1000                 return bus_get_owner_creds_kdbus(bus, mask, ret);
1001         else
1002                 return bus_get_owner_creds_dbus1(bus, mask, ret);
1003 }
1004
1005 static int add_name_change_match(sd_bus *bus,
1006                                  uint64_t cookie,
1007                                  const char *name,
1008                                  const char *old_owner,
1009                                  const char *new_owner) {
1010
1011         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
1012         int is_name_id = -1, r;
1013         struct kdbus_item *item;
1014
1015         assert(bus);
1016
1017         /* If we encounter a match that could match against
1018          * NameOwnerChanged messages, then we need to create
1019          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
1020          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
1021          * multiple if the match is underspecified.
1022          *
1023          * The NameOwnerChanged signals take three parameters with
1024          * unique or well-known names, but only some forms actually
1025          * exist:
1026          *
1027          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
1028          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
1029          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
1030          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
1031          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
1032          *
1033          * For the latter two the two unique names must be identical.
1034          *
1035          * */
1036
1037         if (name) {
1038                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
1039                 if (is_name_id < 0)
1040                         return 0;
1041         }
1042
1043         if (!isempty(old_owner)) {
1044                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
1045                 if (r < 0)
1046                         return 0;
1047                 if (r == 0)
1048                         return 0;
1049                 if (is_name_id > 0 && old_owner_id != name_id)
1050                         return 0;
1051         } else
1052                 old_owner_id = KDBUS_MATCH_ID_ANY;
1053
1054         if (!isempty(new_owner)) {
1055                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
1056                 if (r < 0)
1057                         return r;
1058                 if (r == 0)
1059                         return 0;
1060                 if (is_name_id > 0 && new_owner_id != name_id)
1061                         return 0;
1062         } else
1063                 new_owner_id = KDBUS_MATCH_ID_ANY;
1064
1065         if (is_name_id <= 0) {
1066                 struct kdbus_cmd_match *m;
1067                 size_t sz, l;
1068
1069                 /* If the name argument is missing or is a well-known
1070                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
1071                  * matches for it */
1072
1073                 l = name ? strlen(name) + 1 : 0;
1074
1075                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1076                             offsetof(struct kdbus_item, name_change) +
1077                             offsetof(struct kdbus_notify_name_change, name) +
1078                             l);
1079
1080                 m = alloca0_align(sz, 8);
1081                 m->size = sz;
1082                 m->cookie = cookie;
1083
1084                 item = m->items;
1085                 item->size =
1086                         offsetof(struct kdbus_item, name_change) +
1087                         offsetof(struct kdbus_notify_name_change, name) +
1088                         l;
1089
1090                 item->name_change.old_id.id = old_owner_id;
1091                 item->name_change.new_id.id = new_owner_id;
1092
1093                 if (name)
1094                         memcpy(item->name_change.name, name, l);
1095
1096                 /* If the old name is unset or empty, then
1097                  * this can match against added names */
1098                 if (!old_owner || old_owner[0] == 0) {
1099                         item->type = KDBUS_ITEM_NAME_ADD;
1100
1101                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1102                         if (r < 0)
1103                                 return -errno;
1104                 }
1105
1106                 /* If the new name is unset or empty, then
1107                  * this can match against removed names */
1108                 if (!new_owner || new_owner[0] == 0) {
1109                         item->type = KDBUS_ITEM_NAME_REMOVE;
1110
1111                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1112                         if (r < 0)
1113                                 return -errno;
1114                 }
1115
1116                 /* The CHANGE match we need in either case, because
1117                  * what is reported as a name change by the kernel
1118                  * might just be an owner change between starter and
1119                  * normal clients. For userspace such a change should
1120                  * be considered a removal/addition, hence let's
1121                  * subscribe to this unconditionally. */
1122                 item->type = KDBUS_ITEM_NAME_CHANGE;
1123                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1124                 if (r < 0)
1125                         return -errno;
1126         }
1127
1128         if (is_name_id != 0) {
1129                 struct kdbus_cmd_match *m;
1130                 uint64_t sz;
1131
1132                 /* If the name argument is missing or is a unique
1133                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
1134                  * for it */
1135
1136                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
1137                             offsetof(struct kdbus_item, id_change) +
1138                             sizeof(struct kdbus_notify_id_change));
1139
1140                 m = alloca0_align(sz, 8);
1141                 m->size = sz;
1142                 m->cookie = cookie;
1143
1144                 item = m->items;
1145                 item->size =
1146                         offsetof(struct kdbus_item, id_change) +
1147                         sizeof(struct kdbus_notify_id_change);
1148                 item->id_change.id = name_id;
1149
1150                 /* If the old name is unset or empty, then this can
1151                  * match against added ids */
1152                 if (!old_owner || old_owner[0] == 0) {
1153                         item->type = KDBUS_ITEM_ID_ADD;
1154
1155                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1156                         if (r < 0)
1157                                 return -errno;
1158                 }
1159
1160                 /* If thew new name is unset or empty, then this can
1161                  * match against removed ids */
1162                 if (!new_owner || new_owner[0] == 0) {
1163                         item->type = KDBUS_ITEM_ID_REMOVE;
1164
1165                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1166                         if (r < 0)
1167                                 return -errno;
1168                 }
1169         }
1170
1171         return 0;
1172 }
1173
1174 int bus_add_match_internal_kernel(
1175                 sd_bus *bus,
1176                 struct bus_match_component *components,
1177                 unsigned n_components,
1178                 uint64_t cookie) {
1179
1180         struct kdbus_cmd_match *m;
1181         struct kdbus_item *item;
1182         uint64_t *bloom;
1183         size_t sz;
1184         const char *sender = NULL;
1185         size_t sender_length = 0;
1186         uint64_t src_id = KDBUS_MATCH_ID_ANY;
1187         bool using_bloom = false;
1188         unsigned i;
1189         bool matches_name_change = true;
1190         const char *name_change_arg[3] = {};
1191         int r;
1192
1193         assert(bus);
1194
1195         /* Monitor streams don't support matches, make this a NOP */
1196         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1197                 return 0;
1198
1199         bloom = alloca0(bus->bloom_size);
1200
1201         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1202
1203         for (i = 0; i < n_components; i++) {
1204                 struct bus_match_component *c = &components[i];
1205
1206                 switch (c->type) {
1207
1208                 case BUS_MATCH_SENDER:
1209                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1210                                 matches_name_change = false;
1211
1212                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1213                         if (r < 0)
1214                                 return r;
1215                         else if (r > 0)
1216                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1217                         else  {
1218                                 sender = c->value_str;
1219                                 sender_length = strlen(sender);
1220                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1221                         }
1222
1223                         break;
1224
1225                 case BUS_MATCH_MESSAGE_TYPE:
1226                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1227                                 matches_name_change = false;
1228
1229                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1230                         using_bloom = true;
1231                         break;
1232
1233                 case BUS_MATCH_INTERFACE:
1234                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1235                                 matches_name_change = false;
1236
1237                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1238                         using_bloom = true;
1239                         break;
1240
1241                 case BUS_MATCH_MEMBER:
1242                         if (!streq(c->value_str, "NameOwnerChanged"))
1243                                 matches_name_change = false;
1244
1245                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1246                         using_bloom = true;
1247                         break;
1248
1249                 case BUS_MATCH_PATH:
1250                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1251                                 matches_name_change = false;
1252
1253                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1254                         using_bloom = true;
1255                         break;
1256
1257                 case BUS_MATCH_PATH_NAMESPACE:
1258                         if (!streq(c->value_str, "/")) {
1259                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1260                                 using_bloom = true;
1261                         }
1262                         break;
1263
1264                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1265                         char buf[sizeof("arg")-1 + 2 + 1];
1266
1267                         if (c->type - BUS_MATCH_ARG < 3)
1268                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1269
1270                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
1271                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1272                         using_bloom = true;
1273                         break;
1274                 }
1275
1276                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1277                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1278
1279                         xsprintf(buf, "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1280                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1281                         using_bloom = true;
1282                         break;
1283                 }
1284
1285                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1286                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1287
1288                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1289                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1290                         using_bloom = true;
1291                         break;
1292                 }
1293
1294                 case BUS_MATCH_DESTINATION:
1295                         /* The bloom filter does not include
1296                            the destination, since it is only
1297                            available for broadcast messages
1298                            which do not carry a destination
1299                            since they are undirected. */
1300                         break;
1301
1302                 case BUS_MATCH_ROOT:
1303                 case BUS_MATCH_VALUE:
1304                 case BUS_MATCH_LEAF:
1305                 case _BUS_MATCH_NODE_TYPE_MAX:
1306                 case _BUS_MATCH_NODE_TYPE_INVALID:
1307                         assert_not_reached("Invalid match type?");
1308                 }
1309         }
1310
1311         if (using_bloom)
1312                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1313
1314         m = alloca0_align(sz, 8);
1315         m->size = sz;
1316         m->cookie = cookie;
1317
1318         item = m->items;
1319
1320         if (src_id != KDBUS_MATCH_ID_ANY) {
1321                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1322                 item->type = KDBUS_ITEM_ID;
1323                 item->id = src_id;
1324                 item = KDBUS_ITEM_NEXT(item);
1325         }
1326
1327         if (using_bloom) {
1328                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1329                 item->type = KDBUS_ITEM_BLOOM_MASK;
1330                 memcpy(item->data64, bloom, bus->bloom_size);
1331                 item = KDBUS_ITEM_NEXT(item);
1332         }
1333
1334         if (sender) {
1335                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1336                 item->type = KDBUS_ITEM_NAME;
1337                 memcpy(item->str, sender, sender_length + 1);
1338         }
1339
1340         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1341         if (r < 0)
1342                 return -errno;
1343
1344         if (matches_name_change) {
1345
1346                 /* If this match could theoretically match
1347                  * NameOwnerChanged messages, we need to
1348                  * install a second non-bloom filter explitly
1349                  * for it */
1350
1351                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1352                 if (r < 0)
1353                         return r;
1354         }
1355
1356         return 0;
1357 }
1358
1359 #define internal_match(bus, m)                                          \
1360         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1361          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
1362          : (m))
1363
1364 static int bus_add_match_internal_dbus1(
1365                 sd_bus *bus,
1366                 const char *match) {
1367
1368         const char *e;
1369
1370         assert(bus);
1371         assert(match);
1372
1373         e = internal_match(bus, match);
1374
1375         return sd_bus_call_method(
1376                         bus,
1377                         "org.freedesktop.DBus",
1378                         "/org/freedesktop/DBus",
1379                         "org.freedesktop.DBus",
1380                         "AddMatch",
1381                         NULL,
1382                         NULL,
1383                         "s",
1384                         e);
1385 }
1386
1387 int bus_add_match_internal(
1388                 sd_bus *bus,
1389                 const char *match,
1390                 struct bus_match_component *components,
1391                 unsigned n_components,
1392                 uint64_t cookie) {
1393
1394         assert(bus);
1395
1396         if (bus->is_kernel)
1397                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1398         else
1399                 return bus_add_match_internal_dbus1(bus, match);
1400 }
1401
1402 int bus_remove_match_internal_kernel(
1403                 sd_bus *bus,
1404                 uint64_t cookie) {
1405
1406         struct kdbus_cmd_match m = {
1407                 .size = offsetof(struct kdbus_cmd_match, items),
1408                 .cookie = cookie,
1409         };
1410         int r;
1411
1412         assert(bus);
1413
1414         /* Monitor streams don't support matches, make this a NOP */
1415         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
1416                 return 0;
1417
1418         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1419         if (r < 0)
1420                 return -errno;
1421
1422         return 0;
1423 }
1424
1425 static int bus_remove_match_internal_dbus1(
1426                 sd_bus *bus,
1427                 const char *match) {
1428
1429         const char *e;
1430
1431         assert(bus);
1432         assert(match);
1433
1434         e = internal_match(bus, match);
1435
1436         return sd_bus_call_method(
1437                         bus,
1438                         "org.freedesktop.DBus",
1439                         "/org/freedesktop/DBus",
1440                         "org.freedesktop.DBus",
1441                         "RemoveMatch",
1442                         NULL,
1443                         NULL,
1444                         "s",
1445                         e);
1446 }
1447
1448 int bus_remove_match_internal(
1449                 sd_bus *bus,
1450                 const char *match,
1451                 uint64_t cookie) {
1452
1453         assert(bus);
1454
1455         if (bus->is_kernel)
1456                 return bus_remove_match_internal_kernel(bus, cookie);
1457         else
1458                 return bus_remove_match_internal_dbus1(bus, match);
1459 }
1460
1461 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1462         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1463         const char *mid;
1464         int r;
1465
1466         assert_return(bus, -EINVAL);
1467         assert_return(name, -EINVAL);
1468         assert_return(machine, -EINVAL);
1469         assert_return(!bus_pid_changed(bus), -ECHILD);
1470         assert_return(service_name_is_valid(name), -EINVAL);
1471
1472         if (!BUS_IS_OPEN(bus->state))
1473                 return -ENOTCONN;
1474
1475         if (streq_ptr(name, bus->unique_name))
1476                 return sd_id128_get_machine(machine);
1477
1478         r = sd_bus_message_new_method_call(
1479                         bus,
1480                         &m,
1481                         name,
1482                         "/",
1483                         "org.freedesktop.DBus.Peer",
1484                         "GetMachineId");
1485         if (r < 0)
1486                 return r;
1487
1488         r = sd_bus_message_set_auto_start(m, false);
1489         if (r < 0)
1490                 return r;
1491
1492         r = sd_bus_call(bus, m, 0, NULL, &reply);
1493         if (r < 0)
1494                 return r;
1495
1496         r = sd_bus_message_read(reply, "s", &mid);
1497         if (r < 0)
1498                 return r;
1499
1500         return sd_id128_from_string(mid, machine);
1501 }