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);
88 if (errno == -EALREADY)
89 return SD_BUS_NAME_ALREADY_OWNER;
92 return SD_BUS_NAME_EXISTS;
97 if (n->flags & KDBUS_NAME_IN_QUEUE)
98 return SD_BUS_NAME_IN_QUEUE;
100 return SD_BUS_NAME_PRIMARY_OWNER;
102 r = sd_bus_call_method(
104 "org.freedesktop.DBus",
106 "org.freedesktop.DBus",
116 r = sd_bus_message_read(reply, "u", &ret);
124 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
125 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
133 if (!bus->bus_client)
135 if (!BUS_IS_OPEN(bus->state))
137 if (bus_pid_changed(bus))
140 if (bus->is_kernel) {
141 struct kdbus_cmd_name *n;
145 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
146 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
147 memcpy(n->name, name, l+1);
149 #ifdef HAVE_VALGRIND_MEMCHECK_H
150 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
152 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
158 r = sd_bus_call_method(
160 "org.freedesktop.DBus",
162 "org.freedesktop.DBus",
171 r = sd_bus_message_read(reply, "u", &ret);
179 _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
180 _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
188 if (!BUS_IS_OPEN(bus->state))
190 if (bus_pid_changed(bus))
193 if (bus->is_kernel) {
194 _cleanup_free_ struct kdbus_cmd_names *names = NULL;
195 struct kdbus_cmd_name *name;
198 /* assume 8k size first. If that doesn't suffice, kdbus will tell us
199 * how big the buffer needs to be. */
203 names = realloc(names, size);
208 names->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
210 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
212 if (errno == ENOBUFS && size != names->size) {
223 KDBUS_PART_FOREACH(name, names, names) {
226 if (name->size > sizeof(*name))
229 asprintf(&n, ":1.%llu", (unsigned long long) name->id);
231 r = strv_extend(&x, n);
238 r = sd_bus_call_method(
240 "org.freedesktop.DBus",
242 "org.freedesktop.DBus",
250 r = sd_bus_call_method(
252 "org.freedesktop.DBus",
254 "org.freedesktop.DBus",
255 "ListActivatableNames",
262 r = bus_message_read_strv_extend(reply1, &x);
268 r = bus_message_read_strv_extend(reply2, &x);
280 _public_ int sd_bus_get_owner(
285 sd_bus_creds **creds) {
287 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
288 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
289 _cleanup_free_ char *unique = NULL;
293 assert_return(bus, -EINVAL);
294 assert_return(name, -EINVAL);
295 assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
296 assert_return(mask == 0 || creds, -EINVAL);
297 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
298 assert_return(!bus_pid_changed(bus), -ECHILD);
300 /* Only query the owner if the caller wants to know it or if
301 * the caller just wants to check whether a name exists */
302 if (owner || mask == 0) {
305 r = sd_bus_call_method(
307 "org.freedesktop.DBus",
309 "org.freedesktop.DBus",
318 r = sd_bus_message_read(reply, "s", &found);
322 unique = strdup(found);
326 reply = sd_bus_message_unref(reply);
334 if ((mask & SD_BUS_CREDS_PID) ||
335 mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
338 r = sd_bus_call_method(
340 "org.freedesktop.DBus",
342 "org.freedesktop.DBus",
343 "GetConnectionUnixProcessID",
351 r = sd_bus_message_read(reply, "u", &u);
356 if (mask & SD_BUS_CREDS_PID) {
358 c->mask |= SD_BUS_CREDS_PID;
361 reply = sd_bus_message_unref(reply);
364 if (mask & SD_BUS_CREDS_UID) {
367 r = sd_bus_call_method(
369 "org.freedesktop.DBus",
371 "org.freedesktop.DBus",
372 "GetConnectionUnixUser",
380 r = sd_bus_message_read(reply, "u", &u);
385 c->mask |= SD_BUS_CREDS_UID;
387 reply = sd_bus_message_unref(reply);
390 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
394 r = sd_bus_call_method(
396 "org.freedesktop.DBus",
398 "org.freedesktop.DBus",
399 "GetConnectionSELinuxSecurityContext",
407 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
411 c->label = strndup(p, sz);
415 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
418 r = bus_creds_add_more(c, mask, pid, 0);
436 int bus_add_match_internal(
439 struct bus_match_component *components,
440 unsigned n_components,
448 if (bus->is_kernel) {
449 struct kdbus_cmd_match *m;
450 struct kdbus_item *item;
451 uint64_t bloom[BLOOM_SIZE/8];
453 const char *sender = NULL;
454 size_t sender_length = 0;
455 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
456 bool using_bloom = false;
461 sz = offsetof(struct kdbus_cmd_match, items);
463 for (i = 0; i < n_components; i++) {
464 struct bus_match_component *c = &components[i];
468 case BUS_MATCH_SENDER:
469 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
474 sender = c->value_str;
475 sender_length = strlen(sender);
476 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
481 case BUS_MATCH_MESSAGE_TYPE:
482 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
486 case BUS_MATCH_INTERFACE:
487 bloom_add_pair(bloom, "interface", c->value_str);
491 case BUS_MATCH_MEMBER:
492 bloom_add_pair(bloom, "member", c->value_str);
497 bloom_add_pair(bloom, "path", c->value_str);
501 case BUS_MATCH_PATH_NAMESPACE:
502 if (!streq(c->value_str, "/")) {
503 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
508 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
509 char buf[sizeof("arg")-1 + 2 + 1];
511 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
512 bloom_add_pair(bloom, buf, c->value_str);
517 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
518 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
520 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
521 bloom_add_pair(bloom, buf, c->value_str);
526 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
527 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
529 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
530 bloom_add_pair(bloom, buf, c->value_str);
535 case BUS_MATCH_DESTINATION:
536 /* The bloom filter does not include
537 the destination, since it is only
538 available for broadcast messages
539 which do not carry a destination
540 since they are undirected. */
544 case BUS_MATCH_VALUE:
546 case _BUS_MATCH_NODE_TYPE_MAX:
547 case _BUS_MATCH_NODE_TYPE_INVALID:
548 assert_not_reached("Invalid match type?");
553 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
563 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
564 item->type = KDBUS_MATCH_BLOOM;
565 memcpy(item->data64, bloom, BLOOM_SIZE);
567 item = KDBUS_PART_NEXT(item);
571 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
572 item->type = KDBUS_MATCH_SRC_NAME;
573 memcpy(item->str, sender, sender_length + 1);
576 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
581 return sd_bus_call_method(
583 "org.freedesktop.DBus",
585 "org.freedesktop.DBus",
596 int bus_remove_match_internal(
606 if (bus->is_kernel) {
607 struct kdbus_cmd_match m;
610 m.size = offsetof(struct kdbus_cmd_match, items);
613 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
618 return sd_bus_call_method(
620 "org.freedesktop.DBus",
622 "org.freedesktop.DBus",
633 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
634 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
638 assert_return(bus, -EINVAL);
639 assert_return(name, -EINVAL);
640 assert_return(machine, -EINVAL);
641 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
642 assert_return(!bus_pid_changed(bus), -ECHILD);
644 if (streq_ptr(name, bus->unique_name))
645 return sd_id128_get_machine(machine);
647 r = sd_bus_message_new_method_call(
651 "org.freedesktop.DBus.Peer",
656 r = sd_bus_message_set_no_auto_start(m, true);
660 r = sd_bus_call(bus, m, 0, NULL, &reply);
664 r = sd_bus_message_read(reply, "s", &mid);
668 return sd_id128_from_string(mid, machine);