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_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, items);
393 cmd = alloca0_align(size, 8);
396 size_t item_size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
398 size = offsetof(struct kdbus_cmd_conn_info, items) + item_size;
399 cmd = alloca0_align(size, 8);
400 cmd->items[0].size = item_size;
401 cmd->items[0].type = KDBUS_ITEM_NAME;
402 strcpy(cmd->items[0].str, name);
406 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
408 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
412 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
414 /* Non-activated names are considered not available */
415 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
416 return name[0] == ':' ? -ENXIO : -ESRCH;
422 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
423 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
426 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
429 KDBUS_ITEM_FOREACH(item, conn_info, items) {
431 switch (item->type) {
433 case KDBUS_ITEM_CREDS:
434 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
437 c->uid = (uid_t) item->creds.uid;
438 c->pid = (pid_t) item->creds.pid;
439 c->gid = (gid_t) item->creds.gid;
443 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
444 c->tid = (pid_t) item->creds.tid;
445 c->mask |= SD_BUS_CREDS_TID;
448 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
449 c->pid_starttime = item->creds.starttime;
450 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
455 case KDBUS_ITEM_PID_COMM:
456 if (mask & SD_BUS_CREDS_COMM) {
457 c->comm = strdup(item->str);
463 c->mask |= SD_BUS_CREDS_COMM;
467 case KDBUS_ITEM_TID_COMM:
468 if (mask & SD_BUS_CREDS_TID_COMM) {
469 c->tid_comm = strdup(item->str);
475 c->mask |= SD_BUS_CREDS_TID_COMM;
480 if (mask & SD_BUS_CREDS_EXE) {
481 c->exe = strdup(item->str);
487 c->mask |= SD_BUS_CREDS_EXE;
491 case KDBUS_ITEM_CMDLINE:
492 if (mask & SD_BUS_CREDS_CMDLINE) {
493 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
494 c->cmdline = memdup(item->data, c->cmdline_size);
500 c->mask |= SD_BUS_CREDS_CMDLINE;
504 case KDBUS_ITEM_CGROUP:
505 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
506 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
507 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
510 c->cgroup = strdup(item->str);
516 r = bus_get_root_path(bus);
520 c->cgroup_root = strdup(bus->cgroup_root);
521 if (!c->cgroup_root) {
530 case KDBUS_ITEM_CAPS:
531 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
532 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
535 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
536 c->capability = memdup(item->data, c->capability_size);
537 if (!c->capability) {
546 case KDBUS_ITEM_SECLABEL:
547 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
548 c->label = strdup(item->str);
554 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
558 case KDBUS_ITEM_AUDIT:
559 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
562 c->audit_session_id = item->audit.sessionid;
563 c->audit_login_uid = item->audit.loginuid;
568 case KDBUS_ITEM_NAME:
569 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
570 r = strv_extend(&c->well_known_names, item->name.name);
574 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
578 case KDBUS_ITEM_CONN_NAME:
579 if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
580 c->conn_name = strdup(item->str);
586 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
600 ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
604 static int bus_get_owner_dbus1(
608 sd_bus_creds **creds) {
610 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
611 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
612 const char *unique = NULL;
616 /* Only query the owner if the caller wants to know it or if
617 * the caller just wants to check whether a name exists */
618 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
619 r = sd_bus_call_method(
621 "org.freedesktop.DBus",
622 "/org/freedesktop/DBus",
623 "org.freedesktop.DBus",
632 r = sd_bus_message_read(reply_unique, "s", &unique);
642 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
643 c->unique_name = strdup(unique);
647 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
650 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
651 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
652 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|
653 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
654 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
657 r = sd_bus_call_method(
659 "org.freedesktop.DBus",
660 "/org/freedesktop/DBus",
661 "org.freedesktop.DBus",
662 "GetConnectionUnixProcessID",
666 unique ? unique : name);
670 r = sd_bus_message_read(reply, "u", &u);
675 if (mask & SD_BUS_CREDS_PID) {
677 c->mask |= SD_BUS_CREDS_PID;
680 reply = sd_bus_message_unref(reply);
683 if (mask & SD_BUS_CREDS_UID) {
686 r = sd_bus_call_method(
688 "org.freedesktop.DBus",
689 "/org/freedesktop/DBus",
690 "org.freedesktop.DBus",
691 "GetConnectionUnixUser",
695 unique ? unique : name);
699 r = sd_bus_message_read(reply, "u", &u);
704 c->mask |= SD_BUS_CREDS_UID;
706 reply = sd_bus_message_unref(reply);
709 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
710 const void *p = NULL;
713 r = sd_bus_call_method(
715 "org.freedesktop.DBus",
716 "/org/freedesktop/DBus",
717 "org.freedesktop.DBus",
718 "GetConnectionSELinuxSecurityContext",
722 unique ? unique : name);
726 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
730 c->label = strndup(p, sz);
734 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
737 r = bus_creds_add_more(c, mask, pid, 0);
750 _public_ int sd_bus_get_owner(
754 sd_bus_creds **creds) {
756 assert_return(bus, -EINVAL);
757 assert_return(name, -EINVAL);
758 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
759 assert_return(mask == 0 || creds, -EINVAL);
760 assert_return(!bus_pid_changed(bus), -ECHILD);
761 assert_return(service_name_is_valid(name), -EINVAL);
762 assert_return(bus->bus_client, -ENODATA);
764 if (!BUS_IS_OPEN(bus->state))
768 return bus_get_owner_kdbus(bus, name, mask, creds);
770 return bus_get_owner_dbus1(bus, name, mask, creds);
773 static int add_name_change_match(sd_bus *bus,
776 const char *old_owner,
777 const char *new_owner) {
779 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
780 int is_name_id = -1, r;
781 struct kdbus_item *item;
785 /* If we encounter a match that could match against
786 * NameOwnerChanged messages, then we need to create
787 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
788 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
789 * multiple if the match is underspecified.
791 * The NameOwnerChanged signals take three parameters with
792 * unique or well-known names, but only some forms actually
795 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
796 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
797 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
798 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
799 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
801 * For the latter two the two unique names must be identical.
806 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
811 if (!isempty(old_owner)) {
812 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
817 if (is_name_id > 0 && old_owner_id != name_id)
820 old_owner_id = KDBUS_MATCH_ID_ANY;
822 if (!isempty(new_owner)) {
823 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
828 if (is_name_id > 0 && new_owner_id != name_id)
831 new_owner_id = KDBUS_MATCH_ID_ANY;
833 if (is_name_id <= 0) {
834 struct kdbus_cmd_match *m;
837 /* If the name argument is missing or is a well-known
838 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
841 l = name ? strlen(name) + 1 : 0;
843 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
844 offsetof(struct kdbus_item, name_change) +
845 offsetof(struct kdbus_notify_name_change, name) +
848 m = alloca0_align(sz, 8);
854 offsetof(struct kdbus_item, name_change) +
855 offsetof(struct kdbus_notify_name_change, name) +
858 item->name_change.old_id.id = old_owner_id;
859 item->name_change.new_id.id = new_owner_id;
862 memcpy(item->name_change.name, name, l);
864 /* If the old name is unset or empty, then
865 * this can match against added names */
866 if (!old_owner || old_owner[0] == 0) {
867 item->type = KDBUS_ITEM_NAME_ADD;
869 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
874 /* If the new name is unset or empty, then
875 * this can match against removed names */
876 if (!new_owner || new_owner[0] == 0) {
877 item->type = KDBUS_ITEM_NAME_REMOVE;
879 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
884 /* The CHANGE match we need in either case, because
885 * what is reported as a name change by the kernel
886 * might just be an owner change between starter and
887 * normal clients. For userspace such a change should
888 * be considered a removal/addition, hence let's
889 * subscribe to this unconditionally. */
890 item->type = KDBUS_ITEM_NAME_CHANGE;
891 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
896 if (is_name_id != 0) {
897 struct kdbus_cmd_match *m;
900 /* If the name argument is missing or is a unique
901 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
904 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
905 offsetof(struct kdbus_item, id_change) +
906 sizeof(struct kdbus_notify_id_change));
908 m = alloca0_align(sz, 8);
914 offsetof(struct kdbus_item, id_change) +
915 sizeof(struct kdbus_notify_id_change);
916 item->id_change.id = name_id;
918 /* If the old name is unset or empty, then this can
919 * match against added ids */
920 if (!old_owner || old_owner[0] == 0) {
921 item->type = KDBUS_ITEM_ID_ADD;
923 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
928 /* If thew new name is unset or empty, then this can
929 * match against removed ids */
930 if (!new_owner || new_owner[0] == 0) {
931 item->type = KDBUS_ITEM_ID_REMOVE;
933 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
942 int bus_add_match_internal_kernel(
944 struct bus_match_component *components,
945 unsigned n_components,
948 struct kdbus_cmd_match *m;
949 struct kdbus_item *item;
952 const char *sender = NULL;
953 size_t sender_length = 0;
954 uint64_t src_id = KDBUS_MATCH_ID_ANY;
955 bool using_bloom = false;
957 bool matches_name_change = true;
958 const char *name_change_arg[3] = {};
963 bloom = alloca0(bus->bloom_size);
965 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
967 for (i = 0; i < n_components; i++) {
968 struct bus_match_component *c = &components[i];
972 case BUS_MATCH_SENDER:
973 if (!streq(c->value_str, "org.freedesktop.DBus"))
974 matches_name_change = false;
976 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
980 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
982 sender = c->value_str;
983 sender_length = strlen(sender);
984 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
989 case BUS_MATCH_MESSAGE_TYPE:
990 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
991 matches_name_change = false;
993 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
997 case BUS_MATCH_INTERFACE:
998 if (!streq(c->value_str, "org.freedesktop.DBus"))
999 matches_name_change = false;
1001 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1005 case BUS_MATCH_MEMBER:
1006 if (!streq(c->value_str, "NameOwnerChanged"))
1007 matches_name_change = false;
1009 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1013 case BUS_MATCH_PATH:
1014 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1015 matches_name_change = false;
1017 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1021 case BUS_MATCH_PATH_NAMESPACE:
1022 if (!streq(c->value_str, "/")) {
1023 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1028 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1029 char buf[sizeof("arg")-1 + 2 + 1];
1031 if (c->type - BUS_MATCH_ARG < 3)
1032 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1034 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1035 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1040 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1041 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1043 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1044 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1049 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1050 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1052 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1053 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1058 case BUS_MATCH_DESTINATION:
1059 /* The bloom filter does not include
1060 the destination, since it is only
1061 available for broadcast messages
1062 which do not carry a destination
1063 since they are undirected. */
1066 case BUS_MATCH_ROOT:
1067 case BUS_MATCH_VALUE:
1068 case BUS_MATCH_LEAF:
1069 case _BUS_MATCH_NODE_TYPE_MAX:
1070 case _BUS_MATCH_NODE_TYPE_INVALID:
1071 assert_not_reached("Invalid match type?");
1076 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1078 m = alloca0_align(sz, 8);
1084 if (src_id != KDBUS_MATCH_ID_ANY) {
1085 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1086 item->type = KDBUS_ITEM_ID;
1088 item = KDBUS_ITEM_NEXT(item);
1092 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1093 item->type = KDBUS_ITEM_BLOOM_MASK;
1094 memcpy(item->data64, bloom, bus->bloom_size);
1095 item = KDBUS_ITEM_NEXT(item);
1099 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1100 item->type = KDBUS_ITEM_NAME;
1101 memcpy(item->str, sender, sender_length + 1);
1104 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1108 if (matches_name_change) {
1110 /* If this match could theoretically match
1111 * NameOwnerChanged messages, we need to
1112 * install a second non-bloom filter explitly
1115 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1123 #define internal_match(bus, m) \
1124 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1125 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1128 static int bus_add_match_internal_dbus1(
1130 const char *match) {
1137 e = internal_match(bus, match);
1139 return sd_bus_call_method(
1141 "org.freedesktop.DBus",
1142 "/org/freedesktop/DBus",
1143 "org.freedesktop.DBus",
1151 int bus_add_match_internal(
1154 struct bus_match_component *components,
1155 unsigned n_components,
1161 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1163 return bus_add_match_internal_dbus1(bus, match);
1166 int bus_remove_match_internal_kernel(
1170 struct kdbus_cmd_match m;
1176 m.size = offsetof(struct kdbus_cmd_match, items);
1179 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1186 static int bus_remove_match_internal_dbus1(
1188 const char *match) {
1195 e = internal_match(bus, match);
1197 return sd_bus_call_method(
1199 "org.freedesktop.DBus",
1200 "/org/freedesktop/DBus",
1201 "org.freedesktop.DBus",
1209 int bus_remove_match_internal(
1217 return bus_remove_match_internal_kernel(bus, cookie);
1219 return bus_remove_match_internal_dbus1(bus, match);
1222 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1223 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1227 assert_return(bus, -EINVAL);
1228 assert_return(name, -EINVAL);
1229 assert_return(machine, -EINVAL);
1230 assert_return(!bus_pid_changed(bus), -ECHILD);
1231 assert_return(service_name_is_valid(name), -EINVAL);
1233 if (!BUS_IS_OPEN(bus->state))
1236 if (streq_ptr(name, bus->unique_name))
1237 return sd_id128_get_machine(machine);
1239 r = sd_bus_message_new_method_call(
1244 "org.freedesktop.DBus.Peer",
1249 r = sd_bus_message_set_auto_start(m, false);
1253 r = sd_bus_call(bus, m, 0, NULL, &reply);
1257 r = sd_bus_message_read(reply, "s", &mid);
1261 return sd_id128_from_string(mid, machine);