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)
271 r = strv_consume(x, n);
275 previous_id = name->owner_id;
278 KDBUS_ITEM_FOREACH(item, name, items)
279 if (item->type == KDBUS_ITEM_NAME)
280 entry_name = item->str;
282 if (entry_name && service_name_is_valid(entry_name)) {
283 r = strv_extend(x, entry_name);
289 r = kernel_cmd_free(bus, cmd.offset);
296 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
297 _cleanup_strv_free_ char **x = NULL, **y = NULL;
301 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
307 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
323 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
324 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
325 _cleanup_strv_free_ char **x = NULL, **y = NULL;
329 r = sd_bus_call_method(
331 "org.freedesktop.DBus",
332 "/org/freedesktop/DBus",
333 "org.freedesktop.DBus",
341 r = sd_bus_message_read_strv(reply, &x);
345 reply = sd_bus_message_unref(reply);
349 r = sd_bus_call_method(
351 "org.freedesktop.DBus",
352 "/org/freedesktop/DBus",
353 "org.freedesktop.DBus",
354 "ListActivatableNames",
361 r = sd_bus_message_read_strv(reply, &y);
377 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
378 assert_return(bus, -EINVAL);
379 assert_return(acquired || activatable, -EINVAL);
380 assert_return(!bus_pid_changed(bus), -ECHILD);
382 if (!BUS_IS_OPEN(bus->state))
386 return bus_list_names_kernel(bus, acquired, activatable);
388 return bus_list_names_dbus1(bus, acquired, activatable);
391 static int bus_get_owner_kdbus(
395 sd_bus_creds **creds) {
397 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
398 struct kdbus_cmd_conn_info *cmd;
399 struct kdbus_conn_info *conn_info;
400 struct kdbus_item *item;
405 r = bus_kernel_parse_unique_name(name, &id);
409 size = offsetof(struct kdbus_cmd_conn_info, items);
410 cmd = alloca0_align(size, 8);
413 l = strlen(name) + 1;
414 size = offsetof(struct kdbus_cmd_conn_info, items) + KDBUS_ITEM_SIZE(l);
415 cmd = alloca0_align(size, 8);
416 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
417 cmd->items[0].type = KDBUS_ITEM_NAME;
418 memcpy(cmd->items[0].str, name, l);
422 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
424 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
428 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
430 /* Non-activated names are considered not available */
431 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
432 return name[0] == ':' ? -ENXIO : -ESRCH;
438 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
439 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
442 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
445 KDBUS_ITEM_FOREACH(item, conn_info, items) {
447 switch (item->type) {
449 case KDBUS_ITEM_CREDS:
450 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
453 c->uid = (uid_t) item->creds.uid;
454 c->pid = (pid_t) item->creds.pid;
455 c->gid = (gid_t) item->creds.gid;
459 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
460 c->tid = (pid_t) item->creds.tid;
461 c->mask |= SD_BUS_CREDS_TID;
464 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
465 c->pid_starttime = item->creds.starttime;
466 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
471 case KDBUS_ITEM_PID_COMM:
472 if (mask & SD_BUS_CREDS_COMM) {
473 c->comm = strdup(item->str);
479 c->mask |= SD_BUS_CREDS_COMM;
483 case KDBUS_ITEM_TID_COMM:
484 if (mask & SD_BUS_CREDS_TID_COMM) {
485 c->tid_comm = strdup(item->str);
491 c->mask |= SD_BUS_CREDS_TID_COMM;
496 if (mask & SD_BUS_CREDS_EXE) {
497 c->exe = strdup(item->str);
503 c->mask |= SD_BUS_CREDS_EXE;
507 case KDBUS_ITEM_CMDLINE:
508 if (mask & SD_BUS_CREDS_CMDLINE) {
509 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
510 c->cmdline = memdup(item->data, c->cmdline_size);
516 c->mask |= SD_BUS_CREDS_CMDLINE;
520 case KDBUS_ITEM_CGROUP:
521 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
522 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
523 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
526 c->cgroup = strdup(item->str);
532 r = bus_get_root_path(bus);
536 c->cgroup_root = strdup(bus->cgroup_root);
537 if (!c->cgroup_root) {
546 case KDBUS_ITEM_CAPS:
547 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
548 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
551 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
552 c->capability = memdup(item->data, c->capability_size);
553 if (!c->capability) {
562 case KDBUS_ITEM_SECLABEL:
563 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
564 c->label = strdup(item->str);
570 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
574 case KDBUS_ITEM_AUDIT:
575 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
578 c->audit_session_id = item->audit.sessionid;
579 c->audit_login_uid = item->audit.loginuid;
584 case KDBUS_ITEM_NAME:
585 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
586 r = strv_extend(&c->well_known_names, item->name.name);
590 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
594 case KDBUS_ITEM_CONN_NAME:
595 if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
596 c->conn_name = strdup(item->str);
602 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
616 kernel_cmd_free(bus, cmd->offset);
620 static int bus_get_owner_dbus1(
624 sd_bus_creds **creds) {
626 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
627 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
628 const char *unique = NULL;
632 /* Only query the owner if the caller wants to know it or if
633 * the caller just wants to check whether a name exists */
634 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
635 r = sd_bus_call_method(
637 "org.freedesktop.DBus",
638 "/org/freedesktop/DBus",
639 "org.freedesktop.DBus",
648 r = sd_bus_message_read(reply_unique, "s", &unique);
658 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
659 c->unique_name = strdup(unique);
663 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
666 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
667 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
668 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|
669 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
670 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
673 r = sd_bus_call_method(
675 "org.freedesktop.DBus",
676 "/org/freedesktop/DBus",
677 "org.freedesktop.DBus",
678 "GetConnectionUnixProcessID",
682 unique ? unique : name);
686 r = sd_bus_message_read(reply, "u", &u);
691 if (mask & SD_BUS_CREDS_PID) {
693 c->mask |= SD_BUS_CREDS_PID;
696 reply = sd_bus_message_unref(reply);
699 if (mask & SD_BUS_CREDS_UID) {
702 r = sd_bus_call_method(
704 "org.freedesktop.DBus",
705 "/org/freedesktop/DBus",
706 "org.freedesktop.DBus",
707 "GetConnectionUnixUser",
711 unique ? unique : name);
715 r = sd_bus_message_read(reply, "u", &u);
720 c->mask |= SD_BUS_CREDS_UID;
722 reply = sd_bus_message_unref(reply);
725 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
726 const void *p = NULL;
729 r = sd_bus_call_method(
731 "org.freedesktop.DBus",
732 "/org/freedesktop/DBus",
733 "org.freedesktop.DBus",
734 "GetConnectionSELinuxSecurityContext",
738 unique ? unique : name);
742 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
746 c->label = strndup(p, sz);
750 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
753 r = bus_creds_add_more(c, mask, pid, 0);
766 _public_ int sd_bus_get_owner(
770 sd_bus_creds **creds) {
772 assert_return(bus, -EINVAL);
773 assert_return(name, -EINVAL);
774 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
775 assert_return(mask == 0 || creds, -EINVAL);
776 assert_return(!bus_pid_changed(bus), -ECHILD);
777 assert_return(service_name_is_valid(name), -EINVAL);
778 assert_return(bus->bus_client, -ENODATA);
780 if (!BUS_IS_OPEN(bus->state))
784 return bus_get_owner_kdbus(bus, name, mask, creds);
786 return bus_get_owner_dbus1(bus, name, mask, creds);
789 static int add_name_change_match(sd_bus *bus,
792 const char *old_owner,
793 const char *new_owner) {
795 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
796 int is_name_id = -1, r;
797 struct kdbus_item *item;
801 /* If we encounter a match that could match against
802 * NameOwnerChanged messages, then we need to create
803 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
804 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
805 * multiple if the match is underspecified.
807 * The NameOwnerChanged signals take three parameters with
808 * unique or well-known names, but only some forms actually
811 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
812 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
813 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
814 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
815 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
817 * For the latter two the two unique names must be identical.
822 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
827 if (!isempty(old_owner)) {
828 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
833 if (is_name_id > 0 && old_owner_id != name_id)
836 old_owner_id = KDBUS_MATCH_ID_ANY;
838 if (!isempty(new_owner)) {
839 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
844 if (is_name_id > 0 && new_owner_id != name_id)
847 new_owner_id = KDBUS_MATCH_ID_ANY;
849 if (is_name_id <= 0) {
850 struct kdbus_cmd_match *m;
853 /* If the name argument is missing or is a well-known
854 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
857 l = name ? strlen(name) + 1 : 0;
859 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
860 offsetof(struct kdbus_item, name_change) +
861 offsetof(struct kdbus_notify_name_change, name) +
864 m = alloca0_align(sz, 8);
870 offsetof(struct kdbus_item, name_change) +
871 offsetof(struct kdbus_notify_name_change, name) +
874 item->name_change.old_id.id = old_owner_id;
875 item->name_change.new_id.id = new_owner_id;
878 memcpy(item->name_change.name, name, l);
880 /* If the old name is unset or empty, then
881 * this can match against added names */
882 if (!old_owner || old_owner[0] == 0) {
883 item->type = KDBUS_ITEM_NAME_ADD;
885 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
890 /* If the new name is unset or empty, then
891 * this can match against removed names */
892 if (!new_owner || new_owner[0] == 0) {
893 item->type = KDBUS_ITEM_NAME_REMOVE;
895 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
900 /* The CHANGE match we need in either case, because
901 * what is reported as a name change by the kernel
902 * might just be an owner change between starter and
903 * normal clients. For userspace such a change should
904 * be considered a removal/addition, hence let's
905 * subscribe to this unconditionally. */
906 item->type = KDBUS_ITEM_NAME_CHANGE;
907 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
912 if (is_name_id != 0) {
913 struct kdbus_cmd_match *m;
916 /* If the name argument is missing or is a unique
917 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
920 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
921 offsetof(struct kdbus_item, id_change) +
922 sizeof(struct kdbus_notify_id_change));
924 m = alloca0_align(sz, 8);
930 offsetof(struct kdbus_item, id_change) +
931 sizeof(struct kdbus_notify_id_change);
932 item->id_change.id = name_id;
934 /* If the old name is unset or empty, then this can
935 * match against added ids */
936 if (!old_owner || old_owner[0] == 0) {
937 item->type = KDBUS_ITEM_ID_ADD;
939 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
944 /* If thew new name is unset or empty, then this can
945 * match against removed ids */
946 if (!new_owner || new_owner[0] == 0) {
947 item->type = KDBUS_ITEM_ID_REMOVE;
949 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
958 int bus_add_match_internal_kernel(
960 struct bus_match_component *components,
961 unsigned n_components,
964 struct kdbus_cmd_match *m;
965 struct kdbus_item *item;
968 const char *sender = NULL;
969 size_t sender_length = 0;
970 uint64_t src_id = KDBUS_MATCH_ID_ANY;
971 bool using_bloom = false;
973 bool matches_name_change = true;
974 const char *name_change_arg[3] = {};
979 bloom = alloca0(bus->bloom_size);
981 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
983 for (i = 0; i < n_components; i++) {
984 struct bus_match_component *c = &components[i];
988 case BUS_MATCH_SENDER:
989 if (!streq(c->value_str, "org.freedesktop.DBus"))
990 matches_name_change = false;
992 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
996 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
998 sender = c->value_str;
999 sender_length = strlen(sender);
1000 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1005 case BUS_MATCH_MESSAGE_TYPE:
1006 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1007 matches_name_change = false;
1009 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1013 case BUS_MATCH_INTERFACE:
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, "interface", c->value_str);
1021 case BUS_MATCH_MEMBER:
1022 if (!streq(c->value_str, "NameOwnerChanged"))
1023 matches_name_change = false;
1025 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1029 case BUS_MATCH_PATH:
1030 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1031 matches_name_change = false;
1033 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1037 case BUS_MATCH_PATH_NAMESPACE:
1038 if (!streq(c->value_str, "/")) {
1039 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1044 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1045 char buf[sizeof("arg")-1 + 2 + 1];
1047 if (c->type - BUS_MATCH_ARG < 3)
1048 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1050 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1051 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1056 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1057 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1059 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1060 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1065 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1066 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1068 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1069 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1074 case BUS_MATCH_DESTINATION:
1075 /* The bloom filter does not include
1076 the destination, since it is only
1077 available for broadcast messages
1078 which do not carry a destination
1079 since they are undirected. */
1082 case BUS_MATCH_ROOT:
1083 case BUS_MATCH_VALUE:
1084 case BUS_MATCH_LEAF:
1085 case _BUS_MATCH_NODE_TYPE_MAX:
1086 case _BUS_MATCH_NODE_TYPE_INVALID:
1087 assert_not_reached("Invalid match type?");
1092 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1094 m = alloca0_align(sz, 8);
1100 if (src_id != KDBUS_MATCH_ID_ANY) {
1101 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1102 item->type = KDBUS_ITEM_ID;
1104 item = KDBUS_ITEM_NEXT(item);
1108 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1109 item->type = KDBUS_ITEM_BLOOM_MASK;
1110 memcpy(item->data64, bloom, bus->bloom_size);
1111 item = KDBUS_ITEM_NEXT(item);
1115 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1116 item->type = KDBUS_ITEM_NAME;
1117 memcpy(item->str, sender, sender_length + 1);
1120 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1124 if (matches_name_change) {
1126 /* If this match could theoretically match
1127 * NameOwnerChanged messages, we need to
1128 * install a second non-bloom filter explitly
1131 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1139 #define internal_match(bus, m) \
1140 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1141 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1144 static int bus_add_match_internal_dbus1(
1146 const char *match) {
1153 e = internal_match(bus, match);
1155 return sd_bus_call_method(
1157 "org.freedesktop.DBus",
1158 "/org/freedesktop/DBus",
1159 "org.freedesktop.DBus",
1167 int bus_add_match_internal(
1170 struct bus_match_component *components,
1171 unsigned n_components,
1177 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1179 return bus_add_match_internal_dbus1(bus, match);
1182 int bus_remove_match_internal_kernel(
1186 struct kdbus_cmd_match m;
1192 m.size = offsetof(struct kdbus_cmd_match, items);
1195 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1202 static int bus_remove_match_internal_dbus1(
1204 const char *match) {
1211 e = internal_match(bus, match);
1213 return sd_bus_call_method(
1215 "org.freedesktop.DBus",
1216 "/org/freedesktop/DBus",
1217 "org.freedesktop.DBus",
1225 int bus_remove_match_internal(
1233 return bus_remove_match_internal_kernel(bus, cookie);
1235 return bus_remove_match_internal_dbus1(bus, match);
1238 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1239 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1243 assert_return(bus, -EINVAL);
1244 assert_return(name, -EINVAL);
1245 assert_return(machine, -EINVAL);
1246 assert_return(!bus_pid_changed(bus), -ECHILD);
1247 assert_return(service_name_is_valid(name), -EINVAL);
1249 if (!BUS_IS_OPEN(bus->state))
1252 if (streq_ptr(name, bus->unique_name))
1253 return sd_id128_get_machine(machine);
1255 r = sd_bus_message_new_method_call(
1260 "org.freedesktop.DBus.Peer",
1265 r = sd_bus_message_set_auto_start(m, false);
1269 r = sd_bus_call(bus, m, 0, NULL, &reply);
1273 r = sd_bus_message_read(reply, "s", &mid);
1277 return sd_id128_from_string(mid, machine);