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);
198 names->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
200 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
202 if (errno == ENOBUFS && size != names->size) {
213 KDBUS_PART_FOREACH(name, names, names) {
216 if (name->size > sizeof(*name))
219 asprintf(&n, ":1.%llu", (unsigned long long) name->id);
221 r = strv_extend(&x, n);
228 r = sd_bus_call_method(
230 "org.freedesktop.DBus",
232 "org.freedesktop.DBus",
240 r = sd_bus_call_method(
242 "org.freedesktop.DBus",
244 "org.freedesktop.DBus",
245 "ListActivatableNames",
252 r = bus_message_read_strv_extend(reply1, &x);
258 r = bus_message_read_strv_extend(reply2, &x);
270 _public_ int sd_bus_get_owner(
275 sd_bus_creds **creds) {
277 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
278 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
279 _cleanup_free_ char *unique = NULL;
283 assert_return(bus, -EINVAL);
284 assert_return(name, -EINVAL);
285 assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
286 assert_return(mask == 0 || creds, -EINVAL);
287 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
288 assert_return(!bus_pid_changed(bus), -ECHILD);
290 /* Only query the owner if the caller wants to know it or if
291 * the caller just wants to check whether a name exists */
292 if (owner || mask == 0) {
295 r = sd_bus_call_method(
297 "org.freedesktop.DBus",
299 "org.freedesktop.DBus",
308 r = sd_bus_message_read(reply, "s", &found);
312 unique = strdup(found);
316 reply = sd_bus_message_unref(reply);
324 if ((mask & SD_BUS_CREDS_PID) ||
325 mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
328 r = sd_bus_call_method(
330 "org.freedesktop.DBus",
332 "org.freedesktop.DBus",
333 "GetConnectionUnixProcessID",
341 r = sd_bus_message_read(reply, "u", &u);
346 if (mask & SD_BUS_CREDS_PID) {
348 c->mask |= SD_BUS_CREDS_PID;
351 reply = sd_bus_message_unref(reply);
354 if (mask & SD_BUS_CREDS_UID) {
357 r = sd_bus_call_method(
359 "org.freedesktop.DBus",
361 "org.freedesktop.DBus",
362 "GetConnectionUnixUser",
370 r = sd_bus_message_read(reply, "u", &u);
375 c->mask |= SD_BUS_CREDS_UID;
377 reply = sd_bus_message_unref(reply);
380 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
384 r = sd_bus_call_method(
386 "org.freedesktop.DBus",
388 "org.freedesktop.DBus",
389 "GetConnectionSELinuxSecurityContext",
397 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
401 c->label = strndup(p, sz);
405 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
408 r = bus_creds_add_more(c, mask, pid, 0);
426 int bus_add_match_internal(
429 struct bus_match_component *components,
430 unsigned n_components,
438 if (bus->is_kernel) {
439 struct kdbus_cmd_match *m;
440 struct kdbus_item *item;
441 uint64_t bloom[BLOOM_SIZE/8];
443 const char *sender = NULL;
444 size_t sender_length = 0;
445 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
446 bool using_bloom = false;
451 sz = offsetof(struct kdbus_cmd_match, items);
453 for (i = 0; i < n_components; i++) {
454 struct bus_match_component *c = &components[i];
458 case BUS_MATCH_SENDER:
459 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
464 sender = c->value_str;
465 sender_length = strlen(sender);
466 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
471 case BUS_MATCH_MESSAGE_TYPE:
472 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
476 case BUS_MATCH_INTERFACE:
477 bloom_add_pair(bloom, "interface", c->value_str);
481 case BUS_MATCH_MEMBER:
482 bloom_add_pair(bloom, "member", c->value_str);
487 bloom_add_pair(bloom, "path", c->value_str);
491 case BUS_MATCH_PATH_NAMESPACE:
492 if (!streq(c->value_str, "/")) {
493 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
498 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
499 char buf[sizeof("arg")-1 + 2 + 1];
501 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
502 bloom_add_pair(bloom, buf, c->value_str);
507 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
508 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
510 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
511 bloom_add_pair(bloom, buf, c->value_str);
516 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
517 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
519 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
520 bloom_add_pair(bloom, buf, c->value_str);
525 case BUS_MATCH_DESTINATION:
526 /* The bloom filter does not include
527 the destination, since it is only
528 available for broadcast messages
529 which do not carry a destination
530 since they are undirected. */
534 case BUS_MATCH_VALUE:
536 case _BUS_MATCH_NODE_TYPE_MAX:
537 case _BUS_MATCH_NODE_TYPE_INVALID:
538 assert_not_reached("Invalid match type?");
543 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
553 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
554 item->type = KDBUS_MATCH_BLOOM;
555 memcpy(item->data64, bloom, BLOOM_SIZE);
557 item = KDBUS_PART_NEXT(item);
561 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
562 item->type = KDBUS_MATCH_SRC_NAME;
563 memcpy(item->str, sender, sender_length + 1);
566 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
571 return sd_bus_call_method(
573 "org.freedesktop.DBus",
575 "org.freedesktop.DBus",
586 int bus_remove_match_internal(
596 if (bus->is_kernel) {
597 struct kdbus_cmd_match m;
600 m.size = offsetof(struct kdbus_cmd_match, items);
603 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
608 return sd_bus_call_method(
610 "org.freedesktop.DBus",
612 "org.freedesktop.DBus",
623 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
624 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
628 assert_return(bus, -EINVAL);
629 assert_return(name, -EINVAL);
630 assert_return(machine, -EINVAL);
631 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
632 assert_return(!bus_pid_changed(bus), -ECHILD);
634 if (streq_ptr(name, bus->unique_name))
635 return sd_id128_get_machine(machine);
637 r = sd_bus_message_new_method_call(
641 "org.freedesktop.DBus.Peer",
646 r = sd_bus_message_set_no_auto_start(m, true);
650 r = sd_bus_call(bus, m, 0, NULL, &reply);
654 r = sd_bus_message_read(reply, "s", &mid);
658 return sd_id128_from_string(mid, machine);