Index: uspace/lib/c/generic/async/client.c
===================================================================
--- uspace/lib/c/generic/async/client.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/async/client.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -202,5 +202,5 @@
 void async_reply_received(ipc_call_t *data)
 {
-	amsg_t *msg = data->label;
+	amsg_t *msg = (amsg_t *) data->answer_label;
 	if (!msg)
 		return;
Index: uspace/lib/c/generic/async/server.c
===================================================================
--- uspace/lib/c/generic/async/server.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/async/server.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -144,7 +144,4 @@
 	task_id_t in_task_id;
 
-	/** Incoming phone hash. */
-	sysarg_t in_phone_hash;
-
 	/** Link to the client tracking structure. */
 	client_t *client;
@@ -234,7 +231,4 @@
 static sysarg_t notification_avail = 0;
 
-static FIBRIL_RMUTEX_INITIALIZE(conn_mutex);
-static hash_table_t conn_hash_table;
-
 static size_t client_key_hash(void *key)
 {
@@ -261,58 +255,4 @@
 	.key_hash = client_key_hash,
 	.key_equal = client_key_equal,
-	.equal = NULL,
-	.remove_callback = NULL
-};
-
-typedef struct {
-	task_id_t task_id;
-	sysarg_t phone_hash;
-} conn_key_t;
-
-/** Compute hash into the connection hash table
- *
- * The hash is based on the source task ID and the source phone hash. The task
- * ID is included in the hash because a phone hash alone might not be unique
- * while we still track connections for killed tasks due to kernel's recycling
- * of phone structures.
- *
- * @param key Pointer to the connection key structure.
- *
- * @return Index into the connection hash table.
- *
- */
-static size_t conn_key_hash(void *key)
-{
-	conn_key_t *ck = (conn_key_t *) key;
-
-	size_t hash = 0;
-	hash = hash_combine(hash, LOWER32(ck->task_id));
-	hash = hash_combine(hash, UPPER32(ck->task_id));
-	hash = hash_combine(hash, ck->phone_hash);
-	return hash;
-}
-
-static size_t conn_hash(const ht_link_t *item)
-{
-	connection_t *conn = hash_table_get_inst(item, connection_t, link);
-	return conn_key_hash(&(conn_key_t){
-		.task_id = conn->in_task_id,
-		.phone_hash = conn->in_phone_hash
-	});
-}
-
-static bool conn_key_equal(void *key, const ht_link_t *item)
-{
-	conn_key_t *ck = (conn_key_t *) key;
-	connection_t *conn = hash_table_get_inst(item, connection_t, link);
-	return ((ck->task_id == conn->in_task_id) &&
-	    (ck->phone_hash == conn->in_phone_hash));
-}
-
-/** Operations for the connection hash table. */
-static hash_table_ops_t conn_hash_table_ops = {
-	.hash = conn_hash,
-	.key_hash = conn_key_hash,
-	.key_equal = conn_key_equal,
 	.equal = NULL,
 	.remove_callback = NULL
@@ -386,4 +326,6 @@
 	fibril_connection = (connection_t *) arg;
 
+	mpsc_t *c = fibril_connection->msg_channel;
+
 	/*
 	 * Add our reference for the current connection in the client task
@@ -395,5 +337,5 @@
 	if (!client) {
 		ipc_answer_0(fibril_connection->call.cap_handle, ENOMEM);
-		return 0;
+		goto out;
 	}
 
@@ -411,21 +353,8 @@
 	async_client_put(client);
 
-	fibril_rmutex_lock(&conn_mutex);
-
-	/*
-	 * Remove myself from the connection hash table.
-	 */
-	hash_table_remove(&conn_hash_table, &(conn_key_t){
-		.task_id = fibril_connection->in_task_id,
-		.phone_hash = fibril_connection->in_phone_hash
-	});
-
 	/*
 	 * Close the channel, if it isn't closed already.
 	 */
-	mpsc_t *c = fibril_connection->msg_channel;
 	mpsc_close(c);
-
-	fibril_rmutex_unlock(&conn_mutex);
 
 	/*
@@ -439,4 +368,5 @@
 	 * Clean up memory.
 	 */
+out:
 	mpsc_destroy(c);
 	free(fibril_connection);
@@ -444,4 +374,10 @@
 }
 
+/** Return label usable during replies to IPC_M_CONNECT_ME_TO. */
+sysarg_t async_get_label(void)
+{
+   return (sysarg_t) fibril_connection;
+}
+
 /** Create a new fibril for a new connection.
  *
@@ -450,32 +386,28 @@
  * particular fibrils.
  *
- * @param in_task_id     Identification of the incoming connection.
- * @param in_phone_hash  Identification of the incoming connection.
- * @param call           Call data of the opening call. If call is NULL,
- *                       the connection was opened by accepting the
- *                       IPC_M_CONNECT_TO_ME call and this function is
- *                       called directly by the server.
- * @param handler        Connection handler.
- * @param data           Client argument to pass to the connection handler.
+ * @param conn        Pointer to the connection structure. Will be used as the
+ *                    label of the connected phone and request_label of incoming
+ *                    calls routed through that phone.
+ * @param in_task_id  Identification of the incoming connection.
+ * @param call        Call data of the opening call. If call is NULL, the
+ *                    connection was opened by accepting the
+ *                    IPC_M_CONNECT_TO_ME call and this function is called
+ *                    directly by the server.
+ * @param handler     Connection handler.
+ * @param data        Client argument to pass to the connection handler.
  *
  * @return  New fibril id or NULL on failure.
  *
  */
-static fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash,
+static fid_t async_new_connection(connection_t *conn, task_id_t in_task_id,
     ipc_call_t *call, async_port_handler_t handler, void *data)
 {
-	connection_t *conn = malloc(sizeof(*conn));
-	if (!conn) {
-		if (call)
-			ipc_answer_0(call->cap_handle, ENOMEM);
-
-		return (fid_t) NULL;
-	}
-
 	conn->in_task_id = in_task_id;
-	conn->in_phone_hash = in_phone_hash;
 	conn->msg_channel = mpsc_create(sizeof(ipc_call_t));
 	conn->handler = handler;
 	conn->data = data;
+
+	if (!conn->msg_channel)
+		goto error;
 
 	if (call)
@@ -487,23 +419,20 @@
 	conn->fid = fibril_create(connection_fibril, conn);
 
-	if (conn->fid == 0) {
+	if (conn->fid == 0)
+		goto error;
+
+	fibril_start(conn->fid);
+
+	return conn->fid;
+
+error:
+	if (conn->msg_channel)
 		mpsc_destroy(conn->msg_channel);
-		free(conn);
-
-		if (call)
-			ipc_answer_0(call->cap_handle, ENOMEM);
-
-		return (fid_t) NULL;
-	}
-
-	/* Add connection to the connection hash table */
-
-	fibril_rmutex_lock(&conn_mutex);
-	hash_table_insert(&conn_hash_table, &conn->link);
-	fibril_rmutex_unlock(&conn_mutex);
-
-	fibril_start(conn->fid);
-
-	return conn->fid;
+	free(conn);
+
+	if (call)
+		ipc_answer_0(call->cap_handle, ENOMEM);
+
+	return (fid_t) NULL;
 }
 
@@ -532,20 +461,27 @@
 		return ENOENT;
 
+	connection_t *conn = calloc(1, sizeof(*conn));
+	if (!conn)
+		return ENOMEM;
+
 	ipc_call_t answer;
-	aid_t req = async_send_3(exch, IPC_M_CONNECT_TO_ME, iface, arg1, arg2,
-	    &answer);
+	aid_t req = async_send_5(exch, IPC_M_CONNECT_TO_ME, iface, arg1, arg2,
+	    0, (sysarg_t) conn, &answer);
 
 	errno_t rc;
 	async_wait_for(req, &rc);
-	if (rc != EOK)
+	if (rc != EOK) {
+		free(conn);
 		return rc;
+	}
 
 	rc = async_create_port_internal(iface, handler, data, port_id);
-	if (rc != EOK)
+	if (rc != EOK) {
+		free(conn);
 		return rc;
-
-	sysarg_t phone_hash = IPC_GET_ARG5(answer);
-	fid_t fid = async_new_connection(answer.in_task_id, phone_hash,
-	    NULL, handler, data);
+	}
+
+	fid_t fid = async_new_connection(conn, answer.task_id, NULL, handler,
+	    data);
 	if (fid == (fid_t) NULL)
 		return ENOMEM;
@@ -601,16 +537,10 @@
 	assert(call);
 
-	fibril_rmutex_lock(&conn_mutex);
-
-	ht_link_t *link = hash_table_find(&conn_hash_table, &(conn_key_t){
-		.task_id = call->in_task_id,
-		.phone_hash = call->in_phone_hash
-	});
-	if (!link) {
-		fibril_rmutex_unlock(&conn_mutex);
+	connection_t *conn = (connection_t *) call->request_label;
+
+	if (!conn)
 		return ENOENT;
-	}
-
-	connection_t *conn = hash_table_get_inst(link, connection_t, link);
+
+	assert(conn->msg_channel);
 
 	errno_t rc = mpsc_send(conn->msg_channel, call);
@@ -625,5 +555,4 @@
 	}
 
