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"
37 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
40 assert_return(bus, -EINVAL);
41 assert_return(unique, -EINVAL);
42 assert_return(!bus_pid_changed(bus), -ECHILD);
44 r = bus_ensure_running(bus);
48 *unique = bus->unique_name;
52 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
53 struct kdbus_cmd_name *n;
61 size = offsetof(struct kdbus_cmd_name, name) + l + 1;
64 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
65 memcpy(n->name, name, l+1);
67 #ifdef HAVE_VALGRIND_MEMCHECK_H
68 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
71 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
75 if (n->flags & KDBUS_NAME_IN_QUEUE)
81 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
82 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
83 uint32_t ret, param = 0;
89 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
90 param |= BUS_NAME_ALLOW_REPLACEMENT;
91 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
92 param |= BUS_NAME_REPLACE_EXISTING;
93 if (!(flags & SD_BUS_NAME_QUEUE))
94 param |= BUS_NAME_DO_NOT_QUEUE;
96 r = sd_bus_call_method(
98 "org.freedesktop.DBus",
99 "/org/freedesktop/DBus",
100 "org.freedesktop.DBus",
110 r = sd_bus_message_read(reply, "u", &ret);
114 if (ret == BUS_NAME_ALREADY_OWNER)
116 else if (ret == BUS_NAME_EXISTS)
118 else if (ret == BUS_NAME_IN_QUEUE)
120 else if (ret == BUS_NAME_PRIMARY_OWNER)
126 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
127 assert_return(bus, -EINVAL);
128 assert_return(name, -EINVAL);
129 assert_return(bus->bus_client, -EINVAL);
130 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
131 assert_return(!bus_pid_changed(bus), -ECHILD);
132 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
133 assert_return(service_name_is_valid(name), -EINVAL);
134 assert_return(name[0] != ':', -EINVAL);
137 return bus_request_name_kernel(bus, name, flags);
139 return bus_request_name_dbus1(bus, name, flags);
142 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
143 struct kdbus_cmd_name *n;
151 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
152 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
153 memcpy(n->name, name, l+1);
155 #ifdef HAVE_VALGRIND_MEMCHECK_H
156 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
158 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
165 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
166 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
173 r = sd_bus_call_method(
175 "org.freedesktop.DBus",
176 "/org/freedesktop/DBus",
177 "org.freedesktop.DBus",
186 r = sd_bus_message_read(reply, "u", &ret);
189 if (ret == BUS_NAME_NON_EXISTENT)
191 if (ret == BUS_NAME_NOT_OWNER)
193 if (ret == BUS_NAME_RELEASED)
199 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
200 assert_return(bus, -EINVAL);
201 assert_return(name, -EINVAL);
202 assert_return(bus->bus_client, -EINVAL);
203 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
204 assert_return(!bus_pid_changed(bus), -ECHILD);
205 assert_return(service_name_is_valid(name), -EINVAL);
206 assert_return(name[0] != ':', -EINVAL);
209 return bus_release_name_kernel(bus, name);
211 return bus_release_name_dbus1(bus, name);
214 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
215 struct kdbus_cmd_name_list cmd = {};
216 struct kdbus_name_list *name_list;
217 struct kdbus_cmd_name *name;
218 uint64_t previous_id = 0;
221 /* Caller will free half-constructed list on failure... */
225 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
229 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
231 KDBUS_ITEM_FOREACH(name, name_list, names) {
233 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
236 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0)
245 previous_id = name->owner_id;
248 if (name->size > sizeof(*name) && service_name_is_valid(name->name)) {
249 r = strv_extend(x, name->name);
255 r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd.offset);
262 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
263 _cleanup_strv_free_ char **x = NULL, **y = NULL;
267 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
273 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
289 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
290 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
291 _cleanup_strv_free_ char **x = NULL, **y = NULL;
295 r = sd_bus_call_method(
297 "org.freedesktop.DBus",
298 "/org/freedesktop/DBus",
299 "org.freedesktop.DBus",
307 r = sd_bus_message_read_strv(reply, &x);
311 reply = sd_bus_message_unref(reply);
315 r = sd_bus_call_method(
317 "org.freedesktop.DBus",
318 "/org/freedesktop/DBus",
319 "org.freedesktop.DBus",
320 "ListActivatableNames",
327 r = sd_bus_message_read_strv(reply, &y);
343 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
344 assert_return(bus, -EINVAL);
345 assert_return(acquired || activatable, -EINVAL);
346 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
347 assert_return(!bus_pid_changed(bus), -ECHILD);
350 return bus_list_names_kernel(bus, acquired, activatable);
352 return bus_list_names_dbus1(bus, acquired, activatable);
355 static int bus_get_owner_kdbus(
359 sd_bus_creds **creds) {
361 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
362 struct kdbus_cmd_conn_info *cmd;
363 struct kdbus_conn_info *conn_info;
364 struct kdbus_item *item;
369 r = bus_kernel_parse_unique_name(name, &id);
373 size = offsetof(struct kdbus_cmd_conn_info, name);
377 size = offsetof(struct kdbus_cmd_conn_info, name) + strlen(name) + 1;
379 strcpy(cmd->name, name);
381 cmd->flags = KDBUS_ATTACH_NAMES;
384 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
388 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
390 /* Non-activated names are considered not available */
391 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
392 return name[0] == ':' ? -ENXIO : -ENOENT;
398 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
399 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
402 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
405 KDBUS_ITEM_FOREACH(item, conn_info, items) {
407 switch (item->type) {
409 case KDBUS_ITEM_CREDS:
410 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
413 c->uid = item->creds.uid;
414 c->pid = item->creds.pid;
415 c->gid = item->creds.gid;
419 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
420 c->tid = item->creds.tid;
421 c->mask |= SD_BUS_CREDS_TID;
424 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
425 c->pid_starttime = item->creds.starttime;
426 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
431 case KDBUS_ITEM_PID_COMM:
432 if (mask & SD_BUS_CREDS_COMM) {
433 c->comm = strdup(item->str);
439 c->mask |= SD_BUS_CREDS_COMM;
443 case KDBUS_ITEM_TID_COMM:
444 if (mask & SD_BUS_CREDS_TID_COMM) {
445 c->tid_comm = strdup(item->str);
451 c->mask |= SD_BUS_CREDS_TID_COMM;
456 if (mask & SD_BUS_CREDS_EXE) {
457 c->exe = strdup(item->str);
463 c->mask |= SD_BUS_CREDS_EXE;
467 case KDBUS_ITEM_CMDLINE:
468 if (mask & SD_BUS_CREDS_CMDLINE) {
469 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
470 c->cmdline = memdup(item->data, c->cmdline_size);
476 c->mask |= SD_BUS_CREDS_CMDLINE;
480 case KDBUS_ITEM_CGROUP:
481 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
482 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
483 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
486 c->cgroup = strdup(item->str);
496 case KDBUS_ITEM_CAPS:
497 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
498 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
501 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
502 c->capability = memdup(item->data, c->capability_size);
503 if (!c->capability) {
512 case KDBUS_ITEM_SECLABEL:
513 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
514 c->label = strdup(item->str);
520 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
524 case KDBUS_ITEM_AUDIT:
525 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
528 c->audit_session_id = item->audit.sessionid;
529 c->audit_login_uid = item->audit.loginuid;
534 case KDBUS_ITEM_NAME:
535 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
536 r = strv_extend(&c->well_known_names, item->name.name);
540 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
554 ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
558 static int bus_get_owner_dbus1(
562 sd_bus_creds **creds) {
564 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
565 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
566 const char *unique = NULL;
570 /* Only query the owner if the caller wants to know it or if
571 * the caller just wants to check whether a name exists */
572 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
573 r = sd_bus_call_method(
575 "org.freedesktop.DBus",
576 "/org/freedesktop/DBus",
577 "org.freedesktop.DBus",
586 r = sd_bus_message_read(reply_unique, "s", &unique);
596 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
597 c->unique_name = strdup(unique);
601 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
604 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
605 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
606 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|
607 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
608 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
611 r = sd_bus_call_method(
613 "org.freedesktop.DBus",
614 "/org/freedesktop/DBus",
615 "org.freedesktop.DBus",
616 "GetConnectionUnixProcessID",
620 unique ? unique : name);
624 r = sd_bus_message_read(reply, "u", &u);
629 if (mask & SD_BUS_CREDS_PID) {
631 c->mask |= SD_BUS_CREDS_PID;
634 reply = sd_bus_message_unref(reply);
637 if (mask & SD_BUS_CREDS_UID) {
640 r = sd_bus_call_method(
642 "org.freedesktop.DBus",
643 "/org/freedesktop/DBus",
644 "org.freedesktop.DBus",
645 "GetConnectionUnixUser",
649 unique ? unique : name);
653 r = sd_bus_message_read(reply, "u", &u);
658 c->mask |= SD_BUS_CREDS_UID;
660 reply = sd_bus_message_unref(reply);
663 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
667 r = sd_bus_call_method(
669 "org.freedesktop.DBus",
670 "/org/freedesktop/DBus",
671 "org.freedesktop.DBus",
672 "GetConnectionSELinuxSecurityContext",
676 unique ? unique : name);
680 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
684 c->label = strndup(p, sz);
688 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
691 r = bus_creds_add_more(c, mask, pid, 0);
704 _public_ int sd_bus_get_owner(
708 sd_bus_creds **creds) {
710 assert_return(bus, -EINVAL);
711 assert_return(name, -EINVAL);
712 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
713 assert_return(mask == 0 || creds, -EINVAL);
714 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
715 assert_return(!bus_pid_changed(bus), -ECHILD);
716 assert_return(service_name_is_valid(name), -EINVAL);
717 assert_return(bus->bus_client, -ENODATA);
720 return bus_get_owner_kdbus(bus, name, mask, creds);
722 return bus_get_owner_dbus1(bus, name, mask, creds);
725 static int add_name_change_match(sd_bus *bus,
728 const char *old_owner,
729 const char *new_owner) {
731 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
732 int is_name_id = -1, r;
733 struct kdbus_item *item;
737 /* If we encounter a match that could match against
738 * NameOwnerChanged messages, then we need to create
739 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
740 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
741 * multiple if the match is underspecified.
743 * The NameOwnerChanged signals take three parameters with
744 * unique or well-known names, but only some forms actually
747 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
748 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
749 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
750 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
751 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
753 * For the latter two the two unique names must be identical.
758 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
763 if (!isempty(old_owner)) {
764 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
769 if (is_name_id > 0 && old_owner_id != name_id)
772 old_owner_id = KDBUS_MATCH_ID_ANY;
774 if (!isempty(new_owner)) {
775 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
780 if (is_name_id > 0 && new_owner_id != name_id)
783 new_owner_id = KDBUS_MATCH_ID_ANY;
785 if (is_name_id <= 0) {
786 struct kdbus_cmd_match *m;
789 /* If the name argument is missing or is a well-known
790 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
793 l = name ? strlen(name) + 1 : 0;
795 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
796 offsetof(struct kdbus_item, name_change) +
797 offsetof(struct kdbus_notify_name_change, name) +
806 offsetof(struct kdbus_item, name_change) +
807 offsetof(struct kdbus_notify_name_change, name) +
810 item->name_change.old.id = old_owner_id;
811 item->name_change.new.id = new_owner_id;
814 memcpy(item->name_change.name, name, l);
816 /* If the old name is unset or empty, then
817 * this can match against added names */
818 if (!old_owner || old_owner[0] == 0) {
819 item->type = KDBUS_ITEM_NAME_ADD;
821 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
826 /* If the new name is unset or empty, then
827 * this can match against removed names */
828 if (!new_owner || new_owner[0] == 0) {
829 item->type = KDBUS_ITEM_NAME_REMOVE;
831 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
836 /* The CHANGE match we need in either case, because
837 * what is reported as a name change by the kernel
838 * might just be an owner change between starter and
839 * normal clients. For userspace such a change should
840 * be considered a removal/addition, hence let's
841 * subscribe to this unconditionally. */
842 item->type = KDBUS_ITEM_NAME_CHANGE;
843 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
848 if (is_name_id != 0) {
849 struct kdbus_cmd_match *m;
852 /* If the name argument is missing or is a unique
853 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
856 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
857 offsetof(struct kdbus_item, id_change) +
858 sizeof(struct kdbus_notify_id_change));
866 offsetof(struct kdbus_item, id_change) +
867 sizeof(struct kdbus_notify_id_change);
868 item->id_change.id = name_id;
870 /* If the old name is unset or empty, then this can
871 * match against added ids */
872 if (!old_owner || old_owner[0] == 0) {
873 item->type = KDBUS_ITEM_ID_ADD;
875 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
880 /* If thew new name is unset or empty, then this can
881 * match against removed ids */
882 if (!new_owner || new_owner[0] == 0) {
883 item->type = KDBUS_ITEM_ID_REMOVE;
885 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
894 int bus_add_match_internal_kernel(
897 struct bus_match_component *components,
898 unsigned n_components,
901 struct kdbus_cmd_match *m;
902 struct kdbus_item *item;
903 uint64_t bloom[BLOOM_SIZE/8];
905 const char *sender = NULL;
906 size_t sender_length = 0;
907 uint64_t src_id = KDBUS_MATCH_ID_ANY;
908 bool using_bloom = false;
910 bool matches_name_change = true;
911 const char *name_change_arg[3] = {};
918 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
920 for (i = 0; i < n_components; i++) {
921 struct bus_match_component *c = &components[i];
925 case BUS_MATCH_SENDER:
926 if (!streq(c->value_str, "org.freedesktop.DBus"))
927 matches_name_change = false;
929 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
933 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
935 sender = c->value_str;
936 sender_length = strlen(sender);
937 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
942 case BUS_MATCH_MESSAGE_TYPE:
943 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
944 matches_name_change = false;
946 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
950 case BUS_MATCH_INTERFACE:
951 if (!streq(c->value_str, "org.freedesktop.DBus"))
952 matches_name_change = false;
954 bloom_add_pair(bloom, "interface", c->value_str);
958 case BUS_MATCH_MEMBER:
959 if (!streq(c->value_str, "NameOwnerChanged"))
960 matches_name_change = false;
962 bloom_add_pair(bloom, "member", c->value_str);
967 if (!streq(c->value_str, "/org/freedesktop/DBus"))
968 matches_name_change = false;
970 bloom_add_pair(bloom, "path", c->value_str);
974 case BUS_MATCH_PATH_NAMESPACE:
975 if (!streq(c->value_str, "/")) {
976 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
981 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
982 char buf[sizeof("arg")-1 + 2 + 1];
984 if (c->type - BUS_MATCH_ARG < 3)
985 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
987 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
988 bloom_add_pair(bloom, buf, c->value_str);
993 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
994 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
996 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
997 bloom_add_pair(bloom, buf, c->value_str);
1002 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1003 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1005 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1006 bloom_add_pair(bloom, buf, c->value_str);
1011 case BUS_MATCH_DESTINATION:
1012 /* The bloom filter does not include
1013 the destination, since it is only
1014 available for broadcast messages
1015 which do not carry a destination
1016 since they are undirected. */
1019 case BUS_MATCH_ROOT:
1020 case BUS_MATCH_VALUE:
1021 case BUS_MATCH_LEAF:
1022 case _BUS_MATCH_NODE_TYPE_MAX:
1023 case _BUS_MATCH_NODE_TYPE_INVALID:
1024 assert_not_reached("Invalid match type?");
1029 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
1038 if (src_id != KDBUS_MATCH_ID_ANY) {
1039 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1040 item->type = KDBUS_ITEM_ID;
1042 item = KDBUS_ITEM_NEXT(item);
1046 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
1047 item->type = KDBUS_ITEM_BLOOM;
1048 memcpy(item->data64, bloom, BLOOM_SIZE);
1049 item = KDBUS_ITEM_NEXT(item);
1053 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1054 item->type = KDBUS_ITEM_NAME;
1055 memcpy(item->str, sender, sender_length + 1);
1058 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1062 if (matches_name_change) {
1064 /* If this match could theoretically match
1065 * NameOwnerChanged messages, we need to
1066 * install a second non-bloom filter explitly
1069 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1077 static int bus_add_match_internal_dbus1(
1079 const char *match) {
1084 return sd_bus_call_method(
1086 "org.freedesktop.DBus",
1087 "/org/freedesktop/DBus",
1088 "org.freedesktop.DBus",
1096 int bus_add_match_internal(
1099 struct bus_match_component *components,
1100 unsigned n_components,
1107 return bus_add_match_internal_kernel(bus, 0, components, n_components, cookie);
1109 return bus_add_match_internal_dbus1(bus, match);
1112 int bus_remove_match_internal_kernel(
1117 struct kdbus_cmd_match m;
1123 m.size = offsetof(struct kdbus_cmd_match, items);
1127 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1134 static int bus_remove_match_internal_dbus1(
1136 const char *match) {
1141 return sd_bus_call_method(
1143 "org.freedesktop.DBus",
1144 "/org/freedesktop/DBus",
1145 "org.freedesktop.DBus",
1153 int bus_remove_match_internal(
1162 return bus_remove_match_internal_kernel(bus, 0, cookie);
1164 return bus_remove_match_internal_dbus1(bus, match);
1167 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1168 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1172 assert_return(bus, -EINVAL);
1173 assert_return(name, -EINVAL);
1174 assert_return(machine, -EINVAL);
1175 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1176 assert_return(!bus_pid_changed(bus), -ECHILD);
1177 assert_return(service_name_is_valid(name), -EINVAL);
1179 if (streq_ptr(name, bus->unique_name))
1180 return sd_id128_get_machine(machine);
1182 r = sd_bus_message_new_method_call(
1186 "org.freedesktop.DBus.Peer",
1187 "GetMachineId", &m);
1191 r = sd_bus_message_set_no_auto_start(m, true);
1195 r = sd_bus_call(bus, m, 0, NULL, &reply);
1199 r = sd_bus_message_read(reply, "s", &mid);
1203 return sd_id128_from_string(mid, machine);