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 size_t item_size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
415 size = offsetof(struct kdbus_cmd_conn_info, items) + item_size;
416 cmd = alloca0_align(size, 8);
417 cmd->items[0].size = item_size;
418 cmd->items[0].type = KDBUS_ITEM_NAME;
419 strcpy(cmd->items[0].str, name);
423 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
425 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
429 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
431 /* Non-activated names are considered not available */
432 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
433 return name[0] == ':' ? -ENXIO : -ESRCH;
439 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
440 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
443 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
446 KDBUS_ITEM_FOREACH(item, conn_info, items) {
448 switch (item->type) {
450 case KDBUS_ITEM_CREDS:
451 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
454 c->uid = (uid_t) item->creds.uid;
455 c->pid = (pid_t) item->creds.pid;
456 c->gid = (gid_t) item->creds.gid;
460 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
461 c->tid = (pid_t) item->creds.tid;
462 c->mask |= SD_BUS_CREDS_TID;
465 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
466 c->pid_starttime = item->creds.starttime;
467 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
472 case KDBUS_ITEM_PID_COMM:
473 if (mask & SD_BUS_CREDS_COMM) {
474 c->comm = strdup(item->str);
480 c->mask |= SD_BUS_CREDS_COMM;
484 case KDBUS_ITEM_TID_COMM:
485 if (mask & SD_BUS_CREDS_TID_COMM) {
486 c->tid_comm = strdup(item->str);
492 c->mask |= SD_BUS_CREDS_TID_COMM;
497 if (mask & SD_BUS_CREDS_EXE) {
498 c->exe = strdup(item->str);
504 c->mask |= SD_BUS_CREDS_EXE;
508 case KDBUS_ITEM_CMDLINE:
509 if (mask & SD_BUS_CREDS_CMDLINE) {
510 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
511 c->cmdline = memdup(item->data, c->cmdline_size);
517 c->mask |= SD_BUS_CREDS_CMDLINE;
521 case KDBUS_ITEM_CGROUP:
522 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
523 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
524 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
527 c->cgroup = strdup(item->str);
533 r = bus_get_root_path(bus);
537 c->cgroup_root = strdup(bus->cgroup_root);
538 if (!c->cgroup_root) {
547 case KDBUS_ITEM_CAPS:
548 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
549 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
552 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
553 c->capability = memdup(item->data, c->capability_size);
554 if (!c->capability) {
563 case KDBUS_ITEM_SECLABEL:
564 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
565 c->label = strdup(item->str);
571 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
575 case KDBUS_ITEM_AUDIT:
576 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
579 c->audit_session_id = item->audit.sessionid;
580 c->audit_login_uid = item->audit.loginuid;
585 case KDBUS_ITEM_NAME:
586 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
587 r = strv_extend(&c->well_known_names, item->name.name);
591 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
595 case KDBUS_ITEM_CONN_NAME:
596 if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
597 c->conn_name = strdup(item->str);
603 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
617 kernel_cmd_free(bus, cmd->offset);
621 static int bus_get_owner_dbus1(
625 sd_bus_creds **creds) {
627 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
628 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
629 const char *unique = NULL;
633 /* Only query the owner if the caller wants to know it or if
634 * the caller just wants to check whether a name exists */
635 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
636 r = sd_bus_call_method(
638 "org.freedesktop.DBus",
639 "/org/freedesktop/DBus",
640 "org.freedesktop.DBus",
649 r = sd_bus_message_read(reply_unique, "s", &unique);
659 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
660 c->unique_name = strdup(unique);
664 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
667 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
668 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
669 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|
670 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
671 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
674 r = sd_bus_call_method(
676 "org.freedesktop.DBus",
677 "/org/freedesktop/DBus",
678 "org.freedesktop.DBus",
679 "GetConnectionUnixProcessID",
683 unique ? unique : name);
687 r = sd_bus_message_read(reply, "u", &u);
692 if (mask & SD_BUS_CREDS_PID) {
694 c->mask |= SD_BUS_CREDS_PID;
697 reply = sd_bus_message_unref(reply);
700 if (mask & SD_BUS_CREDS_UID) {
703 r = sd_bus_call_method(
705 "org.freedesktop.DBus",
706 "/org/freedesktop/DBus",
707 "org.freedesktop.DBus",
708 "GetConnectionUnixUser",
712 unique ? unique : name);
716 r = sd_bus_message_read(reply, "u", &u);
721 c->mask |= SD_BUS_CREDS_UID;
723 reply = sd_bus_message_unref(reply);
726 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
727 const void *p = NULL;
730 r = sd_bus_call_method(
732 "org.freedesktop.DBus",
733 "/org/freedesktop/DBus",
734 "org.freedesktop.DBus",
735 "GetConnectionSELinuxSecurityContext",
739 unique ? unique : name);
743 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
747 c->label = strndup(p, sz);
751 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
754 r = bus_creds_add_more(c, mask, pid, 0);
767 _public_ int sd_bus_get_owner(
771 sd_bus_creds **creds) {
773 assert_return(bus, -EINVAL);
774 assert_return(name, -EINVAL);
775 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
776 assert_return(mask == 0 || creds, -EINVAL);
777 assert_return(!bus_pid_changed(bus), -ECHILD);
778 assert_return(service_name_is_valid(name), -EINVAL);
779 assert_return(bus->bus_client, -ENODATA);
781 if (!BUS_IS_OPEN(bus->state))
785 return bus_get_owner_kdbus(bus, name, mask, creds);
787 return bus_get_owner_dbus1(bus, name, mask, creds);
790 static int add_name_change_match(sd_bus *bus,
793 const char *old_owner,
794 const char *new_owner) {
796 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
797 int is_name_id = -1, r;
798 struct kdbus_item *item;
802 /* If we encounter a match that could match against
803 * NameOwnerChanged messages, then we need to create
804 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
805 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
806 * multiple if the match is underspecified.
808 * The NameOwnerChanged signals take three parameters with
809 * unique or well-known names, but only some forms actually
812 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
813 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
814 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
815 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
816 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
818 * For the latter two the two unique names must be identical.
823 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
828 if (!isempty(old_owner)) {
829 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
834 if (is_name_id > 0 && old_owner_id != name_id)
837 old_owner_id = KDBUS_MATCH_ID_ANY;
839 if (!isempty(new_owner)) {
840 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
845 if (is_name_id > 0 && new_owner_id != name_id)
848 new_owner_id = KDBUS_MATCH_ID_ANY;
850 if (is_name_id <= 0) {
851 struct kdbus_cmd_match *m;
854 /* If the name argument is missing or is a well-known
855 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
858 l = name ? strlen(name) + 1 : 0;
860 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
861 offsetof(struct kdbus_item, name_change) +
862 offsetof(struct kdbus_notify_name_change, name) +
865 m = alloca0_align(sz, 8);
871 offsetof(struct kdbus_item, name_change) +
872 offsetof(struct kdbus_notify_name_change, name) +
875 item->name_change.old_id.id = old_owner_id;
876 item->name_change.new_id.id = new_owner_id;
879 memcpy(item->name_change.name, name, l);
881 /* If the old name is unset or empty, then
882 * this can match against added names */
883 if (!old_owner || old_owner[0] == 0) {
884 item->type = KDBUS_ITEM_NAME_ADD;
886 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
891 /* If the new name is unset or empty, then
892 * this can match against removed names */
893 if (!new_owner || new_owner[0] == 0) {
894 item->type = KDBUS_ITEM_NAME_REMOVE;
896 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
901 /* The CHANGE match we need in either case, because
902 * what is reported as a name change by the kernel
903 * might just be an owner change between starter and
904 * normal clients. For userspace such a change should
905 * be considered a removal/addition, hence let's
906 * subscribe to this unconditionally. */
907 item->type = KDBUS_ITEM_NAME_CHANGE;
908 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
913 if (is_name_id != 0) {
914 struct kdbus_cmd_match *m;
917 /* If the name argument is missing or is a unique
918 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
921 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
922 offsetof(struct kdbus_item, id_change) +
923 sizeof(struct kdbus_notify_id_change));
925 m = alloca0_align(sz, 8);
931 offsetof(struct kdbus_item, id_change) +
932 sizeof(struct kdbus_notify_id_change);
933 item->id_change.id = name_id;
935 /* If the old name is unset or empty, then this can
936 * match against added ids */
937 if (!old_owner || old_owner[0] == 0) {
938 item->type = KDBUS_ITEM_ID_ADD;
940 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
945 /* If thew new name is unset or empty, then this can
946 * match against removed ids */
947 if (!new_owner || new_owner[0] == 0) {
948 item->type = KDBUS_ITEM_ID_REMOVE;
950 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
959 int bus_add_match_internal_kernel(
961 struct bus_match_component *components,
962 unsigned n_components,
965 struct kdbus_cmd_match *m;
966 struct kdbus_item *item;
969 const char *sender = NULL;
970 size_t sender_length = 0;
971 uint64_t src_id = KDBUS_MATCH_ID_ANY;
972 bool using_bloom = false;
974 bool matches_name_change = true;
975 const char *name_change_arg[3] = {};
980 bloom = alloca0(bus->bloom_size);
982 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
984 for (i = 0; i < n_components; i++) {
985 struct bus_match_component *c = &components[i];
989 case BUS_MATCH_SENDER:
990 if (!streq(c->value_str, "org.freedesktop.DBus"))
991 matches_name_change = false;
993 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
997 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
999 sender = c->value_str;
1000 sender_length = strlen(sender);
1001 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1006 case BUS_MATCH_MESSAGE_TYPE:
1007 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1008 matches_name_change = false;
1010 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1014 case BUS_MATCH_INTERFACE:
1015 if (!streq(c->value_str, "org.freedesktop.DBus"))
1016 matches_name_change = false;
1018 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1022 case BUS_MATCH_MEMBER:
1023 if (!streq(c->value_str, "NameOwnerChanged"))
1024 matches_name_change = false;
1026 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1030 case BUS_MATCH_PATH:
1031 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1032 matches_name_change = false;
1034 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1038 case BUS_MATCH_PATH_NAMESPACE:
1039 if (!streq(c->value_str, "/")) {
1040 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1045 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1046 char buf[sizeof("arg")-1 + 2 + 1];
1048 if (c->type - BUS_MATCH_ARG < 3)
1049 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1051 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1052 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1057 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1058 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1060 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1061 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1066 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1067 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1069 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1070 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1075 case BUS_MATCH_DESTINATION:
1076 /* The bloom filter does not include
1077 the destination, since it is only
1078 available for broadcast messages
1079 which do not carry a destination
1080 since they are undirected. */
1083 case BUS_MATCH_ROOT:
1084 case BUS_MATCH_VALUE:
1085 case BUS_MATCH_LEAF:
1086 case _BUS_MATCH_NODE_TYPE_MAX:
1087 case _BUS_MATCH_NODE_TYPE_INVALID:
1088 assert_not_reached("Invalid match type?");
1093 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1095 m = alloca0_align(sz, 8);
1101 if (src_id != KDBUS_MATCH_ID_ANY) {
1102 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1103 item->type = KDBUS_ITEM_ID;
1105 item = KDBUS_ITEM_NEXT(item);
1109 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1110 item->type = KDBUS_ITEM_BLOOM_MASK;
1111 memcpy(item->data64, bloom, bus->bloom_size);
1112 item = KDBUS_ITEM_NEXT(item);
1116 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1117 item->type = KDBUS_ITEM_NAME;
1118 memcpy(item->str, sender, sender_length + 1);
1121 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1125 if (matches_name_change) {
1127 /* If this match could theoretically match
1128 * NameOwnerChanged messages, we need to
1129 * install a second non-bloom filter explitly
1132 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1140 #define internal_match(bus, m) \
1141 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1142 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1145 static int bus_add_match_internal_dbus1(
1147 const char *match) {
1154 e = internal_match(bus, match);
1156 return sd_bus_call_method(
1158 "org.freedesktop.DBus",
1159 "/org/freedesktop/DBus",
1160 "org.freedesktop.DBus",
1168 int bus_add_match_internal(
1171 struct bus_match_component *components,
1172 unsigned n_components,
1178 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1180 return bus_add_match_internal_dbus1(bus, match);
1183 int bus_remove_match_internal_kernel(
1187 struct kdbus_cmd_match m;
1193 m.size = offsetof(struct kdbus_cmd_match, items);
1196 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1203 static int bus_remove_match_internal_dbus1(
1205 const char *match) {
1212 e = internal_match(bus, match);
1214 return sd_bus_call_method(
1216 "org.freedesktop.DBus",
1217 "/org/freedesktop/DBus",
1218 "org.freedesktop.DBus",
1226 int bus_remove_match_internal(
1234 return bus_remove_match_internal_kernel(bus, cookie);
1236 return bus_remove_match_internal_dbus1(bus, match);
1239 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1240 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1244 assert_return(bus, -EINVAL);
1245 assert_return(name, -EINVAL);
1246 assert_return(machine, -EINVAL);
1247 assert_return(!bus_pid_changed(bus), -ECHILD);
1248 assert_return(service_name_is_valid(name), -EINVAL);
1250 if (!BUS_IS_OPEN(bus->state))
1253 if (streq_ptr(name, bus->unique_name))
1254 return sd_id128_get_machine(machine);
1256 r = sd_bus_message_new_method_call(
1261 "org.freedesktop.DBus.Peer",
1266 r = sd_bus_message_set_auto_start(m, false);
1270 r = sd_bus_call(bus, m, 0, NULL, &reply);
1274 r = sd_bus_message_read(reply, "s", &mid);
1278 return sd_id128_from_string(mid, machine);