+/**
+ * Seeks key in rule string, and duplicates value of the key into pValue.
+ * Because of the duplication, pValue must be freed after use.
+ *
+ * @param rule rule to look through
+ * @param key key to look for
+ * @param pValue pointer to value of the key found
+ * @return length of the value string, 0 means not found
+ */
+static int parse_match_key(const char *rule, const char* key, char** pValue)
+{
+ const char* pBegin;
+ const char* pValueEnd;
+ int value_length = 0;
+
+ pBegin = strstr(rule, key);
+ if(pBegin)
+ {
+ pBegin += strlen(key);
+ pValueEnd = strchr(pBegin, '\'');
+ if(pValueEnd)
+ {
+ value_length = pValueEnd - pBegin;
+ *pValue = strndup(pBegin, value_length);
+ if(*pValue)
+ _dbus_verbose ("found for key: %s value:'%s'\n", key, *pValue);
+ }
+ }
+ return value_length;
+}
+
+/**
+ * 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;
+ }
+
+out:
+ if(pName)
+ free(pName);
+ if(pInterface)
+ free(pInterface);
+ return ret_value;
+}
+
+/**
+ * Opposing to dbus, in kdbus removes all match rules with given
+ * cookie, which in this implementation is equal to uniqe id.
+ *
+ * @param transport transport
+ * @param id connection id for which rules are to be removed
+ */
+dbus_bool_t remove_match_kdbus (DBusTransport* transport, __u64 id)
+{
+ struct kdbus_cmd_match __attribute__ ((__aligned__(8))) cmd;
+ int fd;
+
+ if(!_dbus_transport_get_socket_fd(transport, &fd))
+ return FALSE;
+
+ cmd.cookie = id;
+ cmd.id = id;
+ cmd.size = sizeof(struct kdbus_cmd_match);
+
+ if(ioctl(fd, KDBUS_CMD_MATCH_REMOVE, &cmd))
+ {
+ _dbus_verbose("Failed removing match rule for id: %llu; error: %d, %m\n", (unsigned long long)id, errno);
+ return FALSE;
+ }
+ else
+ {
+ _dbus_verbose("Match rule removed correctly.\n");
+ return TRUE;
+ }
+}
+
+/*
+ * Creates kdbus bus of given type.
+ */
+char* make_kdbus_bus(DBusBusType type, const char* address, DBusError *error)