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, name) + l + 1;
65 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
66 memcpy(n->name, name, l+1);
68 #ifdef HAVE_VALGRIND_MEMCHECK_H
69 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
72 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
76 if (n->flags & KDBUS_NAME_IN_QUEUE)
82 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
83 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
84 uint32_t ret, param = 0;
90 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
91 param |= BUS_NAME_ALLOW_REPLACEMENT;
92 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
93 param |= BUS_NAME_REPLACE_EXISTING;
94 if (!(flags & SD_BUS_NAME_QUEUE))
95 param |= BUS_NAME_DO_NOT_QUEUE;
97 r = sd_bus_call_method(
99 "org.freedesktop.DBus",
100 "/org/freedesktop/DBus",
101 "org.freedesktop.DBus",
111 r = sd_bus_message_read(reply, "u", &ret);
115 if (ret == BUS_NAME_ALREADY_OWNER)
117 else if (ret == BUS_NAME_EXISTS)
119 else if (ret == BUS_NAME_IN_QUEUE)
121 else if (ret == BUS_NAME_PRIMARY_OWNER)
127 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
128 assert_return(bus, -EINVAL);
129 assert_return(name, -EINVAL);
130 assert_return(bus->bus_client, -EINVAL);
131 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
132 assert_return(!bus_pid_changed(bus), -ECHILD);
133 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
134 assert_return(service_name_is_valid(name), -EINVAL);
135 assert_return(name[0] != ':', -EINVAL);
138 return bus_request_name_kernel(bus, name, flags);
140 return bus_request_name_dbus1(bus, name, flags);
143 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
144 struct kdbus_cmd_name *n;
152 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
153 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
154 memcpy(n->name, name, l+1);
156 #ifdef HAVE_VALGRIND_MEMCHECK_H
157 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
159 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
166 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
167 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
174 r = sd_bus_call_method(
176 "org.freedesktop.DBus",
177 "/org/freedesktop/DBus",
178 "org.freedesktop.DBus",
187 r = sd_bus_message_read(reply, "u", &ret);
190 if (ret == BUS_NAME_NON_EXISTENT)
192 if (ret == BUS_NAME_NOT_OWNER)
194 if (ret == BUS_NAME_RELEASED)
200 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
201 assert_return(bus, -EINVAL);
202 assert_return(name, -EINVAL);
203 assert_return(bus->bus_client, -EINVAL);
204 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
205 assert_return(!bus_pid_changed(bus), -ECHILD);
206 assert_return(service_name_is_valid(name), -EINVAL);
207 assert_return(name[0] != ':', -EINVAL);
210 return bus_release_name_kernel(bus, name);
212 return bus_release_name_dbus1(bus, name);
215 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
216 struct kdbus_cmd_name_list cmd = {};
217 struct kdbus_name_list *name_list;
218 struct kdbus_cmd_name *name;
219 uint64_t previous_id = 0;
222 /* Caller will free half-constructed list on failure... */
226 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
230 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
232 KDBUS_ITEM_FOREACH(name, name_list, names) {
234 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
237 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0)
246 previous_id = name->owner_id;
249 if (name->size > sizeof(*name) && service_name_is_valid(name->name)) {
250 r = strv_extend(x, name->name);
256 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd.offset);
263 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
264 _cleanup_strv_free_ char **x = NULL, **y = NULL;
268 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
274 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
290 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
291 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
292 _cleanup_strv_free_ char **x = NULL, **y = NULL;
296 r = sd_bus_call_method(
298 "org.freedesktop.DBus",
299 "/org/freedesktop/DBus",
300 "org.freedesktop.DBus",
308 r = sd_bus_message_read_strv(reply, &x);
312 reply = sd_bus_message_unref(reply);
316 r = sd_bus_call_method(
318 "org.freedesktop.DBus",
319 "/org/freedesktop/DBus",
320 "org.freedesktop.DBus",
321 "ListActivatableNames",
328 r = sd_bus_message_read_strv(reply, &y);
344 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
345 assert_return(bus, -EINVAL);
346 assert_return(acquired || activatable, -EINVAL);
347 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
348 assert_return(!bus_pid_changed(bus), -ECHILD);
351 return bus_list_names_kernel(bus, acquired, activatable);
353 return bus_list_names_dbus1(bus, acquired, activatable);
356 static int bus_get_owner_kdbus(
360 sd_bus_creds **creds) {
362 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
363 struct kdbus_cmd_conn_info *cmd;
364 struct kdbus_conn_info *conn_info;
365 struct kdbus_item *item;
370 r = bus_kernel_parse_unique_name(name, &id);
374 size = offsetof(struct kdbus_cmd_conn_info, name);
378 size = offsetof(struct kdbus_cmd_conn_info, name) + strlen(name) + 1;
380 strcpy(cmd->name, name);
382 cmd->flags = KDBUS_ATTACH_NAMES;
385 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
389 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
391 /* Non-activated names are considered not available */
392 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
393 return name[0] == ':' ? -ENXIO : -ENOENT;
399 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
400 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
403 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
406 KDBUS_ITEM_FOREACH(item, conn_info, items) {
408 switch (item->type) {
410 case KDBUS_ITEM_CREDS:
411 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
414 c->uid = (uid_t) item->creds.uid;
415 c->pid = (pid_t) item->creds.pid;
416 c->gid = (gid_t) item->creds.gid;
420 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
421 c->tid = (pid_t) item->creds.tid;
422 c->mask |= SD_BUS_CREDS_TID;
425 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
426 c->pid_starttime = item->creds.starttime;
427 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
432 case KDBUS_ITEM_PID_COMM:
433 if (mask & SD_BUS_CREDS_COMM) {
434 c->comm = strdup(item->str);
440 c->mask |= SD_BUS_CREDS_COMM;
444 case KDBUS_ITEM_TID_COMM:
445 if (mask & SD_BUS_CREDS_TID_COMM) {
446 c->tid_comm = strdup(item->str);
452 c->mask |= SD_BUS_CREDS_TID_COMM;
457 if (mask & SD_BUS_CREDS_EXE) {
458 c->exe = strdup(item->str);
464 c->mask |= SD_BUS_CREDS_EXE;
468 case KDBUS_ITEM_CMDLINE:
469 if (mask & SD_BUS_CREDS_CMDLINE) {
470 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
471 c->cmdline = memdup(item->data, c->cmdline_size);
477 c->mask |= SD_BUS_CREDS_CMDLINE;
481 case KDBUS_ITEM_CGROUP:
482 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
483 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
484 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
487 c->cgroup = strdup(item->str);
493 if (!bus->cgroup_root) {
494 r = cg_get_root_path(&bus->cgroup_root);
499 c->cgroup_root = strdup(bus->cgroup_root);
500 if (!c->cgroup_root) {
509 case KDBUS_ITEM_CAPS:
510 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
511 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
514 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
515 c->capability = memdup(item->data, c->capability_size);
516 if (!c->capability) {
525 case KDBUS_ITEM_SECLABEL:
526 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
527 c->label = strdup(item->str);
533 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
537 case KDBUS_ITEM_AUDIT:
538 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
541 c->audit_session_id = item->audit.sessionid;
542 c->audit_login_uid = item->audit.loginuid;
547 case KDBUS_ITEM_NAME:
548 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
549 r = strv_extend(&c->well_known_names, item->name.name);
553 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
567 ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
571 static int bus_get_owner_dbus1(
575 sd_bus_creds **creds) {
577 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
578 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
579 const char *unique = NULL;
583 /* Only query the owner if the caller wants to know it or if
584 * the caller just wants to check whether a name exists */
585 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
586 r = sd_bus_call_method(
588 "org.freedesktop.DBus",
589 "/org/freedesktop/DBus",
590 "org.freedesktop.DBus",
599 r = sd_bus_message_read(reply_unique, "s", &unique);
609 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
610 c->unique_name = strdup(unique);
614 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
617 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
618 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
619 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|
620 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
621 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
624 r = sd_bus_call_method(
626 "org.freedesktop.DBus",
627 "/org/freedesktop/DBus",
628 "org.freedesktop.DBus",
629 "GetConnectionUnixProcessID",
633 unique ? unique : name);
637 r = sd_bus_message_read(reply, "u", &u);
642 if (mask & SD_BUS_CREDS_PID) {
644 c->mask |= SD_BUS_CREDS_PID;
647 reply = sd_bus_message_unref(reply);
650 if (mask & SD_BUS_CREDS_UID) {
653 r = sd_bus_call_method(
655 "org.freedesktop.DBus",
656 "/org/freedesktop/DBus",
657 "org.freedesktop.DBus",
658 "GetConnectionUnixUser",
662 unique ? unique : name);
666 r = sd_bus_message_read(reply, "u", &u);
671 c->mask |= SD_BUS_CREDS_UID;
673 reply = sd_bus_message_unref(reply);
676 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
680 r = sd_bus_call_method(
682 "org.freedesktop.DBus",
683 "/org/freedesktop/DBus",
684 "org.freedesktop.DBus",
685 "GetConnectionSELinuxSecurityContext",
689 unique ? unique : name);
693 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
697 c->label = strndup(p, sz);
701 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
704 r = bus_creds_add_more(c, mask, pid, 0);
717 _public_ int sd_bus_get_owner(
721 sd_bus_creds **creds) {
723 assert_return(bus, -EINVAL);
724 assert_return(name, -EINVAL);
725 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
726 assert_return(mask == 0 || creds, -EINVAL);
727 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
728 assert_return(!bus_pid_changed(bus), -ECHILD);
729 assert_return(service_name_is_valid(name), -EINVAL);
730 assert_return(bus->bus_client, -ENODATA);
733 return bus_get_owner_kdbus(bus, name, mask, creds);
735 return bus_get_owner_dbus1(bus, name, mask, creds);
738 static int add_name_change_match(sd_bus *bus,
741 const char *old_owner,
742 const char *new_owner) {
744 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
745 int is_name_id = -1, r;
746 struct kdbus_item *item;
750 /* If we encounter a match that could match against
751 * NameOwnerChanged messages, then we need to create
752 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
753 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
754 * multiple if the match is underspecified.
756 * The NameOwnerChanged signals take three parameters with
757 * unique or well-known names, but only some forms actually
760 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
761 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
762 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
763 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
764 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
766 * For the latter two the two unique names must be identical.
771 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
776 if (!isempty(old_owner)) {
777 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
782 if (is_name_id > 0 && old_owner_id != name_id)
785 old_owner_id = KDBUS_MATCH_ID_ANY;
787 if (!isempty(new_owner)) {
788 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
793 if (is_name_id > 0 && new_owner_id != name_id)
796 new_owner_id = KDBUS_MATCH_ID_ANY;
798 if (is_name_id <= 0) {
799 struct kdbus_cmd_match *m;
802 /* If the name argument is missing or is a well-known
803 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
806 l = name ? strlen(name) + 1 : 0;
808 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
809 offsetof(struct kdbus_item, name_change) +
810 offsetof(struct kdbus_notify_name_change, name) +
819 offsetof(struct kdbus_item, name_change) +
820 offsetof(struct kdbus_notify_name_change, name) +
823 item->name_change.old.id = old_owner_id;
824 item->name_change.new.id = new_owner_id;
827 memcpy(item->name_change.name, name, l);
829 /* If the old name is unset or empty, then
830 * this can match against added names */
831 if (!old_owner || old_owner[0] == 0) {
832 item->type = KDBUS_ITEM_NAME_ADD;
834 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
839 /* If the new name is unset or empty, then
840 * this can match against removed names */
841 if (!new_owner || new_owner[0] == 0) {
842 item->type = KDBUS_ITEM_NAME_REMOVE;
844 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
849 /* The CHANGE match we need in either case, because
850 * what is reported as a name change by the kernel
851 * might just be an owner change between starter and
852 * normal clients. For userspace such a change should
853 * be considered a removal/addition, hence let's
854 * subscribe to this unconditionally. */
855 item->type = KDBUS_ITEM_NAME_CHANGE;
856 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
861 if (is_name_id != 0) {
862 struct kdbus_cmd_match *m;
865 /* If the name argument is missing or is a unique
866 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
869 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
870 offsetof(struct kdbus_item, id_change) +
871 sizeof(struct kdbus_notify_id_change));
879 offsetof(struct kdbus_item, id_change) +
880 sizeof(struct kdbus_notify_id_change);
881 item->id_change.id = name_id;
883 /* If the old name is unset or empty, then this can
884 * match against added ids */
885 if (!old_owner || old_owner[0] == 0) {
886 item->type = KDBUS_ITEM_ID_ADD;
888 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
893 /* If thew new name is unset or empty, then this can
894 * match against removed ids */
895 if (!new_owner || new_owner[0] == 0) {
896 item->type = KDBUS_ITEM_ID_REMOVE;
898 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
907 int bus_add_match_internal_kernel(
910 struct bus_match_component *components,
911 unsigned n_components,
914 struct kdbus_cmd_match *m;
915 struct kdbus_item *item;
916 uint64_t bloom[BLOOM_SIZE/8];
918 const char *sender = NULL;
919 size_t sender_length = 0;
920 uint64_t src_id = KDBUS_MATCH_ID_ANY;
921 bool using_bloom = false;
923 bool matches_name_change = true;
924 const char *name_change_arg[3] = {};
931 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
933 for (i = 0; i < n_components; i++) {
934 struct bus_match_component *c = &components[i];
938 case BUS_MATCH_SENDER:
939 if (!streq(c->value_str, "org.freedesktop.DBus"))
940 matches_name_change = false;
942 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
946 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
948 sender = c->value_str;
949 sender_length = strlen(sender);
950 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
955 case BUS_MATCH_MESSAGE_TYPE:
956 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
957 matches_name_change = false;
959 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
963 case BUS_MATCH_INTERFACE:
964 if (!streq(c->value_str, "org.freedesktop.DBus"))
965 matches_name_change = false;
967 bloom_add_pair(bloom, "interface", c->value_str);
971 case BUS_MATCH_MEMBER:
972 if (!streq(c->value_str, "NameOwnerChanged"))
973 matches_name_change = false;
975 bloom_add_pair(bloom, "member", c->value_str);
980 if (!streq(c->value_str, "/org/freedesktop/DBus"))
981 matches_name_change = false;
983 bloom_add_pair(bloom, "path", c->value_str);
987 case BUS_MATCH_PATH_NAMESPACE:
988 if (!streq(c->value_str, "/")) {
989 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
994 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
995 char buf[sizeof("arg")-1 + 2 + 1];
997 if (c->type - BUS_MATCH_ARG < 3)
998 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1000 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1001 bloom_add_pair(bloom, buf, c->value_str);
1006 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1007 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1009 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1010 bloom_add_pair(bloom, buf, c->value_str);
1015 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1016 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1018 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1019 bloom_add_pair(bloom, buf, c->value_str);
1024 case BUS_MATCH_DESTINATION:
1025 /* The bloom filter does not include
1026 the destination, since it is only
1027 available for broadcast messages
1028 which do not carry a destination
1029 since they are undirected. */
1032 case BUS_MATCH_ROOT:
1033 case BUS_MATCH_VALUE:
1034 case BUS_MATCH_LEAF:
1035 case _BUS_MATCH_NODE_TYPE_MAX:
1036 case _BUS_MATCH_NODE_TYPE_INVALID:
1037 assert_not_reached("Invalid match type?");
1042 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
1051 if (src_id != KDBUS_MATCH_ID_ANY) {
1052 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1053 item->type = KDBUS_ITEM_ID;
1055 item = KDBUS_ITEM_NEXT(item);
1059 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
1060 item->type = KDBUS_ITEM_BLOOM;
1061 memcpy(item->data64, bloom, BLOOM_SIZE);
1062 item = KDBUS_ITEM_NEXT(item);
1066 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1067 item->type = KDBUS_ITEM_NAME;
1068 memcpy(item->str, sender, sender_length + 1);
1071 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1075 if (matches_name_change) {
1077 /* If this match could theoretically match
1078 * NameOwnerChanged messages, we need to
1079 * install a second non-bloom filter explitly
1082 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1090 static int bus_add_match_internal_dbus1(
1092 const char *match) {
1097 return sd_bus_call_method(
1099 "org.freedesktop.DBus",
1100 "/org/freedesktop/DBus",
1101 "org.freedesktop.DBus",
1109 int bus_add_match_internal(
1112 struct bus_match_component *components,
1113 unsigned n_components,
1120 return bus_add_match_internal_kernel(bus, 0, components, n_components, cookie);
1122 return bus_add_match_internal_dbus1(bus, match);
1125 int bus_remove_match_internal_kernel(
1130 struct kdbus_cmd_match m;
1136 m.size = offsetof(struct kdbus_cmd_match, items);
1140 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1147 static int bus_remove_match_internal_dbus1(
1149 const char *match) {
1154 return sd_bus_call_method(
1156 "org.freedesktop.DBus",
1157 "/org/freedesktop/DBus",
1158 "org.freedesktop.DBus",
1166 int bus_remove_match_internal(
1175 return bus_remove_match_internal_kernel(bus, 0, cookie);
1177 return bus_remove_match_internal_dbus1(bus, match);
1180 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1181 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1185 assert_return(bus, -EINVAL);
1186 assert_return(name, -EINVAL);
1187 assert_return(machine, -EINVAL);
1188 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1189 assert_return(!bus_pid_changed(bus), -ECHILD);
1190 assert_return(service_name_is_valid(name), -EINVAL);
1192 if (streq_ptr(name, bus->unique_name))
1193 return sd_id128_get_machine(machine);
1195 r = sd_bus_message_new_method_call(
1199 "org.freedesktop.DBus.Peer",
1200 "GetMachineId", &m);
1204 r = sd_bus_message_set_no_auto_start(m, true);
1208 r = sd_bus_call(bus, m, 0, NULL, &reply);
1212 r = sd_bus_message_read(reply, "s", &mid);
1216 return sd_id128_from_string(mid, machine);