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_uid(sd_bus *bus, const char *name, uid_t *uid) {
264 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
274 if (!BUS_IS_OPEN(bus->state))
276 if (bus_pid_changed(bus))
279 r = sd_bus_call_method(
281 "org.freedesktop.DBus",
283 "org.freedesktop.DBus",
284 "GetConnectionUnixUser",
292 r = sd_bus_message_read(reply, "u", &u);
300 _public_ int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
301 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
311 if (!BUS_IS_OPEN(bus->state))
313 if (bus_pid_changed(bus))
316 r = sd_bus_call_method(
318 "org.freedesktop.DBus",
320 "org.freedesktop.DBus",
321 "GetConnectionUnixProcessID",
329 r = sd_bus_message_read(reply, "u", &u);
340 int bus_add_match_internal(
343 struct bus_match_component *components,
344 unsigned n_components,
352 if (bus->is_kernel) {
353 struct kdbus_cmd_match *m;
354 struct kdbus_item *item;
355 uint64_t bloom[BLOOM_SIZE/8];
357 const char *sender = NULL;
358 size_t sender_length = 0;
359 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
360 bool using_bloom = false;
365 sz = offsetof(struct kdbus_cmd_match, items);
367 for (i = 0; i < n_components; i++) {
368 struct bus_match_component *c = &components[i];
372 case BUS_MATCH_SENDER:
373 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
378 sender = c->value_str;
379 sender_length = strlen(sender);
380 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
385 case BUS_MATCH_MESSAGE_TYPE:
386 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
390 case BUS_MATCH_INTERFACE:
391 bloom_add_pair(bloom, "interface", c->value_str);
395 case BUS_MATCH_MEMBER:
396 bloom_add_pair(bloom, "member", c->value_str);
401 bloom_add_pair(bloom, "path", c->value_str);
405 case BUS_MATCH_PATH_NAMESPACE:
406 if (!streq(c->value_str, "/")) {
407 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
412 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
413 char buf[sizeof("arg")-1 + 2 + 1];
415 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
416 bloom_add_pair(bloom, buf, c->value_str);
421 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
422 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
424 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
425 bloom_add_pair(bloom, buf, c->value_str);
430 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
431 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
433 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
434 bloom_add_pair(bloom, buf, c->value_str);
439 case BUS_MATCH_DESTINATION:
440 /* The bloom filter does not include
441 the destination, since it is only
442 available for broadcast messages
443 which do not carry a destination
444 since they are undirected. */
448 case BUS_MATCH_VALUE:
450 case _BUS_MATCH_NODE_TYPE_MAX:
451 case _BUS_MATCH_NODE_TYPE_INVALID:
452 assert_not_reached("Invalid match type?");
457 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
467 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
468 item->type = KDBUS_MATCH_BLOOM;
469 memcpy(item->data64, bloom, BLOOM_SIZE);
471 item = KDBUS_ITEM_NEXT(item);
475 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
476 item->type = KDBUS_MATCH_SRC_NAME;
477 memcpy(item->str, sender, sender_length + 1);
480 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
485 return sd_bus_call_method(
487 "org.freedesktop.DBus",
489 "org.freedesktop.DBus",
500 int bus_remove_match_internal(
510 if (bus->is_kernel) {
511 struct kdbus_cmd_match m;
514 m.size = offsetof(struct kdbus_cmd_match, items);
517 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
522 return sd_bus_call_method(
524 "org.freedesktop.DBus",
526 "org.freedesktop.DBus",
537 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
538 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
542 assert_return(bus, -EINVAL);
543 assert_return(name, -EINVAL);
544 assert_return(machine, -EINVAL);
545 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
546 assert_return(!bus_pid_changed(bus), -ECHILD);
548 if (streq_ptr(name, bus->unique_name))
549 return sd_id128_get_machine(machine);
551 r = sd_bus_message_new_method_call(
555 "org.freedesktop.DBus.Peer",
560 r = sd_bus_message_set_no_auto_start(m, true);
564 r = sd_bus_call(bus, m, 0, NULL, &reply);
568 r = sd_bus_message_read(reply, "s", &mid);
572 return sd_id128_from_string(mid, machine);