-	fibril_rmutex_unlock(&conn_mutex);
 	return rc;
 }
@@ -1009,6 +938,11 @@
 	/* New connection */
 	if (IPC_GET_IMETHOD(*call) == IPC_M_CONNECT_ME_TO) {
+		connection_t *conn = calloc(1, sizeof(*conn));
+		if (!conn) {
+			ipc_answer_0(call->cap_handle, ENOMEM);
+			return;
+		}
+
 		iface_t iface = (iface_t) IPC_GET_ARG1(*call);
-		sysarg_t in_phone_hash = IPC_GET_ARG5(*call);
 
 		// TODO: Currently ignores all ports but the first one.
@@ -1017,10 +951,9 @@
 		    async_get_port_handler(iface, 0, &data);
 
-		async_new_connection(call->in_task_id, in_phone_hash, call,
-		    handler, data);
+		async_new_connection(conn, call->task_id, call, handler, data);
 		return;
 	}
 
-	/* Try to route the call through the connection hash table */
+	/* Route the call according to its request label */
 	errno_t rc = route_call(call);
 	if (rc == EOK)
@@ -1083,7 +1016,4 @@
 		abort();
 
-	if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops))
-		abort();
-
 	if (!hash_table_create(&notification_hash_table, 0, 0,
 	    &notification_hash_table_ops))
