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>
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-control.h"
34 #include "bus-bloom.h"
36 #include "cgroup-util.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 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
54 struct kdbus_cmd_name *n;
62 size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
63 n = alloca0_align(size, 8);
65 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
67 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
68 n->items[0].type = KDBUS_ITEM_NAME;
69 memcpy(n->items[0].str, name, l);
71 #ifdef HAVE_VALGRIND_MEMCHECK_H
72 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
75 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
79 if (n->flags & KDBUS_NAME_IN_QUEUE)
85 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
86 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
87 uint32_t ret, param = 0;
93 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
94 param |= BUS_NAME_ALLOW_REPLACEMENT;
95 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
96 param |= BUS_NAME_REPLACE_EXISTING;
97 if (!(flags & SD_BUS_NAME_QUEUE))
98 param |= BUS_NAME_DO_NOT_QUEUE;
100 r = sd_bus_call_method(
102 "org.freedesktop.DBus",
103 "/org/freedesktop/DBus",
104 "org.freedesktop.DBus",
114 r = sd_bus_message_read(reply, "u", &ret);
118 if (ret == BUS_NAME_ALREADY_OWNER)
120 else if (ret == BUS_NAME_EXISTS)
122 else if (ret == BUS_NAME_IN_QUEUE)
124 else if (ret == BUS_NAME_PRIMARY_OWNER)
130 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
131 assert_return(bus, -EINVAL);
132 assert_return(name, -EINVAL);
133 assert_return(bus->bus_client, -EINVAL);
134 assert_return(!bus_pid_changed(bus), -ECHILD);
135 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
136 assert_return(service_name_is_valid(name), -EINVAL);
137 assert_return(name[0] != ':', -EINVAL);
139 if (!BUS_IS_OPEN(bus->state))
143 return bus_request_name_kernel(bus, name, flags);
145 return bus_request_name_dbus1(bus, name, flags);
148 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
149 struct kdbus_cmd_name *n;
156 l = strlen(name) + 1;
157 size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
158 n = alloca0_align(size, 8);
161 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
162 n->items[0].type = KDBUS_ITEM_NAME;
163 memcpy(n->items[0].str, name, l);
165 #ifdef HAVE_VALGRIND_MEMCHECK_H
166 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
168 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
175 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
176 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
183 r = sd_bus_call_method(
185 "org.freedesktop.DBus",
186 "/org/freedesktop/DBus",
187 "org.freedesktop.DBus",
196 r = sd_bus_message_read(reply, "u", &ret);
199 if (ret == BUS_NAME_NON_EXISTENT)
201 if (ret == BUS_NAME_NOT_OWNER)
203 if (ret == BUS_NAME_RELEASED)
209 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
210 assert_return(bus, -EINVAL);
211 assert_return(name, -EINVAL);
212 assert_return(bus->bus_client, -EINVAL);
213 assert_return(!bus_pid_changed(bus), -ECHILD);
214 assert_return(service_name_is_valid(name), -EINVAL);
215 assert_return(name[0] != ':', -EINVAL);
217 if (!BUS_IS_OPEN(bus->state))
221 return bus_release_name_kernel(bus, name);
223 return bus_release_name_dbus1(bus, name);
226 static int kernel_cmd_free(sd_bus *bus, uint64_t offset)
228 struct kdbus_cmd_free cmd;
236 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
243 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
244 struct kdbus_cmd_name_list cmd = {};
245 struct kdbus_name_list *name_list;
246 struct kdbus_cmd_name *name;
247 uint64_t previous_id = 0;
250 /* Caller will free half-constructed list on failure... */
254 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
258 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
260 KDBUS_ITEM_FOREACH(name, name_list, names) {
262 struct kdbus_item *item;
263 const char *entry_name = NULL;
265 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
268 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
273 r = strv_consume(x, n);
277 previous_id = name->owner_id;
280 KDBUS_ITEM_FOREACH(item, name, items)
281 if (item->type == KDBUS_ITEM_NAME)
282 entry_name = item->str;
284 if (entry_name && service_name_is_valid(entry_name)) {
285 r = strv_extend(x, entry_name);
296 kernel_cmd_free(bus, cmd.offset);
300 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
301 _cleanup_strv_free_ char **x = NULL, **y = NULL;
305 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
311 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
327 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
328 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
329 _cleanup_strv_free_ char **x = NULL, **y = NULL;
333 r = sd_bus_call_method(
335 "org.freedesktop.DBus",
336 "/org/freedesktop/DBus",
337 "org.freedesktop.DBus",
345 r = sd_bus_message_read_strv(reply, &x);
349 reply = sd_bus_message_unref(reply);
353 r = sd_bus_call_method(
355 "org.freedesktop.DBus",
356 "/org/freedesktop/DBus",
357 "org.freedesktop.DBus",
358 "ListActivatableNames",
365 r = sd_bus_message_read_strv(reply, &y);
381 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
382 assert_return(bus, -EINVAL);
383 assert_return(acquired || activatable, -EINVAL);
384 assert_return(!bus_pid_changed(bus), -ECHILD);
386 if (!BUS_IS_OPEN(bus->state))
390 return bus_list_names_kernel(bus, acquired, activatable);
392 return bus_list_names_dbus1(bus, acquired, activatable);
395 static int bus_get_owner_kdbus(
399 sd_bus_creds **creds) {
401 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
402 struct kdbus_cmd_conn_info *cmd;
403 struct kdbus_conn_info *conn_info;
404 struct kdbus_item *item;
409 r = bus_kernel_parse_unique_name(name, &id);
413 size = offsetof(struct kdbus_cmd_conn_info, items);
414 cmd = alloca0_align(size, 8);
417 l = strlen(name) + 1;
418 size = offsetof(struct kdbus_cmd_conn_info, items) + KDBUS_ITEM_SIZE(l);
419 cmd = alloca0_align(size, 8);
420 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
421 cmd->items[0].type = KDBUS_ITEM_NAME;
422 memcpy(cmd->items[0].str, name, l);
426 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
428 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
432 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
434 /* Non-activated names are considered not available */
435 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
449 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
450 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
455 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
458 KDBUS_ITEM_FOREACH(item, conn_info, items) {
460 switch (item->type) {
462 case KDBUS_ITEM_CREDS:
463 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
466 c->uid = (uid_t) item->creds.uid;
467 c->pid = (pid_t) item->creds.pid;
468 c->gid = (gid_t) item->creds.gid;
472 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
473 c->tid = (pid_t) item->creds.tid;
474 c->mask |= SD_BUS_CREDS_TID;
477 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
478 c->pid_starttime = item->creds.starttime;
479 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
484 case KDBUS_ITEM_PID_COMM:
485 if (mask & SD_BUS_CREDS_COMM) {
486 c->comm = strdup(item->str);
492 c->mask |= SD_BUS_CREDS_COMM;
496 case KDBUS_ITEM_TID_COMM:
497 if (mask & SD_BUS_CREDS_TID_COMM) {
498 c->tid_comm = strdup(item->str);
504 c->mask |= SD_BUS_CREDS_TID_COMM;
509 if (mask & SD_BUS_CREDS_EXE) {
510 c->exe = strdup(item->str);
516 c->mask |= SD_BUS_CREDS_EXE;
520 case KDBUS_ITEM_CMDLINE:
521 if (mask & SD_BUS_CREDS_CMDLINE) {
522 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
523 c->cmdline = memdup(item->data, c->cmdline_size);
529 c->mask |= SD_BUS_CREDS_CMDLINE;
533 case KDBUS_ITEM_CGROUP:
534 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
535 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
536 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
539 c->cgroup = strdup(item->str);
545 r = bus_get_root_path(bus);
549 c->cgroup_root = strdup(bus->cgroup_root);
550 if (!c->cgroup_root) {
559 case KDBUS_ITEM_CAPS:
560 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
561 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
564 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
565 c->capability = memdup(item->data, c->capability_size);
566 if (!c->capability) {
575 case KDBUS_ITEM_SECLABEL:
576 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
577 c->label = strdup(item->str);
583 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
587 case KDBUS_ITEM_AUDIT:
588 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
591 c->audit_session_id = item->audit.sessionid;
592 c->audit_login_uid = item->audit.loginuid;
597 case KDBUS_ITEM_NAME:
598 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
599 r = strv_extend(&c->well_known_names, item->name.name);
603 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
607 case KDBUS_ITEM_CONN_NAME:
608 if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
609 c->conn_name = strdup(item->str);
615 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
629 kernel_cmd_free(bus, cmd->offset);
633 static int bus_get_owner_dbus1(
637 sd_bus_creds **creds) {
639 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
640 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
641 const char *unique = NULL;
645 /* Only query the owner if the caller wants to know it or if
646 * the caller just wants to check whether a name exists */
647 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
648 r = sd_bus_call_method(
650 "org.freedesktop.DBus",
651 "/org/freedesktop/DBus",
652 "org.freedesktop.DBus",
661 r = sd_bus_message_read(reply_unique, "s", &unique);
671 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
672 c->unique_name = strdup(unique);
676 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
679 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
680 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
681 SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
682 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
683 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
686 r = sd_bus_call_method(
688 "org.freedesktop.DBus",
689 "/org/freedesktop/DBus",
690 "org.freedesktop.DBus",
691 "GetConnectionUnixProcessID",
695 unique ? unique : name);
699 r = sd_bus_message_read(reply, "u", &u);
704 if (mask & SD_BUS_CREDS_PID) {
706 c->mask |= SD_BUS_CREDS_PID;
709 reply = sd_bus_message_unref(reply);
712 if (mask & SD_BUS_CREDS_UID) {
715 r = sd_bus_call_method(
717 "org.freedesktop.DBus",
718 "/org/freedesktop/DBus",
719 "org.freedesktop.DBus",
720 "GetConnectionUnixUser",
724 unique ? unique : name);
728 r = sd_bus_message_read(reply, "u", &u);
733 c->mask |= SD_BUS_CREDS_UID;
735 reply = sd_bus_message_unref(reply);
738 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
739 const void *p = NULL;
742 r = sd_bus_call_method(
744 "org.freedesktop.DBus",
745 "/org/freedesktop/DBus",
746 "org.freedesktop.DBus",
747 "GetConnectionSELinuxSecurityContext",
751 unique ? unique : name);
755 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
759 c->label = strndup(p, sz);
763 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
766 r = bus_creds_add_more(c, mask, pid, 0);
779 _public_ int sd_bus_get_owner(
783 sd_bus_creds **creds) {
785 assert_return(bus, -EINVAL);
786 assert_return(name, -EINVAL);
787 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
788 assert_return(mask == 0 || creds, -EINVAL);
789 assert_return(!bus_pid_changed(bus), -ECHILD);
790 assert_return(service_name_is_valid(name), -EINVAL);
791 assert_return(bus->bus_client, -ENODATA);
793 if (!BUS_IS_OPEN(bus->state))
797 return bus_get_owner_kdbus(bus, name, mask, creds);
799 return bus_get_owner_dbus1(bus, name, mask, creds);
802 static int add_name_change_match(sd_bus *bus,
805 const char *old_owner,
806 const char *new_owner) {
808 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
809 int is_name_id = -1, r;
810 struct kdbus_item *item;
814 /* If we encounter a match that could match against
815 * NameOwnerChanged messages, then we need to create
816 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
817 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
818 * multiple if the match is underspecified.
820 * The NameOwnerChanged signals take three parameters with
821 * unique or well-known names, but only some forms actually
824 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
825 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
826 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
827 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
828 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
830 * For the latter two the two unique names must be identical.
835 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
840 if (!isempty(old_owner)) {
841 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
846 if (is_name_id > 0 && old_owner_id != name_id)
849 old_owner_id = KDBUS_MATCH_ID_ANY;
851 if (!isempty(new_owner)) {
852 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
857 if (is_name_id > 0 && new_owner_id != name_id)
860 new_owner_id = KDBUS_MATCH_ID_ANY;
862 if (is_name_id <= 0) {
863 struct kdbus_cmd_match *m;
866 /* If the name argument is missing or is a well-known
867 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
870 l = name ? strlen(name) + 1 : 0;
872 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
873 offsetof(struct kdbus_item, name_change) +
874 offsetof(struct kdbus_notify_name_change, name) +
877 m = alloca0_align(sz, 8);
883 offsetof(struct kdbus_item, name_change) +
884 offsetof(struct kdbus_notify_name_change, name) +
887 item->name_change.old_id.id = old_owner_id;
888 item->name_change.new_id.id = new_owner_id;
891 memcpy(item->name_change.name, name, l);
893 /* If the old name is unset or empty, then
894 * this can match against added names */
895 if (!old_owner || old_owner[0] == 0) {
896 item->type = KDBUS_ITEM_NAME_ADD;
898 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
903 /* If the new name is unset or empty, then
904 * this can match against removed names */
905 if (!new_owner || new_owner[0] == 0) {
906 item->type = KDBUS_ITEM_NAME_REMOVE;
908 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
913 /* The CHANGE match we need in either case, because
914 * what is reported as a name change by the kernel
915 * might just be an owner change between starter and
916 * normal clients. For userspace such a change should
917 * be considered a removal/addition, hence let's
918 * subscribe to this unconditionally. */
919 item->type = KDBUS_ITEM_NAME_CHANGE;
920 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
925 if (is_name_id != 0) {
926 struct kdbus_cmd_match *m;
929 /* If the name argument is missing or is a unique
930 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
933 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
934 offsetof(struct kdbus_item, id_change) +
935 sizeof(struct kdbus_notify_id_change));
937 m = alloca0_align(sz, 8);
943 offsetof(struct kdbus_item, id_change) +
944 sizeof(struct kdbus_notify_id_change);
945 item->id_change.id = name_id;
947 /* If the old name is unset or empty, then this can
948 * match against added ids */
949 if (!old_owner || old_owner[0] == 0) {
950 item->type = KDBUS_ITEM_ID_ADD;
952 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
957 /* If thew new name is unset or empty, then this can
958 * match against removed ids */
959 if (!new_owner || new_owner[0] == 0) {
960 item->type = KDBUS_ITEM_ID_REMOVE;
962 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
971 int bus_add_match_internal_kernel(
973 struct bus_match_component *components,
974 unsigned n_components,
977 struct kdbus_cmd_match *m;
978 struct kdbus_item *item;
981 const char *sender = NULL;
982 size_t sender_length = 0;
983 uint64_t src_id = KDBUS_MATCH_ID_ANY;
984 bool using_bloom = false;
986 bool matches_name_change = true;
987 const char *name_change_arg[3] = {};
992 bloom = alloca0(bus->bloom_size);
994 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
996 for (i = 0; i < n_components; i++) {
997 struct bus_match_component *c = &components[i];
1001 case BUS_MATCH_SENDER:
1002 if (!streq(c->value_str, "org.freedesktop.DBus"))
1003 matches_name_change = false;
1005 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1009 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1011 sender = c->value_str;
1012 sender_length = strlen(sender);
1013 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1018 case BUS_MATCH_MESSAGE_TYPE:
1019 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1020 matches_name_change = false;
1022 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1026 case BUS_MATCH_INTERFACE:
1027 if (!streq(c->value_str, "org.freedesktop.DBus"))
1028 matches_name_change = false;
1030 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1034 case BUS_MATCH_MEMBER:
1035 if (!streq(c->value_str, "NameOwnerChanged"))
1036 matches_name_change = false;
1038 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1042 case BUS_MATCH_PATH:
1043 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1044 matches_name_change = false;
1046 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1050 case BUS_MATCH_PATH_NAMESPACE:
1051 if (!streq(c->value_str, "/")) {
1052 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1057 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1058 char buf[sizeof("arg")-1 + 2 + 1];
1060 if (c->type - BUS_MATCH_ARG < 3)
1061 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1063 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1064 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1069 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1070 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1072 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1073 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1078 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1079 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1081 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1082 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1087 case BUS_MATCH_DESTINATION:
1088 /* The bloom filter does not include
1089 the destination, since it is only
1090 available for broadcast messages
1091 which do not carry a destination
1092 since they are undirected. */
1095 case BUS_MATCH_ROOT:
1096 case BUS_MATCH_VALUE:
1097 case BUS_MATCH_LEAF:
1098 case _BUS_MATCH_NODE_TYPE_MAX:
1099 case _BUS_MATCH_NODE_TYPE_INVALID:
1100 assert_not_reached("Invalid match type?");
1105 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1107 m = alloca0_align(sz, 8);
1113 if (src_id != KDBUS_MATCH_ID_ANY) {
1114 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1115 item->type = KDBUS_ITEM_ID;
1117 item = KDBUS_ITEM_NEXT(item);
1121 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1122 item->type = KDBUS_ITEM_BLOOM_MASK;
1123 memcpy(item->data64, bloom, bus->bloom_size);
1124 item = KDBUS_ITEM_NEXT(item);
1128 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1129 item->type = KDBUS_ITEM_NAME;
1130 memcpy(item->str, sender, sender_length + 1);
1133 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1137 if (matches_name_change) {
1139 /* If this match could theoretically match
1140 * NameOwnerChanged messages, we need to
1141 * install a second non-bloom filter explitly
1144 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1152 #define internal_match(bus, m) \
1153 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1154 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1157 static int bus_add_match_internal_dbus1(
1159 const char *match) {
1166 e = internal_match(bus, match);
1168 return sd_bus_call_method(
1170 "org.freedesktop.DBus",
1171 "/org/freedesktop/DBus",
1172 "org.freedesktop.DBus",
1180 int bus_add_match_internal(
1183 struct bus_match_component *components,
1184 unsigned n_components,
1190 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1192 return bus_add_match_internal_dbus1(bus, match);
1195 int bus_remove_match_internal_kernel(
1199 struct kdbus_cmd_match m;
1205 m.size = offsetof(struct kdbus_cmd_match, items);
1208 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1215 static int bus_remove_match_internal_dbus1(
1217 const char *match) {
1224 e = internal_match(bus, match);
1226 return sd_bus_call_method(
1228 "org.freedesktop.DBus",
1229 "/org/freedesktop/DBus",
1230 "org.freedesktop.DBus",
1238 int bus_remove_match_internal(
1246 return bus_remove_match_internal_kernel(bus, cookie);
1248 return bus_remove_match_internal_dbus1(bus, match);
1251 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1252 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1256 assert_return(bus, -EINVAL);
1257 assert_return(name, -EINVAL);
1258 assert_return(machine, -EINVAL);
1259 assert_return(!bus_pid_changed(bus), -ECHILD);
1260 assert_return(service_name_is_valid(name), -EINVAL);
1262 if (!BUS_IS_OPEN(bus->state))
1265 if (streq_ptr(name, bus->unique_name))
1266 return sd_id128_get_machine(machine);
1268 r = sd_bus_message_new_method_call(
1273 "org.freedesktop.DBus.Peer",
1278 r = sd_bus_message_set_auto_start(m, false);
1282 r = sd_bus_call(bus, m, 0, NULL, &reply);
1286 r = sd_bus_message_read(reply, "s", &mid);
1290 return sd_id128_from_string(mid, machine);