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 static int add_name_change_match(sd_bus *bus,
422 const char *old_owner,
423 const char *new_owner) {
425 uint64_t name_id = 0, old_owner_id = 0, new_owner_id = 0;
426 int is_name_id = -1, r;
427 struct kdbus_item *item;
431 /* If we encounter a match that could match against
432 * NameOwnerChanged messages, then we need to create
433 * KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE} and
434 * KDBUS_MATCH_ID_{ADD,REMOVE} matches for it, possibly
435 * multiple if the match is underspecified.
437 * The NameOwnerChanged signals take three parameters with
438 * unique or well-known names, but only some forms actually
441 * WELLKNOWN, "", UNIQUE → KDBUS_MATCH_NAME_ADD
442 * WELLKNOWN, UNIQUE, "" → KDBUS_MATCH_NAME_REMOVE
443 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_MATCH_NAME_CHANGE
444 * UNIQUE, "", UNIQUE → KDBUS_MATCH_ID_ADD
445 * UNIQUE, UNIQUE, "" → KDBUS_MATCH_ID_REMOVE
447 * For the latter two the two unique names must be identical.
452 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
458 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
463 if (is_name_id > 0 && old_owner_id != name_id)
468 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
473 if (is_name_id > 0 && new_owner_id != name_id)
477 if (is_name_id <= 0) {
480 /* If the name argument is missing or is a well-known
481 * name, then add KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE}
484 l = name ? strlen(name) : 0;
486 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
487 offsetof(struct kdbus_item, name_change) +
488 offsetof(struct kdbus_notify_name_change, name) +
494 struct kdbus_cmd_match match;
500 m.match.cookie = cookie;
501 m.match.src_id = KDBUS_SRC_ID_KERNEL;
503 item = m.match.items;
505 offsetof(struct kdbus_item, name_change) +
506 offsetof(struct kdbus_notify_name_change, name) +
509 item->name_change.old_id = old_owner_id;
510 item->name_change.new_id = new_owner_id;
513 strcpy(item->name_change.name, name);
515 /* If the old name is unset or empty, then
516 * this can match against added names */
517 if (!old_owner || old_owner[0] == 0) {
518 item->type = KDBUS_MATCH_NAME_ADD;
520 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
525 /* If the new name is unset or empty, then
526 * this can match against removed names */
527 if (!new_owner || new_owner[0] == 0) {
528 item->type = KDBUS_MATCH_NAME_REMOVE;
530 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
535 /* If the neither name is explicitly set to
536 * the empty string, then this can match
537 * agains changed names */
538 if (!(old_owner && old_owner[0] == 0) &&
539 !(new_owner && new_owner[0] == 0)) {
540 item->type = KDBUS_MATCH_NAME_CHANGE;
542 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
549 if (is_name_id != 0) {
551 ALIGN8(offsetof(struct kdbus_cmd_match, items) +
552 offsetof(struct kdbus_item, id_change) +
553 sizeof(struct kdbus_notify_id_change));
556 struct kdbus_cmd_match match;
559 /* If the name argument is missing or is a unique
560 * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
566 m.match.cookie = cookie;
567 m.match.src_id = KDBUS_SRC_ID_KERNEL;
569 item = m.match.items;
570 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
571 item->id_change.id = name_id;
573 /* If the old name is unset or empty, then this can
574 * match against added ids */
575 if (!old_owner || old_owner[0] == 0) {
576 item->type = KDBUS_MATCH_ID_ADD;
578 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
583 /* If thew new name is unset or empty, then this can
584 match against removed ids */
585 if (!new_owner || new_owner[0] == 0) {
586 item->type = KDBUS_MATCH_ID_REMOVE;
588 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
597 int bus_add_match_internal(
600 struct bus_match_component *components,
601 unsigned n_components,
609 if (bus->is_kernel) {
610 struct kdbus_cmd_match *m;
611 struct kdbus_item *item;
612 uint64_t bloom[BLOOM_SIZE/8];
614 const char *sender = NULL;
615 size_t sender_length = 0;
616 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
617 bool using_bloom = false;
619 bool matches_name_change = true;
620 const char *name_change_arg[3] = {};
624 sz = offsetof(struct kdbus_cmd_match, items);
626 for (i = 0; i < n_components; i++) {
627 struct bus_match_component *c = &components[i];
631 case BUS_MATCH_SENDER:
632 if (!streq(c->value_str, "org.freedesktop.DBus"))
633 matches_name_change = false;
635 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
640 sender = c->value_str;
641 sender_length = strlen(sender);
642 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
647 case BUS_MATCH_MESSAGE_TYPE:
648 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
649 matches_name_change = false;
651 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
655 case BUS_MATCH_INTERFACE:
656 if (!streq(c->value_str, "org.freedesktop.DBus"))
657 matches_name_change = false;
659 bloom_add_pair(bloom, "interface", c->value_str);
663 case BUS_MATCH_MEMBER:
664 if (!streq(c->value_str, "NameOwnerChanged"))
665 matches_name_change = false;
667 bloom_add_pair(bloom, "member", c->value_str);
672 if (!streq(c->value_str, "/org/freedesktop/DBus"))
673 matches_name_change = false;
675 bloom_add_pair(bloom, "path", c->value_str);
679 case BUS_MATCH_PATH_NAMESPACE:
680 if (!streq(c->value_str, "/")) {
681 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
686 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
687 char buf[sizeof("arg")-1 + 2 + 1];
689 if (c->type - BUS_MATCH_ARG < 3)
690 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
692 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
693 bloom_add_pair(bloom, buf, c->value_str);
698 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
699 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
701 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
702 bloom_add_pair(bloom, buf, c->value_str);
707 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
708 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
710 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
711 bloom_add_pair(bloom, buf, c->value_str);
716 case BUS_MATCH_DESTINATION:
717 /* The bloom filter does not include
718 the destination, since it is only
719 available for broadcast messages
720 which do not carry a destination
721 since they are undirected. */
725 case BUS_MATCH_VALUE:
727 case _BUS_MATCH_NODE_TYPE_MAX:
728 case _BUS_MATCH_NODE_TYPE_INVALID:
729 assert_not_reached("Invalid match type?");
734 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
744 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
745 item->type = KDBUS_MATCH_BLOOM;
746 memcpy(item->data64, bloom, BLOOM_SIZE);
748 item = KDBUS_PART_NEXT(item);
752 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
753 item->type = KDBUS_MATCH_SRC_NAME;
754 memcpy(item->str, sender, sender_length + 1);
757 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
761 if (matches_name_change) {
763 /* If this match could theoretically match
764 * NameOwnerChanged messages, we need to
765 * install a second non-bloom filter explitly
768 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
775 return sd_bus_call_method(
777 "org.freedesktop.DBus",
779 "org.freedesktop.DBus",
787 int bus_remove_match_internal(
797 if (bus->is_kernel) {
798 struct kdbus_cmd_match m;
801 m.size = offsetof(struct kdbus_cmd_match, items);
804 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
811 return sd_bus_call_method(
813 "org.freedesktop.DBus",
815 "org.freedesktop.DBus",
824 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
825 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
829 assert_return(bus, -EINVAL);
830 assert_return(name, -EINVAL);
831 assert_return(machine, -EINVAL);
832 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
833 assert_return(!bus_pid_changed(bus), -ECHILD);
835 if (streq_ptr(name, bus->unique_name))
836 return sd_id128_get_machine(machine);
838 r = sd_bus_message_new_method_call(
842 "org.freedesktop.DBus.Peer",
847 r = sd_bus_message_set_no_auto_start(m, true);
851 r = sd_bus_call(bus, m, 0, NULL, &reply);
855 r = sd_bus_message_read(reply, "s", &mid);
859 return sd_id128_from_string(mid, machine);