Index: uspace/lib/hound/include/hound/protocol.h
===================================================================
--- uspace/lib/hound/include/hound/protocol.h	(revision e6e5f4ecffd03dfe956ff307d3314335fc7d5d34)
+++ uspace/lib/hound/include/hound/protocol.h	(revision 6ec1d480ee8e599fbab1192e113acd039e31d0b4)
@@ -95,4 +95,5 @@
 	int (*rem_context)(void *, hound_context_id_t);
 	bool (*is_record_context)(void *, hound_context_id_t);
+	int (*get_list)(void *, const char ***, size_t *, const char *, int);
 	int (*connect)(void *, const char *, const char *);
 	int (*disconnect)(void *, const char *, const char *);
Index: uspace/lib/hound/src/protocol.c
===================================================================
--- uspace/lib/hound/src/protocol.c	(revision e6e5f4ecffd03dfe956ff307d3314335fc7d5d34)
+++ uspace/lib/hound/src/protocol.c	(revision 6ec1d480ee8e599fbab1192e113acd039e31d0b4)
@@ -37,4 +37,5 @@
 #include <errno.h>
 #include <loc.h>
+#include <macros.h>
 #include <str.h>
 #include <stdlib.h>
@@ -143,26 +144,27 @@
 	}
 	unsigned name_count = IPC_GET_ARG1(res_call);
-	size_t max_length = IPC_GET_ARG2(res_call);
 
 	/* Start receiving names */
-	const char ** names = NULL;
+	const char **names = NULL;
 	if (name_count) {
+		size_t *sizes = calloc(name_count, sizeof(size_t));
 		names = calloc(name_count, sizeof(char *));
-		char *tmp_name = malloc(max_length + 1);
-		if (!names || !tmp_name) {
-			async_exchange_end(exch);
-			return ENOMEM;
-		}
-		for (unsigned i = 0; i < name_count; ++i) {
-			bzero(tmp_name, max_length + 1);
-			ret = async_data_read_start(exch, tmp_name, max_length);
-			if (ret == EOK) {
-				names[i] = str_dup(tmp_name);
-				ret = names[i] ? EOK : ENOMEM;
-			}
-			if (ret != EOK)
-				break;
-		}
-		free(tmp_name);
+		if (!names || !sizes)
+			ret = ENOMEM;
+
+		if (ret == EOK)
+			ret = async_data_read_start(exch, sizes,
+			    name_count * sizeof(size_t));
+		for (unsigned i = 0; i < name_count && ret == EOK; ++i) {
+			char *name = malloc(sizes[i] + 1);
+			if (name) {
+				bzero(name, sizes[i]);
+				ret = async_data_read_start(exch, name, sizes[i]);
+				names[i] = name;
+			} else {
+				ret = ENOMEM;
+			}
+		}
+		free(sizes);
 	}
 	async_exchange_end(exch);
@@ -188,9 +190,12 @@
 	if (!exch)
 		return ENOMEM;
-	int ret = async_req_0_0(exch, IPC_M_HOUND_CONNECT);
+	ipc_call_t call;
+	aid_t id = async_send_0(exch, IPC_M_HOUND_CONNECT, &call);
+	int ret = id ? EOK : EPARTY;
 	if (ret == EOK)
 		ret = async_data_write_start(exch, source, str_size(source));
 	if (ret == EOK)
 		ret = async_data_write_start(exch, sink, str_size(sink));
+	async_wait_for(id, (sysarg_t*)&ret);
 	async_exchange_end(exch);
 	return ret;
@@ -204,9 +209,12 @@
 	if (!exch)
 		return ENOMEM;
-	int ret = async_req_0_0(exch, IPC_M_HOUND_DISCONNECT);
+	ipc_call_t call;
+	aid_t id = async_send_0(exch, IPC_M_HOUND_DISCONNECT, &call);
+	int ret = id ? EOK : EPARTY;
 	if (ret == EOK)
 		ret = async_data_write_start(exch, source, str_size(source));
 	if (ret == EOK)
 		ret = async_data_write_start(exch, sink, str_size(sink));
+	async_wait_for(id, (sysarg_t*)&ret);
 	async_exchange_end(exch);
 	return ENOTSUP;
@@ -304,4 +312,102 @@
 			    server_iface->rem_context(server_iface->server, id);
 			async_answer_0(callid, ret);
+			break;
+		}
+		case IPC_M_HOUND_GET_LIST: {
+			if (!server_iface || !server_iface->get_list) {
+				async_answer_0(callid, ENOTSUP);
+				break;
+			}
+			const char **list = NULL;
+			const int flags = IPC_GET_ARG1(call);
+			size_t count = IPC_GET_ARG2(call);
+			const bool conn = IPC_GET_ARG3(call);
+			char *conn_name = NULL;
+			int ret = EOK;
+			if (conn)
+				ret = async_data_write_accept(
+				    (void**)&conn_name, true, 0, 0, 0, 0);
+
+			if (ret == EOK)
+				ret = server_iface->get_list(
+				    server_iface->server, &list, &count,
+				    conn_name, flags);
+			free(conn_name);
+			size_t *sizes = NULL;
+			if (count)
+				sizes = calloc(count, sizeof(size_t));
+			if (count && !sizes)
+				ret = ENOMEM;
+			async_answer_1(callid, ret, count);
+
+			/* We are done */
+			if (count == 0 || ret != EOK)
+				break;
+
+			/* Prepare sizes table */
+			for (unsigned i = 0; i < count; ++i)
+				sizes[i] = str_size(list[i]);
+
+			/* Send sizes table */
+			ipc_callid_t id;
+			if (async_data_read_receive(&id, NULL)) {
+				ret = async_data_read_finalize(id, sizes,
+				    count * sizeof(size_t));
+			}
+			free(sizes);
+
+			/* Proceed to send names */
+			for (unsigned i = 0; i < count; ++i) {
+				size_t size = str_size(list[i]);
+				ipc_callid_t id;
+				if (ret == EOK &&
+				    async_data_read_receive(&id, NULL)) {
+					ret = async_data_read_finalize(id,
+					    list[i], size);
+				}
+				free(list[i]);
+			}
+			free(list);
+			break;
+		}
+		case IPC_M_HOUND_CONNECT: {
+			if (!server_iface || !server_iface->connect) {
+				async_answer_0(callid, ENOTSUP);
+				break;
+			}
+			void *source = NULL;
+			void *sink = NULL;
+			int ret =
+			    async_data_write_accept(&source, true, 0, 0, 0, 0);
+			if (ret == EOK)
+				ret = async_data_write_accept(&sink,
+				    true, 0, 0, 0, 0);
+			if (ret == EOK)
+				ret = server_iface->connect(
+				    server_iface->server, source, sink);
+			free(source);
+			free(sink);
+			async_answer_0(callid, ret);
+			break;
+		}
+		case IPC_M_HOUND_DISCONNECT: {
+			if (!server_iface || !server_iface->disconnect) {
+				async_answer_0(callid, ENOTSUP);
+				break;
+			}
+			void *source = NULL;
+			void *sink = NULL;
+			int ret =
+			    async_data_write_accept(&source, true, 0, 0, 0, 0);
+			if (ret == EOK)
+				ret = async_data_write_accept(&sink,
+				    true, 0, 0, 0, 0);
+			if (ret == EOK)
+				ret = server_iface->connect(
+				    server_iface->server, source, sink);
+			free(source);
+			free(sink);
+			async_answer_0(callid, ret);
+			break;
 		}
 		case IPC_M_HOUND_STREAM_ENTER: {
