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 + 1);
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 + 1;
68 n->items[0].type = KDBUS_ITEM_NAME;
69 memcpy(n->items[0].str, name, l+1);
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;
157 size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l + 1);
158 n = alloca0_align(size, 8);
161 n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l + 1;
162 n->items[0].type = KDBUS_ITEM_NAME;
163 memcpy(n->items[0].str, name, l+1);
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_get_list(sd_bus *bus, uint64_t flags, char ***x) {
227 struct kdbus_cmd_name_list cmd = {};
228 struct kdbus_name_list *name_list;
229 struct kdbus_cmd_name *name;
230 uint64_t previous_id = 0;
233 /* Caller will free half-constructed list on failure... */
237 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
241 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
243 KDBUS_ITEM_FOREACH(name, name_list, names) {
245 struct kdbus_item *item;
246 const char *entry_name = NULL;
248 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
251 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0)
254 r = strv_consume(x, n);
258 previous_id = name->owner_id;
261 KDBUS_ITEM_FOREACH(item, name, items)
262 if (item->type == KDBUS_ITEM_NAME)
263 entry_name = item->str;
265 if (entry_name && service_name_is_valid(entry_name)) {
266 r = strv_extend(x, entry_name);
272 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd.offset);
279 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
280 _cleanup_strv_free_ char **x = NULL, **y = NULL;
284 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
290 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
306 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
307 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
308 _cleanup_strv_free_ char **x = NULL, **y = NULL;
312 r = sd_bus_call_method(
314 "org.freedesktop.DBus",
315 "/org/freedesktop/DBus",
316 "org.freedesktop.DBus",
324 r = sd_bus_message_read_strv(reply, &x);
328 reply = sd_bus_message_unref(reply);
332 r = sd_bus_call_method(
334 "org.freedesktop.DBus",
335 "/org/freedesktop/DBus",
336 "org.freedesktop.DBus",
337 "ListActivatableNames",
344 r = sd_bus_message_read_strv(reply, &y);
360 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
361 assert_return(bus, -EINVAL);
362 assert_return(acquired || activatable, -EINVAL);
363 assert_return(!bus_pid_changed(bus), -ECHILD);
365 if (!BUS_IS_OPEN(bus->state))
369 return bus_list_names_kernel(bus, acquired, activatable);
371 return bus_list_names_dbus1(bus, acquired, activatable);
374 static int bus_get_owner_kdbus(
378 sd_bus_creds **creds) {
380 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
381 struct kdbus_cmd_conn_info *cmd;
382 struct kdbus_conn_info *conn_info;
383 struct kdbus_item *item;
388 r = bus_kernel_parse_unique_name(name, &id);
392 size = offsetof(struct kdbus_cmd_conn_info, name);
393 cmd = alloca0_align(size, 8);
396 size = offsetof(struct kdbus_cmd_conn_info, name) + strlen(name) + 1;
397 cmd = alloca0_align(size, 8);
398 strcpy(cmd->name, name);
402 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
404 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
408 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
410 /* Non-activated names are considered not available */
411 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
412 return name[0] == ':' ? -ENXIO : -ESRCH;
418 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
419 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
422 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
425 KDBUS_ITEM_FOREACH(item, conn_info, items) {
427 switch (item->type) {
429 case KDBUS_ITEM_CREDS:
430 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
433 c->uid = (uid_t) item->creds.uid;
434 c->pid = (pid_t) item->creds.pid;
435 c->gid = (gid_t) item->creds.gid;
439 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
440 c->tid = (pid_t) item->creds.tid;
441 c->mask |= SD_BUS_CREDS_TID;
444 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
445 c->pid_starttime = item->creds.starttime;
446 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
451 case KDBUS_ITEM_PID_COMM:
452 if (mask & SD_BUS_CREDS_COMM) {
453 c->comm = strdup(item->str);
459 c->mask |= SD_BUS_CREDS_COMM;
463 case KDBUS_ITEM_TID_COMM:
464 if (mask & SD_BUS_CREDS_TID_COMM) {
465 c->tid_comm = strdup(item->str);
471 c->mask |= SD_BUS_CREDS_TID_COMM;
476 if (mask & SD_BUS_CREDS_EXE) {
477 c->exe = strdup(item->str);
483 c->mask |= SD_BUS_CREDS_EXE;
487 case KDBUS_ITEM_CMDLINE:
488 if (mask & SD_BUS_CREDS_CMDLINE) {
489 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
490 c->cmdline = memdup(item->data, c->cmdline_size);
496 c->mask |= SD_BUS_CREDS_CMDLINE;
500 case KDBUS_ITEM_CGROUP:
501 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
502 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
503 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
506 c->cgroup = strdup(item->str);
512 r = bus_get_root_path(bus);
516 c->cgroup_root = strdup(bus->cgroup_root);
517 if (!c->cgroup_root) {
526 case KDBUS_ITEM_CAPS:
527 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
528 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
531 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
532 c->capability = memdup(item->data, c->capability_size);
533 if (!c->capability) {
542 case KDBUS_ITEM_SECLABEL:
543 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
544 c->label = strdup(item->str);
550 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
554 case KDBUS_ITEM_AUDIT:
555 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
558 c->audit_session_id = item->audit.sessionid;
559 c->audit_login_uid = item->audit.loginuid;
564 case KDBUS_ITEM_NAME:
565 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
566 r = strv_extend(&c->well_known_names, item->name.name);
570 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
574 case KDBUS_ITEM_CONN_NAME:
575 if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
576 c->conn_name = strdup(item->str);
582 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
596 ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
600 static int bus_get_owner_dbus1(
604 sd_bus_creds **creds) {
606 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
607 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
608 const char *unique = NULL;
612 /* Only query the owner if the caller wants to know it or if
613 * the caller just wants to check whether a name exists */
614 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
615 r = sd_bus_call_method(
617 "org.freedesktop.DBus",
618 "/org/freedesktop/DBus",
619 "org.freedesktop.DBus",
628 r = sd_bus_message_read(reply_unique, "s", &unique);
638 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
639 c->unique_name = strdup(unique);
643 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
646 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
647 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
648 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|
649 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
650 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
653 r = sd_bus_call_method(
655 "org.freedesktop.DBus",
656 "/org/freedesktop/DBus",
657 "org.freedesktop.DBus",
658 "GetConnectionUnixProcessID",
662 unique ? unique : name);
666 r = sd_bus_message_read(reply, "u", &u);
671 if (mask & SD_BUS_CREDS_PID) {
673 c->mask |= SD_BUS_CREDS_PID;
676 reply = sd_bus_message_unref(reply);
679 if (mask & SD_BUS_CREDS_UID) {
682 r = sd_bus_call_method(
684 "org.freedesktop.DBus",
685 "/org/freedesktop/DBus",
686 "org.freedesktop.DBus",
687 "GetConnectionUnixUser",
691 unique ? unique : name);
695 r = sd_bus_message_read(reply, "u", &u);
700 c->mask |= SD_BUS_CREDS_UID;
702 reply = sd_bus_message_unref(reply);
705 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
706 const void *p = NULL;
709 r = sd_bus_call_method(
711 "org.freedesktop.DBus",
712 "/org/freedesktop/DBus",
713 "org.freedesktop.DBus",
714 "GetConnectionSELinuxSecurityContext",
718 unique ? unique : name);
722 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
726 c->label = strndup(p, sz);
730 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
733 r = bus_creds_add_more(c, mask, pid, 0);
746 _public_ int sd_bus_get_owner(
750 sd_bus_creds **creds) {
752 assert_return(bus, -EINVAL);
753 assert_return(name, -EINVAL);
754 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
755 assert_return(mask == 0 || creds, -EINVAL);
756 assert_return(!bus_pid_changed(bus), -ECHILD);
757 assert_return(service_name_is_valid(name), -EINVAL);
758 assert_return(bus->bus_client, -ENODATA);
760 if (!BUS_IS_OPEN(bus->state))
764 return bus_get_owner_kdbus(bus, name, mask, creds);
766 return bus_get_owner_dbus1(bus, name, mask, creds);
769 static int add_name_change_match(sd_bus *bus,
772 const char *old_owner,
773 const char *new_owner) {
775 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
776 int is_name_id = -1, r;
777 struct kdbus_item *item;
781 /* If we encounter a match that could match against
782 * NameOwnerChanged messages, then we need to create
783 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
784 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
785 * multiple if the match is underspecified.
787 * The NameOwnerChanged signals take three parameters with
788 * unique or well-known names, but only some forms actually
791 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
792 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
793 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
794 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
795 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
797 * For the latter two the two unique names must be identical.
802 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
807 if (!isempty(old_owner)) {
808 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
813 if (is_name_id > 0 && old_owner_id != name_id)
816 old_owner_id = KDBUS_MATCH_ID_ANY;
818 if (!isempty(new_owner)) {
819 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
824 if (is_name_id > 0 && new_owner_id != name_id)
827 new_owner_id = KDBUS_MATCH_ID_ANY;
829 if (is_name_id <= 0) {
830 struct kdbus_cmd_match *m;
833 /* If the name argument is missing or is a well-known
834 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
837 l = name ? strlen(name) + 1 : 0;
839 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
840 offsetof(struct kdbus_item, name_change) +
841 offsetof(struct kdbus_notify_name_change, name) +
844 m = alloca0_align(sz, 8);
850 offsetof(struct kdbus_item, name_change) +
851 offsetof(struct kdbus_notify_name_change, name) +
854 item->name_change.old.id = old_owner_id;
855 item->name_change.new.id = new_owner_id;
858 memcpy(item->name_change.name, name, l);
860 /* If the old name is unset or empty, then
861 * this can match against added names */
862 if (!old_owner || old_owner[0] == 0) {
863 item->type = KDBUS_ITEM_NAME_ADD;
865 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
870 /* If the new name is unset or empty, then
871 * this can match against removed names */
872 if (!new_owner || new_owner[0] == 0) {
873 item->type = KDBUS_ITEM_NAME_REMOVE;
875 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
880 /* The CHANGE match we need in either case, because
881 * what is reported as a name change by the kernel
882 * might just be an owner change between starter and
883 * normal clients. For userspace such a change should
884 * be considered a removal/addition, hence let's
885 * subscribe to this unconditionally. */
886 item->type = KDBUS_ITEM_NAME_CHANGE;
887 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
892 if (is_name_id != 0) {
893 struct kdbus_cmd_match *m;
896 /* If the name argument is missing or is a unique
897 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
900 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
901 offsetof(struct kdbus_item, id_change) +
902 sizeof(struct kdbus_notify_id_change));
904 m = alloca0_align(sz, 8);
910 offsetof(struct kdbus_item, id_change) +
911 sizeof(struct kdbus_notify_id_change);
912 item->id_change.id = name_id;
914 /* If the old name is unset or empty, then this can
915 * match against added ids */
916 if (!old_owner || old_owner[0] == 0) {
917 item->type = KDBUS_ITEM_ID_ADD;
919 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
924 /* If thew new name is unset or empty, then this can
925 * match against removed ids */
926 if (!new_owner || new_owner[0] == 0) {
927 item->type = KDBUS_ITEM_ID_REMOVE;
929 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
938 int bus_add_match_internal_kernel(
940 struct bus_match_component *components,
941 unsigned n_components,
944 struct kdbus_cmd_match *m;
945 struct kdbus_item *item;
948 const char *sender = NULL;
949 size_t sender_length = 0;
950 uint64_t src_id = KDBUS_MATCH_ID_ANY;
951 bool using_bloom = false;
953 bool matches_name_change = true;
954 const char *name_change_arg[3] = {};
959 bloom = alloca0(bus->bloom_size);
961 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
963 for (i = 0; i < n_components; i++) {
964 struct bus_match_component *c = &components[i];
968 case BUS_MATCH_SENDER:
969 if (!streq(c->value_str, "org.freedesktop.DBus"))
970 matches_name_change = false;
972 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
976 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
978 sender = c->value_str;
979 sender_length = strlen(sender);
980 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
985 case BUS_MATCH_MESSAGE_TYPE:
986 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
987 matches_name_change = false;
989 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
993 case BUS_MATCH_INTERFACE:
994 if (!streq(c->value_str, "org.freedesktop.DBus"))
995 matches_name_change = false;
997 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1001 case BUS_MATCH_MEMBER:
1002 if (!streq(c->value_str, "NameOwnerChanged"))
1003 matches_name_change = false;
1005 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1009 case BUS_MATCH_PATH:
1010 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1011 matches_name_change = false;
1013 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1017 case BUS_MATCH_PATH_NAMESPACE:
1018 if (!streq(c->value_str, "/")) {
1019 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1024 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1025 char buf[sizeof("arg")-1 + 2 + 1];
1027 if (c->type - BUS_MATCH_ARG < 3)
1028 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1030 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1031 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1036 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1037 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1039 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1040 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1045 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1046 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1048 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1049 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1054 case BUS_MATCH_DESTINATION:
1055 /* The bloom filter does not include
1056 the destination, since it is only
1057 available for broadcast messages
1058 which do not carry a destination
1059 since they are undirected. */
1062 case BUS_MATCH_ROOT:
1063 case BUS_MATCH_VALUE:
1064 case BUS_MATCH_LEAF:
1065 case _BUS_MATCH_NODE_TYPE_MAX:
1066 case _BUS_MATCH_NODE_TYPE_INVALID:
1067 assert_not_reached("Invalid match type?");
1072 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1074 m = alloca0_align(sz, 8);
1080 if (src_id != KDBUS_MATCH_ID_ANY) {
1081 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1082 item->type = KDBUS_ITEM_ID;
1084 item = KDBUS_ITEM_NEXT(item);
1088 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1089 item->type = KDBUS_ITEM_BLOOM_MASK;
1090 memcpy(item->data64, bloom, bus->bloom_size);
1091 item = KDBUS_ITEM_NEXT(item);
1095 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1096 item->type = KDBUS_ITEM_NAME;
1097 memcpy(item->str, sender, sender_length + 1);
1100 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1104 if (matches_name_change) {
1106 /* If this match could theoretically match
1107 * NameOwnerChanged messages, we need to
1108 * install a second non-bloom filter explitly
1111 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1119 #define internal_match(bus, m) \
1120 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1121 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1124 static int bus_add_match_internal_dbus1(
1126 const char *match) {
1133 e = internal_match(bus, match);
1135 return sd_bus_call_method(
1137 "org.freedesktop.DBus",
1138 "/org/freedesktop/DBus",
1139 "org.freedesktop.DBus",
1147 int bus_add_match_internal(
1150 struct bus_match_component *components,
1151 unsigned n_components,
1157 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1159 return bus_add_match_internal_dbus1(bus, match);
1162 int bus_remove_match_internal_kernel(
1166 struct kdbus_cmd_match m;
1172 m.size = offsetof(struct kdbus_cmd_match, items);
1175 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1182 static int bus_remove_match_internal_dbus1(
1184 const char *match) {
1191 e = internal_match(bus, match);
1193 return sd_bus_call_method(
1195 "org.freedesktop.DBus",
1196 "/org/freedesktop/DBus",
1197 "org.freedesktop.DBus",
1205 int bus_remove_match_internal(
1213 return bus_remove_match_internal_kernel(bus, cookie);
1215 return bus_remove_match_internal_dbus1(bus, match);
1218 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1219 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1223 assert_return(bus, -EINVAL);
1224 assert_return(name, -EINVAL);
1225 assert_return(machine, -EINVAL);
1226 assert_return(!bus_pid_changed(bus), -ECHILD);
1227 assert_return(service_name_is_valid(name), -EINVAL);
1229 if (!BUS_IS_OPEN(bus->state))
1232 if (streq_ptr(name, bus->unique_name))
1233 return sd_id128_get_machine(machine);
1235 r = sd_bus_message_new_method_call(
1240 "org.freedesktop.DBus.Peer",
1245 r = sd_bus_message_set_auto_start(m, false);
1249 r = sd_bus_call(bus, m, 0, NULL, &reply);
1253 r = sd_bus_message_read(reply, "s", &mid);
1257 return sd_id128_from_string(mid, machine);