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(
228 sd_bus_creds **creds) {
230 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
231 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
232 _cleanup_free_ char *unique = NULL;
236 assert_return(bus, -EINVAL);
237 assert_return(name, -EINVAL);
238 assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
239 assert_return(mask == 0 || creds, -EINVAL);
240 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
241 assert_return(!bus_pid_changed(bus), -ECHILD);
243 /* Only query the owner if the caller wants to know it or if
244 * the caller just wants to check whether a name exists */
245 if (owner || mask == 0) {
248 r = sd_bus_call_method(
250 "org.freedesktop.DBus",
252 "org.freedesktop.DBus",
261 r = sd_bus_message_read(reply, "s", &found);
265 unique = strdup(found);
269 reply = sd_bus_message_unref(reply);
277 if ((mask & SD_BUS_CREDS_PID) ||
278 mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
281 r = sd_bus_call_method(
283 "org.freedesktop.DBus",
285 "org.freedesktop.DBus",
286 "GetConnectionUnixProcessID",
294 r = sd_bus_message_read(reply, "u", &u);
299 if (mask & SD_BUS_CREDS_PID) {
301 c->mask |= SD_BUS_CREDS_PID;
304 reply = sd_bus_message_unref(reply);
307 if (mask & SD_BUS_CREDS_UID) {
310 r = sd_bus_call_method(
312 "org.freedesktop.DBus",
314 "org.freedesktop.DBus",
315 "GetConnectionUnixUser",
323 r = sd_bus_message_read(reply, "u", &u);
328 c->mask |= SD_BUS_CREDS_UID;
330 reply = sd_bus_message_unref(reply);
333 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
337 r = sd_bus_call_method(
339 "org.freedesktop.DBus",
341 "org.freedesktop.DBus",
342 "GetConnectionSELinuxSecurityContext",
350 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
354 c->label = strndup(p, sz);
358 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
361 r = bus_creds_add_more(c, mask, pid, 0);
379 int bus_add_match_internal(
382 struct bus_match_component *components,
383 unsigned n_components,
391 if (bus->is_kernel) {
392 struct kdbus_cmd_match *m;
393 struct kdbus_item *item;
394 uint64_t bloom[BLOOM_SIZE/8];
396 const char *sender = NULL;
397 size_t sender_length = 0;
398 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
399 bool using_bloom = false;
404 sz = offsetof(struct kdbus_cmd_match, items);
406 for (i = 0; i < n_components; i++) {
407 struct bus_match_component *c = &components[i];
411 case BUS_MATCH_SENDER:
412 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
417 sender = c->value_str;
418 sender_length = strlen(sender);
419 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
424 case BUS_MATCH_MESSAGE_TYPE:
425 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
429 case BUS_MATCH_INTERFACE:
430 bloom_add_pair(bloom, "interface", c->value_str);
434 case BUS_MATCH_MEMBER:
435 bloom_add_pair(bloom, "member", c->value_str);
440 bloom_add_pair(bloom, "path", c->value_str);
444 case BUS_MATCH_PATH_NAMESPACE:
445 if (!streq(c->value_str, "/")) {
446 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
451 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
452 char buf[sizeof("arg")-1 + 2 + 1];
454 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
455 bloom_add_pair(bloom, buf, c->value_str);
460 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
461 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
463 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
464 bloom_add_pair(bloom, buf, c->value_str);
469 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
470 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
472 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
473 bloom_add_pair(bloom, buf, c->value_str);
478 case BUS_MATCH_DESTINATION:
479 /* The bloom filter does not include
480 the destination, since it is only
481 available for broadcast messages
482 which do not carry a destination
483 since they are undirected. */
487 case BUS_MATCH_VALUE:
489 case _BUS_MATCH_NODE_TYPE_MAX:
490 case _BUS_MATCH_NODE_TYPE_INVALID:
491 assert_not_reached("Invalid match type?");
496 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
506 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
507 item->type = KDBUS_MATCH_BLOOM;
508 memcpy(item->data64, bloom, BLOOM_SIZE);
510 item = KDBUS_ITEM_NEXT(item);
514 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
515 item->type = KDBUS_MATCH_SRC_NAME;
516 memcpy(item->str, sender, sender_length + 1);
519 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
524 return sd_bus_call_method(
526 "org.freedesktop.DBus",
528 "org.freedesktop.DBus",
539 int bus_remove_match_internal(
549 if (bus->is_kernel) {
550 struct kdbus_cmd_match m;
553 m.size = offsetof(struct kdbus_cmd_match, items);
556 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
561 return sd_bus_call_method(
563 "org.freedesktop.DBus",
565 "org.freedesktop.DBus",
576 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
577 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
581 assert_return(bus, -EINVAL);
582 assert_return(name, -EINVAL);
583 assert_return(machine, -EINVAL);
584 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
585 assert_return(!bus_pid_changed(bus), -ECHILD);
587 if (streq_ptr(name, bus->unique_name))
588 return sd_id128_get_machine(machine);
590 r = sd_bus_message_new_method_call(
594 "org.freedesktop.DBus.Peer",
599 r = sd_bus_message_set_no_auto_start(m, true);
603 r = sd_bus_call(bus, m, 0, NULL, &reply);
607 r = sd_bus_message_read(reply, "s", &mid);
611 return sd_id128_from_string(mid, machine);