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_name_info *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) {
273 r = strv_consume(x, n);
277 previous_id = name->owner_id;
280 KDBUS_ITEM_FOREACH(item, name, items)
281 if (item->type == KDBUS_ITEM_NAME)
282 entry_name = item->str;
284 if (entry_name && service_name_is_valid(entry_name)) {
285 r = strv_extend(x, entry_name);
296 kernel_cmd_free(bus, cmd.offset);
300 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
301 _cleanup_strv_free_ char **x = NULL, **y = NULL;
305 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
311 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
327 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
328 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
329 _cleanup_strv_free_ char **x = NULL, **y = NULL;
333 r = sd_bus_call_method(
335 "org.freedesktop.DBus",
336 "/org/freedesktop/DBus",
337 "org.freedesktop.DBus",
345 r = sd_bus_message_read_strv(reply, &x);
349 reply = sd_bus_message_unref(reply);
353 r = sd_bus_call_method(
355 "org.freedesktop.DBus",
356 "/org/freedesktop/DBus",
357 "org.freedesktop.DBus",
358 "ListActivatableNames",
365 r = sd_bus_message_read_strv(reply, &y);
381 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
382 assert_return(bus, -EINVAL);
383 assert_return(acquired || activatable, -EINVAL);
384 assert_return(!bus_pid_changed(bus), -ECHILD);
386 if (!BUS_IS_OPEN(bus->state))
390 return bus_list_names_kernel(bus, acquired, activatable);
392 return bus_list_names_dbus1(bus, acquired, activatable);
395 static int bus_populate_creds_from_items(sd_bus *bus,
396 struct kdbus_info *info,
400 struct kdbus_item *item;
404 KDBUS_ITEM_FOREACH(item, info, items) {
406 switch (item->type) {
408 case KDBUS_ITEM_CREDS:
409 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
412 c->uid = (uid_t) item->creds.uid;
413 c->pid = (pid_t) item->creds.pid;
414 c->gid = (gid_t) item->creds.gid;
418 if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
419 c->tid = (pid_t) item->creds.tid;
420 c->mask |= SD_BUS_CREDS_TID;
423 if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
424 c->pid_starttime = item->creds.starttime;
425 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
430 case KDBUS_ITEM_PID_COMM:
431 if (mask & SD_BUS_CREDS_COMM) {
432 c->comm = strdup(item->str);
436 c->mask |= SD_BUS_CREDS_COMM;
440 case KDBUS_ITEM_TID_COMM:
441 if (mask & SD_BUS_CREDS_TID_COMM) {
442 c->tid_comm = strdup(item->str);
446 c->mask |= SD_BUS_CREDS_TID_COMM;
451 if (mask & SD_BUS_CREDS_EXE) {
452 c->exe = strdup(item->str);
456 c->mask |= SD_BUS_CREDS_EXE;
460 case KDBUS_ITEM_CMDLINE:
461 if (mask & SD_BUS_CREDS_CMDLINE) {
462 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
463 c->cmdline = memdup(item->data, c->cmdline_size);
467 c->mask |= SD_BUS_CREDS_CMDLINE;
471 case KDBUS_ITEM_CGROUP:
472 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
473 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
474 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
477 c->cgroup = strdup(item->str);
481 r = bus_get_root_path(bus);
485 c->cgroup_root = strdup(bus->cgroup_root);
493 case KDBUS_ITEM_CAPS:
494 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
495 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
498 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
499 c->capability = memdup(item->data, c->capability_size);
507 case KDBUS_ITEM_SECLABEL:
508 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
509 c->label = strdup(item->str);
513 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
517 case KDBUS_ITEM_AUDIT:
518 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
521 c->audit_session_id = item->audit.sessionid;
522 c->audit_login_uid = item->audit.loginuid;
527 case KDBUS_ITEM_NAME:
528 if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
529 r = strv_extend(&c->well_known_names, item->name.name);
533 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
537 case KDBUS_ITEM_CONN_NAME:
538 if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
539 c->conn_name = strdup(item->str);
543 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
552 static int bus_get_name_creds_kdbus(
556 sd_bus_creds **creds) {
558 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
559 struct kdbus_cmd_info *cmd;
560 struct kdbus_info *conn_info;
565 r = bus_kernel_parse_unique_name(name, &id);
569 size = offsetof(struct kdbus_cmd_info, items);
570 cmd = alloca0_align(size, 8);
573 l = strlen(name) + 1;
574 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
575 cmd = alloca0_align(size, 8);
576 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
577 cmd->items[0].type = KDBUS_ITEM_NAME;
578 memcpy(cmd->items[0].str, name, l);
582 kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
584 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
588 conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
590 /* Non-activated names are considered not available */
591 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
605 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
606 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
611 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
614 r = bus_populate_creds_from_items(bus, conn_info, mask, c);
626 kernel_cmd_free(bus, cmd->offset);
630 static int bus_get_name_creds_dbus1(
634 sd_bus_creds **creds) {
636 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
637 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
638 const char *unique = NULL;
642 /* Only query the owner if the caller wants to know it or if
643 * the caller just wants to check whether a name exists */
644 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
645 r = sd_bus_call_method(
647 "org.freedesktop.DBus",
648 "/org/freedesktop/DBus",
649 "org.freedesktop.DBus",
658 r = sd_bus_message_read(reply_unique, "s", &unique);
668 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
669 c->unique_name = strdup(unique);
673 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
676 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
677 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
678 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|
679 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
680 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
683 r = sd_bus_call_method(
685 "org.freedesktop.DBus",
686 "/org/freedesktop/DBus",
687 "org.freedesktop.DBus",
688 "GetConnectionUnixProcessID",
692 unique ? unique : name);
696 r = sd_bus_message_read(reply, "u", &u);
701 if (mask & SD_BUS_CREDS_PID) {
703 c->mask |= SD_BUS_CREDS_PID;
706 reply = sd_bus_message_unref(reply);
709 if (mask & SD_BUS_CREDS_UID) {
712 r = sd_bus_call_method(
714 "org.freedesktop.DBus",
715 "/org/freedesktop/DBus",
716 "org.freedesktop.DBus",
717 "GetConnectionUnixUser",
721 unique ? unique : name);
725 r = sd_bus_message_read(reply, "u", &u);
730 c->mask |= SD_BUS_CREDS_UID;
732 reply = sd_bus_message_unref(reply);
735 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
736 const void *p = NULL;
739 r = sd_bus_call_method(
741 "org.freedesktop.DBus",
742 "/org/freedesktop/DBus",
743 "org.freedesktop.DBus",
744 "GetConnectionSELinuxSecurityContext",
748 unique ? unique : name);
752 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
756 c->label = strndup(p, sz);
760 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
763 r = bus_creds_add_more(c, mask, pid, 0);
776 _public_ int sd_bus_get_name_creds(
780 sd_bus_creds **creds) {
782 assert_return(bus, -EINVAL);
783 assert_return(name, -EINVAL);
784 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
785 assert_return(mask == 0 || creds, -EINVAL);
786 assert_return(!bus_pid_changed(bus), -ECHILD);
787 assert_return(service_name_is_valid(name), -EINVAL);
788 assert_return(bus->bus_client, -ENODATA);
790 if (!BUS_IS_OPEN(bus->state))
794 return bus_get_name_creds_kdbus(bus, name, mask, creds);
796 return bus_get_name_creds_dbus1(bus, name, mask, creds);
799 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
800 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
804 assert_return(bus, -EINVAL);
805 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
806 assert_return(ret, -EINVAL);
807 assert_return(!bus_pid_changed(bus), -ECHILD);
809 if (!BUS_IS_OPEN(bus->state))
812 if (!bus->ucred_valid && !isempty(bus->label))
819 if (bus->ucred_valid) {
820 pid = c->pid = bus->ucred.pid;
821 c->uid = bus->ucred.uid;
822 c->gid = bus->ucred.gid;
824 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
827 if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
828 c->label = strdup(bus->label);
830 sd_bus_creds_unref(c);
834 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
837 if (bus->is_kernel) {
838 struct kdbus_cmd_info cmd = {};
839 struct kdbus_info *creator_info;
841 cmd.size = sizeof(cmd);
842 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
846 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
848 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
849 kernel_cmd_free(bus, cmd.offset);
854 r = bus_creds_add_more(c, mask, pid, 0);
856 sd_bus_creds_unref(c);
865 static int add_name_change_match(sd_bus *bus,
868 const char *old_owner,
869 const char *new_owner) {
871 uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
872 int is_name_id = -1, r;
873 struct kdbus_item *item;
877 /* If we encounter a match that could match against
878 * NameOwnerChanged messages, then we need to create
879 * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
880 * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
881 * multiple if the match is underspecified.
883 * The NameOwnerChanged signals take three parameters with
884 * unique or well-known names, but only some forms actually
887 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
888 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
889 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
890 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
891 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
893 * For the latter two the two unique names must be identical.
898 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
903 if (!isempty(old_owner)) {
904 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
909 if (is_name_id > 0 && old_owner_id != name_id)
912 old_owner_id = KDBUS_MATCH_ID_ANY;
914 if (!isempty(new_owner)) {
915 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
920 if (is_name_id > 0 && new_owner_id != name_id)
923 new_owner_id = KDBUS_MATCH_ID_ANY;
925 if (is_name_id <= 0) {
926 struct kdbus_cmd_match *m;
929 /* If the name argument is missing or is a well-known
930 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
933 l = name ? strlen(name) + 1 : 0;
935 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
936 offsetof(struct kdbus_item, name_change) +
937 offsetof(struct kdbus_notify_name_change, name) +
940 m = alloca0_align(sz, 8);
946 offsetof(struct kdbus_item, name_change) +
947 offsetof(struct kdbus_notify_name_change, name) +
950 item->name_change.old_id.id = old_owner_id;
951 item->name_change.new_id.id = new_owner_id;
954 memcpy(item->name_change.name, name, l);
956 /* If the old name is unset or empty, then
957 * this can match against added names */
958 if (!old_owner || old_owner[0] == 0) {
959 item->type = KDBUS_ITEM_NAME_ADD;
961 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
966 /* If the new name is unset or empty, then
967 * this can match against removed names */
968 if (!new_owner || new_owner[0] == 0) {
969 item->type = KDBUS_ITEM_NAME_REMOVE;
971 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
976 /* The CHANGE match we need in either case, because
977 * what is reported as a name change by the kernel
978 * might just be an owner change between starter and
979 * normal clients. For userspace such a change should
980 * be considered a removal/addition, hence let's
981 * subscribe to this unconditionally. */
982 item->type = KDBUS_ITEM_NAME_CHANGE;
983 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
988 if (is_name_id != 0) {
989 struct kdbus_cmd_match *m;
992 /* If the name argument is missing or is a unique
993 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
996 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
997 offsetof(struct kdbus_item, id_change) +
998 sizeof(struct kdbus_notify_id_change));
1000 m = alloca0_align(sz, 8);
1006 offsetof(struct kdbus_item, id_change) +
1007 sizeof(struct kdbus_notify_id_change);
1008 item->id_change.id = name_id;
1010 /* If the old name is unset or empty, then this can
1011 * match against added ids */
1012 if (!old_owner || old_owner[0] == 0) {
1013 item->type = KDBUS_ITEM_ID_ADD;
1015 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1020 /* If thew new name is unset or empty, then this can
1021 * match against removed ids */
1022 if (!new_owner || new_owner[0] == 0) {
1023 item->type = KDBUS_ITEM_ID_REMOVE;
1025 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1034 int bus_add_match_internal_kernel(
1036 struct bus_match_component *components,
1037 unsigned n_components,
1040 struct kdbus_cmd_match *m;
1041 struct kdbus_item *item;
1044 const char *sender = NULL;
1045 size_t sender_length = 0;
1046 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1047 bool using_bloom = false;
1049 bool matches_name_change = true;
1050 const char *name_change_arg[3] = {};
1055 bloom = alloca0(bus->bloom_size);
1057 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1059 for (i = 0; i < n_components; i++) {
1060 struct bus_match_component *c = &components[i];
1064 case BUS_MATCH_SENDER:
1065 if (!streq(c->value_str, "org.freedesktop.DBus"))
1066 matches_name_change = false;
1068 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1072 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1074 sender = c->value_str;
1075 sender_length = strlen(sender);
1076 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1081 case BUS_MATCH_MESSAGE_TYPE:
1082 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1083 matches_name_change = false;
1085 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1089 case BUS_MATCH_INTERFACE:
1090 if (!streq(c->value_str, "org.freedesktop.DBus"))
1091 matches_name_change = false;
1093 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1097 case BUS_MATCH_MEMBER:
1098 if (!streq(c->value_str, "NameOwnerChanged"))
1099 matches_name_change = false;
1101 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1105 case BUS_MATCH_PATH:
1106 if (!streq(c->value_str, "/org/freedesktop/DBus"))
1107 matches_name_change = false;
1109 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1113 case BUS_MATCH_PATH_NAMESPACE:
1114 if (!streq(c->value_str, "/")) {
1115 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1120 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1121 char buf[sizeof("arg")-1 + 2 + 1];
1123 if (c->type - BUS_MATCH_ARG < 3)
1124 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1126 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1127 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1132 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1133 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1135 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1136 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1141 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1142 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1144 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1145 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1150 case BUS_MATCH_DESTINATION:
1151 /* The bloom filter does not include
1152 the destination, since it is only
1153 available for broadcast messages
1154 which do not carry a destination
1155 since they are undirected. */
1158 case BUS_MATCH_ROOT:
1159 case BUS_MATCH_VALUE:
1160 case BUS_MATCH_LEAF:
1161 case _BUS_MATCH_NODE_TYPE_MAX:
1162 case _BUS_MATCH_NODE_TYPE_INVALID:
1163 assert_not_reached("Invalid match type?");
1168 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1170 m = alloca0_align(sz, 8);
1176 if (src_id != KDBUS_MATCH_ID_ANY) {
1177 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1178 item->type = KDBUS_ITEM_ID;
1180 item = KDBUS_ITEM_NEXT(item);
1184 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1185 item->type = KDBUS_ITEM_BLOOM_MASK;
1186 memcpy(item->data64, bloom, bus->bloom_size);
1187 item = KDBUS_ITEM_NEXT(item);
1191 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1192 item->type = KDBUS_ITEM_NAME;
1193 memcpy(item->str, sender, sender_length + 1);
1196 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1200 if (matches_name_change) {
1202 /* If this match could theoretically match
1203 * NameOwnerChanged messages, we need to
1204 * install a second non-bloom filter explitly
1207 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1215 #define internal_match(bus, m) \
1216 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
1217 ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1220 static int bus_add_match_internal_dbus1(
1222 const char *match) {
1229 e = internal_match(bus, match);
1231 return sd_bus_call_method(
1233 "org.freedesktop.DBus",
1234 "/org/freedesktop/DBus",
1235 "org.freedesktop.DBus",
1243 int bus_add_match_internal(
1246 struct bus_match_component *components,
1247 unsigned n_components,
1253 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1255 return bus_add_match_internal_dbus1(bus, match);
1258 int bus_remove_match_internal_kernel(
1262 struct kdbus_cmd_match m;
1268 m.size = offsetof(struct kdbus_cmd_match, items);
1271 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1278 static int bus_remove_match_internal_dbus1(
1280 const char *match) {
1287 e = internal_match(bus, match);
1289 return sd_bus_call_method(
1291 "org.freedesktop.DBus",
1292 "/org/freedesktop/DBus",
1293 "org.freedesktop.DBus",
1301 int bus_remove_match_internal(
1309 return bus_remove_match_internal_kernel(bus, cookie);
1311 return bus_remove_match_internal_dbus1(bus, match);
1314 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1315 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1319 assert_return(bus, -EINVAL);
1320 assert_return(name, -EINVAL);
1321 assert_return(machine, -EINVAL);
1322 assert_return(!bus_pid_changed(bus), -ECHILD);
1323 assert_return(service_name_is_valid(name), -EINVAL);
1325 if (!BUS_IS_OPEN(bus->state))
1328 if (streq_ptr(name, bus->unique_name))
1329 return sd_id128_get_machine(machine);
1331 r = sd_bus_message_new_method_call(
1336 "org.freedesktop.DBus.Peer",
1341 r = sd_bus_message_set_auto_start(m, false);
1345 r = sd_bus_call(bus, m, 0, NULL, &reply);
1349 r = sd_bus_message_read(reply, "s", &mid);
1353 return sd_id128_from_string(mid, machine);