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 if (bus->is_kernel) {
184 _cleanup_free_ struct kdbus_cmd_names *names = NULL;
185 struct kdbus_cmd_name *name;
188 /* assume 8k size first. If that doesn't suffice, kdbus will tell us
189 * how big the buffer needs to be. */
193 names = realloc(names, size);
199 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
201 if (errno == ENOBUFS && size != names->size) {
212 KDBUS_PART_FOREACH(name, names, names) {
213 r = strv_extend(&x, name->name);
220 r = sd_bus_call_method(
222 "org.freedesktop.DBus",
224 "org.freedesktop.DBus",
232 r = sd_bus_call_method(
234 "org.freedesktop.DBus",
236 "org.freedesktop.DBus",
237 "ListActivatableNames",
244 r = bus_message_read_strv_extend(reply1, &x);
250 r = bus_message_read_strv_extend(reply2, &x);
262 _public_ int sd_bus_get_owner(
267 sd_bus_creds **creds) {
269 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
270 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
271 _cleanup_free_ char *unique = NULL;
275 assert_return(bus, -EINVAL);
276 assert_return(name, -EINVAL);
277 assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
278 assert_return(mask == 0 || creds, -EINVAL);
279 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
280 assert_return(!bus_pid_changed(bus), -ECHILD);
282 /* Only query the owner if the caller wants to know it or if
283 * the caller just wants to check whether a name exists */
284 if (owner || mask == 0) {
287 r = sd_bus_call_method(
289 "org.freedesktop.DBus",
291 "org.freedesktop.DBus",
300 r = sd_bus_message_read(reply, "s", &found);
304 unique = strdup(found);
308 reply = sd_bus_message_unref(reply);
316 if ((mask & SD_BUS_CREDS_PID) ||
317 mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
320 r = sd_bus_call_method(
322 "org.freedesktop.DBus",
324 "org.freedesktop.DBus",
325 "GetConnectionUnixProcessID",
333 r = sd_bus_message_read(reply, "u", &u);
338 if (mask & SD_BUS_CREDS_PID) {
340 c->mask |= SD_BUS_CREDS_PID;
343 reply = sd_bus_message_unref(reply);
346 if (mask & SD_BUS_CREDS_UID) {
349 r = sd_bus_call_method(
351 "org.freedesktop.DBus",
353 "org.freedesktop.DBus",
354 "GetConnectionUnixUser",
362 r = sd_bus_message_read(reply, "u", &u);
367 c->mask |= SD_BUS_CREDS_UID;
369 reply = sd_bus_message_unref(reply);
372 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
376 r = sd_bus_call_method(
378 "org.freedesktop.DBus",
380 "org.freedesktop.DBus",
381 "GetConnectionSELinuxSecurityContext",
389 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
393 c->label = strndup(p, sz);
397 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
400 r = bus_creds_add_more(c, mask, pid, 0);
418 int bus_add_match_internal(
421 struct bus_match_component *components,
422 unsigned n_components,
430 if (bus->is_kernel) {
431 struct kdbus_cmd_match *m;
432 struct kdbus_item *item;
433 uint64_t bloom[BLOOM_SIZE/8];
435 const char *sender = NULL;
436 size_t sender_length = 0;
437 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
438 bool using_bloom = false;
443 sz = offsetof(struct kdbus_cmd_match, items);
445 for (i = 0; i < n_components; i++) {
446 struct bus_match_component *c = &components[i];
450 case BUS_MATCH_SENDER:
451 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
456 sender = c->value_str;
457 sender_length = strlen(sender);
458 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
463 case BUS_MATCH_MESSAGE_TYPE:
464 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
468 case BUS_MATCH_INTERFACE:
469 bloom_add_pair(bloom, "interface", c->value_str);
473 case BUS_MATCH_MEMBER:
474 bloom_add_pair(bloom, "member", c->value_str);
479 bloom_add_pair(bloom, "path", c->value_str);
483 case BUS_MATCH_PATH_NAMESPACE:
484 if (!streq(c->value_str, "/")) {
485 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
490 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
491 char buf[sizeof("arg")-1 + 2 + 1];
493 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
494 bloom_add_pair(bloom, buf, c->value_str);
499 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
500 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
502 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
503 bloom_add_pair(bloom, buf, c->value_str);
508 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
509 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
511 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
512 bloom_add_pair(bloom, buf, c->value_str);
517 case BUS_MATCH_DESTINATION:
518 /* The bloom filter does not include
519 the destination, since it is only
520 available for broadcast messages
521 which do not carry a destination
522 since they are undirected. */
526 case BUS_MATCH_VALUE:
528 case _BUS_MATCH_NODE_TYPE_MAX:
529 case _BUS_MATCH_NODE_TYPE_INVALID:
530 assert_not_reached("Invalid match type?");
535 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
545 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
546 item->type = KDBUS_MATCH_BLOOM;
547 memcpy(item->data64, bloom, BLOOM_SIZE);
549 item = KDBUS_PART_NEXT(item);
553 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
554 item->type = KDBUS_MATCH_SRC_NAME;
555 memcpy(item->str, sender, sender_length + 1);
558 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
563 return sd_bus_call_method(
565 "org.freedesktop.DBus",
567 "org.freedesktop.DBus",
578 int bus_remove_match_internal(
588 if (bus->is_kernel) {
589 struct kdbus_cmd_match m;
592 m.size = offsetof(struct kdbus_cmd_match, items);
595 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
600 return sd_bus_call_method(
602 "org.freedesktop.DBus",
604 "org.freedesktop.DBus",
615 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
616 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
620 assert_return(bus, -EINVAL);
621 assert_return(name, -EINVAL);
622 assert_return(machine, -EINVAL);
623 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
624 assert_return(!bus_pid_changed(bus), -ECHILD);
626 if (streq_ptr(name, bus->unique_name))
627 return sd_id128_get_machine(machine);
629 r = sd_bus_message_new_method_call(
633 "org.freedesktop.DBus.Peer",
638 r = sd_bus_message_set_no_auto_start(m, true);
642 r = sd_bus_call(bus, m, 0, NULL, &reply);
646 r = sd_bus_message_read(reply, "s", &mid);
650 return sd_id128_from_string(mid, machine);