1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-control.h"
35 #include "bus-bloom.h"
38 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
45 if (bus_pid_changed(bus))
48 r = bus_ensure_running(bus);
52 *unique = bus->unique_name;
56 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
57 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
67 if (!BUS_IS_OPEN(bus->state))
69 if (bus_pid_changed(bus))
73 struct kdbus_cmd_name *n;
77 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
78 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
80 memcpy(n->name, name, l+1);
82 #ifdef HAVE_VALGRIND_MEMCHECK_H
83 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
86 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
92 r = sd_bus_call_method(
94 "org.freedesktop.DBus",
96 "org.freedesktop.DBus",
106 r = sd_bus_message_read(reply, "u", &ret);
114 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
115 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
123 if (!bus->bus_client)
125 if (!BUS_IS_OPEN(bus->state))
127 if (bus_pid_changed(bus))
130 if (bus->is_kernel) {
131 struct kdbus_cmd_name *n;
135 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
136 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
137 memcpy(n->name, name, l+1);
139 #ifdef HAVE_VALGRIND_MEMCHECK_H
140 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
142 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
148 r = sd_bus_call_method(
150 "org.freedesktop.DBus",
152 "org.freedesktop.DBus",
161 r = sd_bus_message_read(reply, "u", &ret);
169 _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
170 _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
178 if (!BUS_IS_OPEN(bus->state))
180 if (bus_pid_changed(bus))
183 r = sd_bus_call_method(
185 "org.freedesktop.DBus",
187 "org.freedesktop.DBus",
195 r = sd_bus_call_method(
197 "org.freedesktop.DBus",
199 "org.freedesktop.DBus",
200 "ListActivatableNames",
207 r = bus_message_read_strv_extend(reply1, &x);
213 r = bus_message_read_strv_extend(reply2, &x);
223 _public_ int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
224 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
228 assert_return(bus, -EINVAL);
229 assert_return(name, -EINVAL);
230 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
231 assert_return(!bus_pid_changed(bus), -ECHILD);
233 r = sd_bus_call_method(
235 "org.freedesktop.DBus",
237 "org.freedesktop.DBus",
246 r = sd_bus_message_read(reply, "s", &found);
263 _public_ int sd_bus_get_owner_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds) {
264 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
265 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
269 assert_return(bus, -EINVAL);
270 assert_return(name, -EINVAL);
271 assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
272 assert_return(creds, -EINVAL);
273 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
274 assert_return(!bus_pid_changed(bus), -ECHILD);
280 if ((mask & SD_BUS_CREDS_PID) ||
281 mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
284 r = sd_bus_call_method(
286 "org.freedesktop.DBus",
288 "org.freedesktop.DBus",
289 "GetConnectionUnixProcessID",
297 r = sd_bus_message_read(reply, "u", &u);
302 if (mask & SD_BUS_CREDS_PID) {
304 c->mask |= SD_BUS_CREDS_PID;
307 reply = sd_bus_message_unref(reply);
310 if (mask & SD_BUS_CREDS_UID) {
313 r = sd_bus_call_method(
315 "org.freedesktop.DBus",
317 "org.freedesktop.DBus",
318 "GetConnectionUnixUser",
326 r = sd_bus_message_read(reply, "u", &u);
331 c->mask |= SD_BUS_CREDS_UID;
333 reply = sd_bus_message_unref(reply);
336 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
340 r = sd_bus_call_method(
342 "org.freedesktop.DBus",
344 "org.freedesktop.DBus",
345 "GetConnectionSELinuxSecurityContext",
353 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
357 c->label = strndup(p, sz);
361 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
364 r = bus_creds_add_more(c, mask, pid, 0);
374 int bus_add_match_internal(
377 struct bus_match_component *components,
378 unsigned n_components,
386 if (bus->is_kernel) {
387 struct kdbus_cmd_match *m;
388 struct kdbus_item *item;
389 uint64_t bloom[BLOOM_SIZE/8];
391 const char *sender = NULL;
392 size_t sender_length = 0;
393 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
394 bool using_bloom = false;
399 sz = offsetof(struct kdbus_cmd_match, items);
401 for (i = 0; i < n_components; i++) {
402 struct bus_match_component *c = &components[i];
406 case BUS_MATCH_SENDER:
407 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
412 sender = c->value_str;
413 sender_length = strlen(sender);
414 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
419 case BUS_MATCH_MESSAGE_TYPE:
420 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
424 case BUS_MATCH_INTERFACE:
425 bloom_add_pair(bloom, "interface", c->value_str);
429 case BUS_MATCH_MEMBER:
430 bloom_add_pair(bloom, "member", c->value_str);
435 bloom_add_pair(bloom, "path", c->value_str);
439 case BUS_MATCH_PATH_NAMESPACE:
440 if (!streq(c->value_str, "/")) {
441 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
446 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
447 char buf[sizeof("arg")-1 + 2 + 1];
449 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
450 bloom_add_pair(bloom, buf, c->value_str);
455 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
456 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
458 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
459 bloom_add_pair(bloom, buf, c->value_str);
464 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
465 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
467 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
468 bloom_add_pair(bloom, buf, c->value_str);
473 case BUS_MATCH_DESTINATION:
474 /* The bloom filter does not include
475 the destination, since it is only
476 available for broadcast messages
477 which do not carry a destination
478 since they are undirected. */
482 case BUS_MATCH_VALUE:
484 case _BUS_MATCH_NODE_TYPE_MAX:
485 case _BUS_MATCH_NODE_TYPE_INVALID:
486 assert_not_reached("Invalid match type?");
491 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
501 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
502 item->type = KDBUS_MATCH_BLOOM;
503 memcpy(item->data64, bloom, BLOOM_SIZE);
505 item = KDBUS_ITEM_NEXT(item);
509 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
510 item->type = KDBUS_MATCH_SRC_NAME;
511 memcpy(item->str, sender, sender_length + 1);
514 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
519 return sd_bus_call_method(
521 "org.freedesktop.DBus",
523 "org.freedesktop.DBus",
534 int bus_remove_match_internal(
544 if (bus->is_kernel) {
545 struct kdbus_cmd_match m;
548 m.size = offsetof(struct kdbus_cmd_match, items);
551 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
556 return sd_bus_call_method(
558 "org.freedesktop.DBus",
560 "org.freedesktop.DBus",
571 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
572 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
576 assert_return(bus, -EINVAL);
577 assert_return(name, -EINVAL);
578 assert_return(machine, -EINVAL);
579 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
580 assert_return(!bus_pid_changed(bus), -ECHILD);
582 if (streq_ptr(name, bus->unique_name))
583 return sd_id128_get_machine(machine);
585 r = sd_bus_message_new_method_call(
589 "org.freedesktop.DBus.Peer",
594 r = sd_bus_message_set_no_auto_start(m, true);
598 r = sd_bus_call(bus, m, 0, NULL, &reply);
602 r = sd_bus_message_read(reply, "s", &mid);
606 return sd_id128_from_string(mid, machine);