@@ -1171,14 +1101,9 @@
 		return ENOENT;
 
-	ipc_call_t answer;
-	aid_t req = async_send_3(exch, IPC_M_CONNECT_TO_ME, iface, arg2, arg3,
-	    &answer);
-
-	errno_t rc;
-	async_wait_for(req, &rc);
-	if (rc != EOK)
-		return (errno_t) rc;
-
-	return EOK;
+	sysarg_t label = 0;
+	errno_t rc = async_req_5_0(exch, IPC_M_CONNECT_TO_ME, iface, arg2, arg3,
+	    0, label);
+
+	return rc;
 }
 
Index: uspace/lib/c/generic/bd_srv.c
===================================================================
--- uspace/lib/c/generic/bd_srv.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/bd_srv.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -228,5 +228,5 @@
 
 	/* Accept the connection */
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	srv = bd_srv_create(srvs);
Index: uspace/lib/c/generic/inet/tcp.c
===================================================================
--- uspace/lib/c/generic/inet/tcp.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/inet/tcp.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -817,5 +817,5 @@
 	tcp_t *tcp = (tcp_t *)arg;
 
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	while (true) {
Index: uspace/lib/c/generic/inet/udp.c
===================================================================
--- uspace/lib/c/generic/inet/udp.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/inet/udp.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -494,5 +494,5 @@
 	udp_t *udp = (udp_t *)arg;
 
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	while (true) {
Index: uspace/lib/c/generic/io/chardev_srv.c
===================================================================
--- uspace/lib/c/generic/io/chardev_srv.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/io/chardev_srv.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -136,5 +136,5 @@
 
 	/* Accept the connection */
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	srv = chardev_srv_create(srvs);
Index: uspace/lib/c/generic/io/con_srv.c
===================================================================
--- uspace/lib/c/generic/io/con_srv.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/io/con_srv.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -333,5 +333,5 @@
 
 	/* Accept the connection */
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	srv = con_srv_create(srvs);
Index: uspace/lib/c/generic/iplink_srv.c
===================================================================
--- uspace/lib/c/generic/iplink_srv.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/generic/iplink_srv.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -238,5 +238,5 @@
 
 	/* Accept the connection */
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/include/async.h	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -332,4 +332,6 @@
     sysarg_t *, sysarg_t *);
 
+extern sysarg_t async_get_label(void);
+
 extern async_sess_t *async_connect_me_to(async_exch_t *, iface_t, sysarg_t,
     sysarg_t);
Index: uspace/lib/c/include/ipc/common.h
===================================================================
--- uspace/lib/c/include/ipc/common.h	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/c/include/ipc/common.h	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -36,19 +36,10 @@
 #define LIBC_IPC_COMMON_H_
 
+#include <types/common.h>
 #include <abi/ipc/ipc.h>
-#include <abi/proc/task.h>
-#include <abi/cap.h>
-#include <types/common.h>
 
 #define IPC_FLAG_BLOCKING  0x01
 
-typedef struct {
-	sysarg_t args[IPC_CALL_LEN];
-	task_id_t in_task_id;
-	sysarg_t in_phone_hash;
-	unsigned int flags;
-	void *label;
-	cap_call_handle_t cap_handle;
-} ipc_call_t;
+typedef ipc_data_t ipc_call_t;
 
 #endif
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/drv/generic/driver.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -339,5 +339,5 @@
 {
 	/* Accept connection */
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	while (true) {
@@ -419,5 +419,5 @@
 		ret = (*fun->ops->open)(fun);
 
-	async_answer_0(icall, ret);
+	async_answer_5(icall, ret, 0, 0, 0, 0, async_get_label());
 	if (ret != EOK) {
 		fun_del_ref(fun);
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/fs/libfs.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -283,5 +283,5 @@
 		 * created by IPC_M_CONNECT_TO_ME.
 		 */
-		async_answer_0(icall, EOK);
+		async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 	}
 
Index: uspace/lib/graph/graph.c
===================================================================
--- uspace/lib/graph/graph.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/graph/graph.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -501,5 +501,5 @@
 
 	/* Accept the connection. */
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	/* Establish callback session. */
@@ -569,5 +569,5 @@
 
 	/* Accept the connection. */
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	/* Enter command loop. */
Index: uspace/lib/hound/src/protocol.c
===================================================================
--- uspace/lib/hound/src/protocol.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/hound/src/protocol.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -396,5 +396,5 @@
 	/* Accept connection if there is a valid iface*/
 	if (server_iface) {
-		async_answer_0(icall, EOK);
+		async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 	} else {
 		async_answer_0(icall, ENOTSUP);
Index: uspace/lib/usbvirt/src/device.c
===================================================================
--- uspace/lib/usbvirt/src/device.c	(revision 889cdb1c2046af9d31d314fa691773fa2e4f9119)
+++ uspace/lib/usbvirt/src/device.c	(revision f5837524878dfa0cfbf12164f7b8144cee094f9a)
@@ -58,5 +58,5 @@
 	assert(DEV != NULL);
 
-	async_answer_0(icall, EOK);
+	async_answer_5(icall, EOK, 0, 0, 0, 0, async_get_label());
 
 	while (true) {
