+/**
+ * Adds a match rule to match broadcast messages going through the message bus.
+ * Do no affect messages addressed directly.
+ *
+ * The "rule" argument is the string form of a match rule.
+ *
+ * Only part of the dbus's matching capabilities is implemented in kdbus now, because of different mechanism.
+ * Current mapping:
+ * interface match key mapped to bloom
+ * sender match key mapped to src_name
+ *
+ * @param transport transport
+ * @param id id of connection for which the rule is to be added
+ * @param rule textual form of match rule
+ */
+dbus_bool_t add_match_kdbus (DBusTransport* transport, __u64 id, const char *rule)
+{
+ struct kdbus_cmd_match* pCmd_match;
+ struct kdbus_item *pItem;
+ __u64 src_id = KDBUS_MATCH_SRC_ID_ANY;
+ uint64_t size;
+ int name_size;
+ char* pName = NULL;
+ char* pInterface = NULL;
+ dbus_bool_t ret_value = FALSE;
+ int fd;
+ __u64 bloom_size;
+
+ if(!_dbus_transport_get_socket_fd(transport, &fd))
+ return FALSE;
+
+ bloom_size = dbus_transport_get_bloom_size(transport);
+
+ /*parsing rule and calculating size of command*/
+ size = sizeof(struct kdbus_cmd_match);
+ if(parse_match_key(rule, "interface='", &pInterface)) /*actual size is not important for interface because bloom size is defined by bus*/
+ size += KDBUS_ITEM_HEADER_SIZE + bloom_size;
+ name_size = parse_match_key(rule, "sender='", &pName);
+ if(name_size)
+ {
+ if(!strncmp(pName, ":1.", 3)) /*if name is unique name it must be converted to unique id*/
+ {
+ src_id = strtoull(&pName[3], NULL, 10);
+ free(pName);
+ pName = NULL;
+ }
+ else
+ size += KDBUS_ITEM_SIZE(name_size + 1); //well known name
+ }
+
+ pCmd_match = alloca(size);
+ if(pCmd_match == NULL)
+ goto out;
+
+ pCmd_match->id = id;
+ pCmd_match->cookie = id;
+ pCmd_match->size = size;
+ pCmd_match->src_id = src_id;
+
+ pItem = pCmd_match->items;
+ if(pName)
+ {
+ pItem->type = KDBUS_MATCH_SRC_NAME;
+ pItem->size = KDBUS_ITEM_HEADER_SIZE + name_size + 1;
+ memcpy(pItem->str, pName, strlen(pName) + 1);
+ pItem = KDBUS_PART_NEXT(pItem);
+ }
+ if(pInterface)
+ {
+ pItem->type = KDBUS_MATCH_BLOOM;
+ pItem->size = KDBUS_ITEM_HEADER_SIZE + bloom_size;
+ strncpy(pItem->data, pInterface, bloom_size);
+ }
+
+ if(ioctl(fd, KDBUS_CMD_MATCH_ADD, pCmd_match))
+ _dbus_verbose("Failed adding match bus rule %s,\nerror: %d, %m\n", rule, errno);
+ else
+ {
+ _dbus_verbose("Added match bus rule %s for id:%llu\n", rule, (unsigned long long)id);
+ ret_value = TRUE;
+ }