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) {
41 assert_return(bus, -EINVAL);
42 assert_return(unique, -EINVAL);
43 assert_return(!bus_pid_changed(bus), -ECHILD);
45 r = bus_ensure_running(bus);
49 *unique = bus->unique_name;
53 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
54 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
58 assert_return(bus, -EINVAL);
59 assert_return(name, -EINVAL);
60 assert_return(bus->bus_client, -EINVAL);
61 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
62 assert_return(!bus_pid_changed(bus), -ECHILD);
65 struct kdbus_cmd_name *n;
69 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
70 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
72 memcpy(n->name, name, l+1);
74 #ifdef HAVE_VALGRIND_MEMCHECK_H
75 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
78 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
80 if (errno == -EALREADY)
81 return SD_BUS_NAME_ALREADY_OWNER;
84 return SD_BUS_NAME_EXISTS;
89 if (n->flags & KDBUS_NAME_IN_QUEUE)
90 return SD_BUS_NAME_IN_QUEUE;
92 return SD_BUS_NAME_PRIMARY_OWNER;
94 r = sd_bus_call_method(
96 "org.freedesktop.DBus",
98 "org.freedesktop.DBus",
108 r = sd_bus_message_read(reply, "u", &ret);
116 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
117 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
121 assert_return(bus, -EINVAL);
122 assert_return(name, -EINVAL);
123 assert_return(bus->bus_client, -EINVAL);
124 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
125 assert_return(!bus_pid_changed(bus), -ECHILD);
127 if (bus->is_kernel) {
128 struct kdbus_cmd_name *n;
132 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
133 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
134 memcpy(n->name, name, l+1);
136 #ifdef HAVE_VALGRIND_MEMCHECK_H
137 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
139 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
145 r = sd_bus_call_method(
147 "org.freedesktop.DBus",
149 "org.freedesktop.DBus",
158 r = sd_bus_message_read(reply, "u", &ret);
166 _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
167 _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
171 assert_return(bus, -EINVAL);
172 assert_return(l, -EINVAL);
173 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
174 assert_return(!bus_pid_changed(bus), -ECHILD);
176 if (bus->is_kernel) {
177 _cleanup_free_ struct kdbus_cmd_names *names = NULL;
178 struct kdbus_cmd_name *name;
181 /* assume 8k size first. If that doesn't suffice, kdbus will tell us
182 * how big the buffer needs to be. */
186 names = realloc(names, size);
191 names->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
193 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
195 if (errno == ENOBUFS && size != names->size) {
206 KDBUS_PART_FOREACH(name, names, names) {
209 if (name->size > sizeof(*name))
212 asprintf(&n, ":1.%llu", (unsigned long long) name->id);
214 r = strv_extend(&x, n);
221 r = sd_bus_call_method(
223 "org.freedesktop.DBus",
225 "org.freedesktop.DBus",
233 r = sd_bus_call_method(
235 "org.freedesktop.DBus",
237 "org.freedesktop.DBus",
238 "ListActivatableNames",
245 r = bus_message_read_strv_extend(reply1, &x);
251 r = bus_message_read_strv_extend(reply2, &x);
263 _public_ int sd_bus_get_owner(
268 sd_bus_creds **creds) {
270 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
271 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
272 _cleanup_free_ char *unique = NULL;
276 assert_return(bus, -EINVAL);
277 assert_return(name, -EINVAL);
278 assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP);
279 assert_return(mask == 0 || creds, -EINVAL);
280 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
281 assert_return(!bus_pid_changed(bus), -ECHILD);
283 /* Only query the owner if the caller wants to know it or if
284 * the caller just wants to check whether a name exists */
285 if (owner || mask == 0) {
288 r = sd_bus_call_method(
290 "org.freedesktop.DBus",
292 "org.freedesktop.DBus",
301 r = sd_bus_message_read(reply, "s", &found);
305 unique = strdup(found);
309 reply = sd_bus_message_unref(reply);
317 if ((mask & SD_BUS_CREDS_PID) ||
318 mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) {
321 r = sd_bus_call_method(
323 "org.freedesktop.DBus",
325 "org.freedesktop.DBus",
326 "GetConnectionUnixProcessID",
334 r = sd_bus_message_read(reply, "u", &u);
339 if (mask & SD_BUS_CREDS_PID) {
341 c->mask |= SD_BUS_CREDS_PID;
344 reply = sd_bus_message_unref(reply);
347 if (mask & SD_BUS_CREDS_UID) {
350 r = sd_bus_call_method(
352 "org.freedesktop.DBus",
354 "org.freedesktop.DBus",
355 "GetConnectionUnixUser",
363 r = sd_bus_message_read(reply, "u", &u);
368 c->mask |= SD_BUS_CREDS_UID;
370 reply = sd_bus_message_unref(reply);
373 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
377 r = sd_bus_call_method(
379 "org.freedesktop.DBus",
381 "org.freedesktop.DBus",
382 "GetConnectionSELinuxSecurityContext",
390 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
394 c->label = strndup(p, sz);
398 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
401 r = bus_creds_add_more(c, mask, pid, 0);
419 int bus_add_match_internal(
422 struct bus_match_component *components,
423 unsigned n_components,
431 if (bus->is_kernel) {
432 struct kdbus_cmd_match *m;
433 struct kdbus_item *item;
434 uint64_t bloom[BLOOM_SIZE/8];
436 const char *sender = NULL;
437 size_t sender_length = 0;
438 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
439 bool using_bloom = false;
444 sz = offsetof(struct kdbus_cmd_match, items);
446 for (i = 0; i < n_components; i++) {
447 struct bus_match_component *c = &components[i];
451 case BUS_MATCH_SENDER:
452 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
457 sender = c->value_str;
458 sender_length = strlen(sender);
459 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
464 case BUS_MATCH_MESSAGE_TYPE:
465 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
469 case BUS_MATCH_INTERFACE:
470 bloom_add_pair(bloom, "interface", c->value_str);
474 case BUS_MATCH_MEMBER:
475 bloom_add_pair(bloom, "member", c->value_str);
480 bloom_add_pair(bloom, "path", c->value_str);
484 case BUS_MATCH_PATH_NAMESPACE:
485 if (!streq(c->value_str, "/")) {
486 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
491 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
492 char buf[sizeof("arg")-1 + 2 + 1];
494 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
495 bloom_add_pair(bloom, buf, c->value_str);
500 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
501 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
503 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
504 bloom_add_pair(bloom, buf, c->value_str);
509 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
510 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
512 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
513 bloom_add_pair(bloom, buf, c->value_str);
518 case BUS_MATCH_DESTINATION:
519 /* The bloom filter does not include
520 the destination, since it is only
521 available for broadcast messages
522 which do not carry a destination
523 since they are undirected. */
527 case BUS_MATCH_VALUE:
529 case _BUS_MATCH_NODE_TYPE_MAX:
530 case _BUS_MATCH_NODE_TYPE_INVALID:
531 assert_not_reached("Invalid match type?");
536 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
546 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
547 item->type = KDBUS_MATCH_BLOOM;
548 memcpy(item->data64, bloom, BLOOM_SIZE);
550 item = KDBUS_PART_NEXT(item);
554 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
555 item->type = KDBUS_MATCH_SRC_NAME;
556 memcpy(item->str, sender, sender_length + 1);
559 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
564 return sd_bus_call_method(
566 "org.freedesktop.DBus",
568 "org.freedesktop.DBus",
579 int bus_remove_match_internal(
589 if (bus->is_kernel) {
590 struct kdbus_cmd_match m;
593 m.size = offsetof(struct kdbus_cmd_match, items);
596 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
601 return sd_bus_call_method(
603 "org.freedesktop.DBus",
605 "org.freedesktop.DBus",
616 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
617 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
621 assert_return(bus, -EINVAL);
622 assert_return(name, -EINVAL);
623 assert_return(machine, -EINVAL);
624 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
625 assert_return(!bus_pid_changed(bus), -ECHILD);
627 if (streq_ptr(name, bus->unique_name))
628 return sd_id128_get_machine(machine);
630 r = sd_bus_message_new_method_call(
634 "org.freedesktop.DBus.Peer",
639 r = sd_bus_message_set_no_auto_start(m, true);
643 r = sd_bus_call(bus, m, 0, NULL, &reply);
647 r = sd_bus_message_read(reply, "s", &mid);
651 return sd_id128_from_string(mid, machine);