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