Index: abi/include/abi/ipc/interfaces.h
===================================================================
--- abi/include/abi/ipc/interfaces.h	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ abi/include/abi/ipc/interfaces.h	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -79,4 +79,5 @@
 
 typedef enum {
+	INTERFACE_ANY = 0,
 	INTERFACE_LOADER =
 	    FOURCC_COMPACT('l', 'o', 'a', 'd') | IFACE_EXCHANGE_SERIALIZE,
Index: uspace/lib/c/generic/async/server.c
===================================================================
--- uspace/lib/c/generic/async/server.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/lib/c/generic/async/server.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -1317,13 +1317,13 @@
  * Ask through phone for a new connection to some service.
  *
- * @param exch Exchange for sending the message.
- * @param arg1 User defined argument.
- * @param arg2 User defined argument.
- * @param arg3 User defined argument.
+ * @param exch  Exchange for sending the message.
+ * @param iface Callback interface.
+ * @param arg2  User defined argument.
+ * @param arg3  User defined argument.
  *
  * @return Zero on success or an error code.
  *
  */
-errno_t async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
+errno_t async_connect_to_me(async_exch_t *exch, iface_t iface, sysarg_t arg2,
     sysarg_t arg3)
 {
@@ -1332,5 +1332,5 @@
 
 	ipc_call_t answer;
-	aid_t req = async_send_3(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
+	aid_t req = async_send_3(exch, IPC_M_CONNECT_TO_ME, iface, arg2, arg3,
 	    &answer);
 
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/lib/c/generic/devman.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -192,5 +192,5 @@
 
 	exch = devman_exchange_begin(INTERFACE_DDF_DRIVER);
-	async_connect_to_me(exch, 0, 0, 0);
+	async_connect_to_me(exch, INTERFACE_ANY, 0, 0);
 	devman_exchange_end(exch);
 
Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/lib/c/generic/loc.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -255,5 +255,5 @@
 	}
 
-	async_connect_to_me(exch, 0, 0, 0);
+	async_connect_to_me(exch, INTERFACE_ANY, 0, 0);
 
 	/*
Index: uspace/lib/c/generic/ns.c
===================================================================
--- uspace/lib/c/generic/ns.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/lib/c/generic/ns.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -46,16 +46,21 @@
 static async_sess_t *sess_ns = NULL;
 
-errno_t service_register(service_t service)
-{
-	errno_t retval;
+errno_t service_register(service_t service, iface_t iface,
+    async_port_handler_t handler, void *data)
+{
+	async_sess_t *sess = ns_session_get();
+	if (sess == NULL)
+		return EIO;
+
+	port_id_t port;
+	errno_t rc = async_create_port(iface, handler, data, &port);
+	if (rc != EOK)
+		return rc;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
 	ipc_call_t answer;
-
-	async_sess_t *sess = ns_session_get();
-	if (sess == NULL)
-		return EIO;
-
-	async_exch_t *exch = async_exchange_begin(sess);
-	aid_t req = async_send_1(exch, NS_REGISTER, service, &answer);
-	errno_t rc = async_connect_to_me(exch, 0, service, 0);
+	aid_t req = async_send_2(exch, NS_REGISTER, service, iface, &answer);
+	rc = async_connect_to_me(exch, iface, service, 0);
 
 	async_exchange_end(exch);
@@ -66,4 +71,32 @@
 	}
 
+	errno_t retval;
+	async_wait_for(req, &retval);
+	return rc;
+}
+
+errno_t service_register_broker(service_t service, async_port_handler_t handler,
+    void *data)
+{
+	async_set_fallback_port_handler(handler, data);
+
+	async_sess_t *sess = ns_session_get();
+	if (sess == NULL)
+		return EIO;
+
+	async_exch_t *exch = async_exchange_begin(sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, NS_REGISTER_BROKER, service, &answer);
+	errno_t rc = async_connect_to_me(exch, INTERFACE_ANY, service, 0);
+
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_forget(req);
+		return rc;
+	}
+
+	errno_t retval;
 	async_wait_for(req, &retval);
 	return rc;
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/lib/c/include/async.h	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -342,5 +342,5 @@
 extern async_sess_t *async_connect_kbox(task_id_t);
 
-extern errno_t async_connect_to_me(async_exch_t *, sysarg_t, sysarg_t, sysarg_t);
+extern errno_t async_connect_to_me(async_exch_t *, iface_t, sysarg_t, sysarg_t);
 
 extern errno_t async_hangup(async_sess_t *);
Index: uspace/lib/c/include/ipc/ns.h
===================================================================
--- uspace/lib/c/include/ipc/ns.h	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/lib/c/include/ipc/ns.h	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -41,4 +41,5 @@
 	NS_PING = IPC_FIRST_USER_METHOD,
 	NS_REGISTER,
+	NS_REGISTER_BROKER,
 	NS_TASK_WAIT,
 	NS_ID_INTRO,
Index: uspace/lib/c/include/ns.h
===================================================================
--- uspace/lib/c/include/ns.h	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/lib/c/include/ns.h	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -40,5 +40,7 @@
 #include <async.h>
 
-extern errno_t service_register(service_t);
+extern errno_t service_register(service_t, iface_t, async_port_handler_t,
+    void *);
+extern errno_t service_register_broker(service_t, async_port_handler_t, void *);
 extern async_sess_t *service_connect(service_t, iface_t, sysarg_t);
 extern async_sess_t *service_connect_blocking(service_t, iface_t, sysarg_t);
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/devman/main.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -325,33 +325,4 @@
 	async_set_client_data_destructor(devman_client_data_destroy);
 
-	port_id_t port;
-	rc = async_create_port(INTERFACE_DDF_DRIVER,
-	    devman_connection_driver, NULL, &port);
-	if (rc != EOK) {
-		printf("%s: Error creating DDF driver port: %s\n", NAME, str_error(rc));
-		return rc;
-	}
-
-	rc = async_create_port(INTERFACE_DDF_CLIENT,
-	    devman_connection_client, NULL, &port);
-	if (rc != EOK) {
-		printf("%s: Error creating DDF client port: %s\n", NAME, str_error(rc));
-		return rc;
-	}
-
-	rc = async_create_port(INTERFACE_DEVMAN_DEVICE,
-	    devman_connection_device, NULL, &port);
-	if (rc != EOK) {
-		printf("%s: Error creating devman device port: %s\n", NAME, str_error(rc));
-		return rc;
-	}
-
-	rc = async_create_port(INTERFACE_DEVMAN_PARENT,
-	    devman_connection_parent, NULL, &port);
-	if (rc != EOK) {
-		printf("%s: Error creating devman parent port: %s\n", NAME, str_error(rc));
-		return rc;
-	}
-
 	async_set_fallback_port_handler(devman_forward, NULL);
 
@@ -362,7 +333,29 @@
 
 	/* Register device manager at naming service. */
-	rc = service_register(SERVICE_DEVMAN);
-	if (rc != EOK) {
-		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering as a service: %s", str_error(rc));
+	rc = service_register(SERVICE_DEVMAN, INTERFACE_DDF_DRIVER,
+	    devman_connection_driver, NULL);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering driver port: %s", str_error(rc));
+		return rc;
+	}
+
+	rc = service_register(SERVICE_DEVMAN, INTERFACE_DDF_CLIENT,
+	    devman_connection_client, NULL);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering client port: %s", str_error(rc));
+		return rc;
+	}
+
+	rc = service_register(SERVICE_DEVMAN, INTERFACE_DEVMAN_DEVICE,
+	    devman_connection_device, NULL);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering device port: %s", str_error(rc));
+		return rc;
+	}
+
+	rc = service_register(SERVICE_DEVMAN, INTERFACE_DEVMAN_PARENT,
+	    devman_connection_parent, NULL);
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering parent port: %s", str_error(rc));
 		return rc;
 	}
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/loader/main.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -399,6 +399,4 @@
 int main(int argc, char *argv[])
 {
-	async_set_fallback_port_handler(ldr_connection, NULL);
-
 	/* Introduce this task to the NS (give it our task ID). */
 	task_id_t id = task_get_id();
@@ -407,15 +405,10 @@
 		return rc;
 
-	/* Create port */
-	port_id_t port;
-	rc = async_create_port(INTERFACE_LOADER, ldr_connection, NULL, &port);
+	/* Register at naming service. */
+	rc = service_register(SERVICE_LOADER, INTERFACE_LOADER,
+	    ldr_connection, NULL);
 	if (rc != EOK)
 		return rc;
 
-	/* Register at naming service. */
-	rc = service_register(SERVICE_LOADER);
-	if (rc != EOK)
-		return rc;
-
 	async_manager();
 
Index: uspace/srv/locsrv/locsrv.c
===================================================================
--- uspace/srv/locsrv/locsrv.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/locsrv/locsrv.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -1533,26 +1533,22 @@
 	}
 
-	port_id_t port;
-	errno_t rc = async_create_port(INTERFACE_LOC_SUPPLIER,
-	    loc_connection_supplier, NULL, &port);
+	/* Register location service at naming service */
+	errno_t rc = service_register(SERVICE_LOC, INTERFACE_LOC_SUPPLIER,
+	    loc_connection_supplier, NULL);
 	if (rc != EOK) {
-		printf("%s: Error while creating supplier port: %s\n", NAME, str_error(rc));
+		printf("%s: Error while registering supplier service: %s\n", NAME, str_error(rc));
 		return rc;
 	}
 
-	rc = async_create_port(INTERFACE_LOC_CONSUMER,
-	    loc_connection_consumer, NULL, &port);
+	rc = service_register(SERVICE_LOC, INTERFACE_LOC_CONSUMER,
+	    loc_connection_consumer, NULL);
 	if (rc != EOK) {
-		printf("%s: Error while creating consumer port: %s\n", NAME, str_error(rc));
+		printf("%s: Error while registering consumer service: %s\n", NAME, str_error(rc));
 		return rc;
 	}
 
-	/* Set a handler of incomming connections */
-	async_set_fallback_port_handler(loc_forward, NULL);
-
-	/* Register location service at naming service */
-	rc = service_register(SERVICE_LOC);
+	rc = service_register_broker(SERVICE_LOC, loc_forward, NULL);
 	if (rc != EOK) {
-		printf("%s: Error while registering service: %s\n", NAME, str_error(rc));
+		printf("%s: Error while registering broker service: %s\n", NAME, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/logger/main.c
===================================================================
--- uspace/srv/logger/main.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/logger/main.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -67,26 +67,21 @@
 	}
 
-	port_id_t port;
-	errno_t rc = async_create_port(INTERFACE_LOGGER_CONTROL,
-	    connection_handler_control, NULL, &port);
+	errno_t rc = service_register(SERVICE_LOGGER, INTERFACE_LOGGER_CONTROL,
+	    connection_handler_control, NULL);
 	if (rc != EOK) {
-		printf("%s: Error while creating control port: %s\n", NAME, str_error(rc));
-		return rc;
-	}
-
-	rc = async_create_port(INTERFACE_LOGGER_WRITER,
-	    connection_handler_writer, NULL, &port);
-	if (rc != EOK) {
-		printf("%s: Error while creating writer port: %s\n", NAME, str_error(rc));
-		return rc;
-	}
-
-	rc = service_register(SERVICE_LOGGER);
-	if (rc != EOK) {
-		printf(NAME ": failed to register: %s.\n", str_error(rc));
+		printf("%s: Failed to register control port: %s.\n", NAME,
+		    str_error(rc));
 		return -1;
 	}
 
-	printf(NAME ": Accepting connections\n");
+	rc = service_register(SERVICE_LOGGER, INTERFACE_LOGGER_WRITER,
+	    connection_handler_writer, NULL);
+	if (rc != EOK) {
+		printf("%s: Failed to register writer port: %s.\n", NAME,
+		    str_error(rc));
+		return -1;
+	}
+
+	printf("%s: Accepting connections\n", NAME);
 	async_manager();
 
Index: uspace/srv/ns/clonable.c
===================================================================
--- uspace/srv/ns/clonable.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/ns/clonable.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -54,5 +54,5 @@
 static list_t cs_req;
 
-errno_t clonable_init(void)
+errno_t ns_clonable_init(void)
 {
 	list_initialize(&cs_req);
@@ -61,17 +61,15 @@
 
 /** Return true if @a service is clonable. */
-bool service_clonable(service_t service)
+bool ns_service_is_clonable(service_t service, iface_t iface)
 {
-	return (service == SERVICE_LOADER);
+	return (service == SERVICE_LOADER) && (iface == INTERFACE_LOADER);
 }
 
 /** Register clonable service.
  *
- * @param service Service to be registered.
- * @param phone   Phone to be used for connections to the service.
- * @param call    Pointer to call structure.
+ * @param call Pointer to call structure.
  *
  */
-void register_clonable(service_t service, sysarg_t phone, ipc_call_t *call)
+void ns_clonable_register(ipc_call_t *call)
 {
 	link_t *req_link = list_first(&cs_req);
@@ -87,5 +85,5 @@
 
 	/* Currently we can only handle a single type of clonable service. */
-	assert(csr->service == SERVICE_LOADER);
+	assert(ns_service_is_clonable(csr->service, csr->iface));
 
 	async_answer_0(call, EOK);
@@ -113,7 +111,7 @@
  *
  */
-void connect_to_clonable(service_t service, iface_t iface, ipc_call_t *call)
+void ns_clonable_forward(service_t service, iface_t iface, ipc_call_t *call)
 {
-	assert(service == SERVICE_LOADER);
+	assert(ns_service_is_clonable(service, iface));
 
 	cs_req_t *csr = malloc(sizeof(cs_req_t));
Index: uspace/srv/ns/clonable.h
===================================================================
--- uspace/srv/ns/clonable.h	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/ns/clonable.h	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -39,9 +39,9 @@
 #include <stdbool.h>
 
-extern errno_t clonable_init(void);
+extern errno_t ns_clonable_init(void);
 
-extern bool service_clonable(service_t);
-extern void register_clonable(service_t, sysarg_t, ipc_call_t *);
-extern void connect_to_clonable(service_t, iface_t, ipc_call_t *);
+extern bool ns_service_is_clonable(service_t, iface_t);
+extern void ns_clonable_register(ipc_call_t *);
+extern void ns_clonable_forward(service_t, iface_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/ns/ns.c
===================================================================
--- uspace/srv/ns/ns.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/ns/ns.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -61,9 +61,10 @@
 		 * Client requests to be connected to a service.
 		 */
-		if (service_clonable(service)) {
-			connect_to_clonable(service, iface, icall);
+		if (ns_service_is_clonable(service, iface)) {
+			ns_clonable_forward(service, iface, icall);
 		} else {
-			connect_to_service(service, iface, icall);
+			ns_service_forward(service, iface, icall);
 		}
+
 		return;
 	}
@@ -72,5 +73,5 @@
 
 	while (true) {
-		process_pending_conn();
+		ns_pending_conn_process();
 
 		async_get_call(&call);
@@ -82,21 +83,24 @@
 
 		service_t service;
-		sysarg_t phone;
 
 		switch (IPC_GET_IMETHOD(call)) {
 		case NS_REGISTER:
 			service = IPC_GET_ARG1(call);
-			phone = IPC_GET_ARG5(call);
+			iface = IPC_GET_ARG2(call);
 
 			/*
 			 * Server requests service registration.
 			 */
-			if (service_clonable(service)) {
-				register_clonable(service, phone, &call);
+			if (ns_service_is_clonable(service, iface)) {
+				ns_clonable_register(&call);
 				continue;
 			} else {
-				retval = register_service(service, phone, &call);
+				retval = ns_service_register(service, iface);
 			}
 
+			break;
+		case NS_REGISTER_BROKER:
+			service = IPC_GET_ARG1(call);
+			retval = ns_service_register_broker(service);
 			break;
 		case NS_PING:
@@ -115,5 +119,6 @@
 			break;
 		default:
-			printf("ns: method not supported\n");
+			printf("%s: Method not supported (%" PRIun ")\n",
+			    NAME, IPC_GET_IMETHOD(call));
 			retval = ENOTSUP;
 			break;
@@ -130,9 +135,9 @@
 	printf("%s: HelenOS IPC Naming Service\n", NAME);
 
-	errno_t rc = service_init();
+	errno_t rc = ns_service_init();
 	if (rc != EOK)
 		return rc;
 
-	rc = clonable_init();
+	rc = ns_clonable_init();
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/ns/service.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -47,7 +47,21 @@
 	service_t service;
 
+	/** Interface hash table */
+	hash_table_t iface_hash_table;
+
+	/** Broker session to the service */
+	async_sess_t *broker_sess;
+} hashed_service_t;
+
+/** Interface hash table item. */
+typedef struct {
+	ht_link_t link;
+
+	/** Interface ID */
+	iface_t iface;
+
 	/** Session to the service */
 	async_sess_t *sess;
-} hashed_service_t;
+} hashed_iface_t;
 
 static size_t service_key_hash(void *key)
@@ -70,4 +84,25 @@
 
 	return service->service == *(service_t *) key;
+}
+
+static size_t iface_key_hash(void *key)
+{
+	return *(iface_t *) key;
+}
+
+static size_t iface_hash(const ht_link_t *item)
+{
+	hashed_iface_t *iface =
+	    hash_table_get_inst(item, hashed_iface_t, link);
+
+	return iface->iface;
+}
+
+static bool iface_key_equal(void *key, const ht_link_t *item)
+{
+	hashed_iface_t *iface =
+	    hash_table_get_inst(item, hashed_iface_t, link);
+
+	return iface->iface == *(iface_t *) key;
 }
 
@@ -81,4 +116,13 @@
 };
 
+/** Operations for interface hash table. */
+static hash_table_ops_t iface_hash_table_ops = {
+	.hash = iface_hash,
+	.key_hash = iface_key_hash,
+	.key_equal = iface_key_equal,
+	.equal = NULL,
+	.remove_callback = NULL
+};
+
 /** Service hash table structure. */
 static hash_table_t service_hash_table;
@@ -94,5 +138,5 @@
 static list_t pending_conn;
 
-errno_t service_init(void)
+errno_t ns_service_init(void)
 {
 	if (!hash_table_create(&service_hash_table, 0, 0,
@@ -107,18 +151,45 @@
 }
 
+static void ns_forward(async_sess_t *sess, ipc_call_t *call, iface_t iface)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	async_forward_fast(call, exch, iface, IPC_GET_ARG3(*call), 0,
+	    IPC_FF_NONE);
+	async_exchange_end(exch);
+}
+
 /** Process pending connection requests */
-void process_pending_conn(void)
+void ns_pending_conn_process(void)
 {
 loop:
 	list_foreach(pending_conn, link, pending_conn_t, pending) {
-		ht_link_t *link = hash_table_find(&service_hash_table, &pending->service);
+		ht_link_t *link =
+		    hash_table_find(&service_hash_table, &pending->service);
 		if (!link)
 			continue;
 
-		hashed_service_t *hashed_service = hash_table_get_inst(link, hashed_service_t, link);
-		async_exch_t *exch = async_exchange_begin(hashed_service->sess);
-		async_forward_fast(&pending->call, exch, pending->iface,
-		    IPC_GET_ARG3(pending->call), 0, IPC_FF_NONE);
-		async_exchange_end(exch);
+		hashed_service_t *hashed_service =
+		    hash_table_get_inst(link, hashed_service_t, link);
+
+		link = hash_table_find(&hashed_service->iface_hash_table,
+		    &pending->iface);
+		if (!link) {
+			if (hashed_service->broker_sess != NULL) {
+				ns_forward(hashed_service->broker_sess, &pending->call,
+				    pending->iface);
+
+				list_remove(&pending->link);
+				free(pending);
+
+				goto loop;
+			}
+
+			continue;
+		}
+
+		hashed_iface_t *hashed_iface =
+		    hash_table_get_inst(link, hashed_iface_t, link);
+
+		ns_forward(hashed_iface->sess, &pending->call, pending->iface);
 
 		list_remove(&pending->link);
@@ -129,17 +200,75 @@
 }
 
+/** Register interface to a service.
+ *
+ * @param service Service to which the interface belongs.
+ * @param iface   Interface to be registered.
+ *
+ * @return Zero on success or a value from @ref errno.h.
+ *
+ */
+static errno_t ns_iface_register(hashed_service_t *hashed_service, iface_t iface)
+{
+	ht_link_t *link = hash_table_find(&hashed_service->iface_hash_table,
+	    &iface);
+	if (link)
+		return EEXIST;
+
+	hashed_iface_t *hashed_iface =
+	    (hashed_iface_t *) malloc(sizeof(hashed_iface_t));
+	if (!hashed_iface)
+		return ENOMEM;
+
+	hashed_iface->iface = iface;
+	hashed_iface->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (hashed_iface->sess == NULL) {
+		free(hashed_iface);
+		return EIO;
+	}
+
+	hash_table_insert(&hashed_service->iface_hash_table,
+	    &hashed_iface->link);
+	return EOK;
+}
+
+/** Register broker to a service.
+ *
+ * @param service Service to which the broker belongs.
+ *
+ * @return Zero on success or a value from @ref errno.h.
+ *
+ */
+static errno_t ns_broker_register(hashed_service_t *hashed_service)
+{
+	if (hashed_service->broker_sess != NULL)
+		return EEXIST;
+
+	hashed_service->broker_sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (hashed_service->broker_sess == NULL)
+		return EIO;
+
+	return EOK;
+}
+
 /** Register service.
  *
  * @param service Service to be registered.
- * @param phone   Phone to be used for connections to the service.
- * @param call    Pointer to call structure.
+ * @param iface   Interface to be registered.
  *
  * @return Zero on success or a value from @ref errno.h.
  *
  */
-errno_t register_service(service_t service, sysarg_t phone, ipc_call_t *call)
-{
-	if (hash_table_find(&service_hash_table, &service))
-		return EEXIST;
+errno_t ns_service_register(service_t service, iface_t iface)
+{
+	ht_link_t *link = hash_table_find(&service_hash_table, &service);
+
+	if (link) {
+		hashed_service_t *hashed_service =
+		    hash_table_get_inst(link, hashed_service_t, link);
+
+		assert(hashed_service->service == service);
+
+		return ns_iface_register(hashed_service, iface);
+	}
 
 	hashed_service_t *hashed_service =
@@ -148,10 +277,80 @@
 		return ENOMEM;
 
+	if (!hash_table_create(&hashed_service->iface_hash_table, 0, 0,
+	    &iface_hash_table_ops)) {
+		free(hashed_service);
+		return ENOMEM;
+	}
+
+	hashed_service->broker_sess = NULL;
 	hashed_service->service = service;
-	hashed_service->sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	if (hashed_service->sess == NULL)
-		return EIO;
+	errno_t rc = ns_iface_register(hashed_service, iface);
+	if (rc != EOK) {
+		free(hashed_service);
+		return rc;
+	}
 
 	hash_table_insert(&service_hash_table, &hashed_service->link);
+	return EOK;
+}
+
+/** Register broker service.
+ *
+ * @param service Broker service to be registered.
+ *
+ * @return Zero on success or a value from @ref errno.h.
+ *
+ */
+errno_t ns_service_register_broker(service_t service)
+{
+	ht_link_t *link = hash_table_find(&service_hash_table, &service);
+
+	if (link) {
+		hashed_service_t *hashed_service =
+		    hash_table_get_inst(link, hashed_service_t, link);
+
+		assert(hashed_service->service == service);
+
+		return ns_broker_register(hashed_service);
+	}
+
+	hashed_service_t *hashed_service =
+	    (hashed_service_t *) malloc(sizeof(hashed_service_t));
+	if (!hashed_service)
+		return ENOMEM;
+
+	if (!hash_table_create(&hashed_service->iface_hash_table, 0, 0,
+	    &iface_hash_table_ops)) {
+		free(hashed_service);
+		return ENOMEM;
+	}
+
+	hashed_service->broker_sess = NULL;
+	hashed_service->service = service;
+	errno_t rc = ns_broker_register(hashed_service);
+	if (rc != EOK) {
+		free(hashed_service);
+		return rc;
+	}
+
+	hash_table_insert(&service_hash_table, &hashed_service->link);
+	return EOK;
+}
+
+/** Add pending connection */
+static errno_t ns_pending_conn_add(service_t service, iface_t iface,
+    ipc_call_t *call)
+{
+	pending_conn_t *pending =
+	    (pending_conn_t *) malloc(sizeof(pending_conn_t));
+	if (!pending)
+		return ENOMEM;
+
+	link_initialize(&pending->link);
+	pending->service = service;
+	pending->iface = iface;
+	pending->call = *call;
+
+	list_append(&pending->link, &pending_conn);
 	return EOK;
 }
@@ -166,5 +365,5 @@
  *
  */
-void connect_to_service(service_t service, iface_t iface, ipc_call_t *call)
+void ns_service_forward(service_t service, iface_t iface, ipc_call_t *call)
 {
 	sysarg_t flags = IPC_GET_ARG4(*call);
@@ -175,28 +374,44 @@
 		if (flags & IPC_FLAG_BLOCKING) {
 			/* Blocking connection, add to pending list */
-			pending_conn_t *pending =
-			    (pending_conn_t *) malloc(sizeof(pending_conn_t));
-			if (!pending) {
-				retval = ENOMEM;
-				goto out;
-			}
-
-			link_initialize(&pending->link);
-			pending->service = service;
-			pending->iface = iface;
-			pending->call = *call;
-
-			list_append(&pending->link, &pending_conn);
+			errno_t rc = ns_pending_conn_add(service, iface, call);
+			if (rc == EOK)
+				return;
+
+			retval = rc;
+			goto out;
+		}
+
+		retval = ENOENT;
+		goto out;
+	}
+
+	hashed_service_t *hashed_service =
+	    hash_table_get_inst(link, hashed_service_t, link);
+
+	link = hash_table_find(&hashed_service->iface_hash_table, &iface);
+	if (!link) {
+		if (hashed_service->broker_sess != NULL) {
+			ns_forward(hashed_service->broker_sess, call, iface);
 			return;
 		}
 
+		if (flags & IPC_FLAG_BLOCKING) {
+			/* Blocking connection, add to pending list */
+			errno_t rc = ns_pending_conn_add(service, iface, call);
+			if (rc == EOK)
+				return;
+
+			retval = rc;
+			goto out;
+		}
+
 		retval = ENOENT;
 		goto out;
 	}
 
-	hashed_service_t *hashed_service = hash_table_get_inst(link, hashed_service_t, link);
-	async_exch_t *exch = async_exchange_begin(hashed_service->sess);
-	async_forward_fast(call, exch, iface, IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
-	async_exchange_end(exch);
+	hashed_iface_t *hashed_iface =
+	    hash_table_get_inst(link, hashed_iface_t, link);
+
+	ns_forward(hashed_iface->sess, call, iface);
 	return;
 
Index: uspace/srv/ns/service.h
===================================================================
--- uspace/srv/ns/service.h	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/ns/service.h	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -38,9 +38,10 @@
 #include <abi/ipc/interfaces.h>
 
-extern errno_t service_init(void);
-extern void process_pending_conn(void);
+extern errno_t ns_service_init(void);
+extern void ns_pending_conn_process(void);
 
-extern errno_t register_service(service_t, sysarg_t, ipc_call_t *);
-extern void connect_to_service(service_t, iface_t, ipc_call_t *);
+extern errno_t ns_service_register(service_t, iface_t);
+extern errno_t ns_service_register_broker(service_t);
+extern void ns_service_forward(service_t, iface_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/vfs/vfs.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -117,19 +117,4 @@
 
 	/*
-	 * Create a port for the pager.
-	 */
-	port_id_t port;
-	errno_t rc = async_create_port(INTERFACE_PAGER, vfs_pager, NULL, &port);
-	if (rc != EOK) {
-		printf("%s: Cannot create pager port: %s\n", NAME, str_error(rc));
-		return rc;
-	}
-
-	/*
-	 * Set a connection handling function/fibril.
-	 */
-	async_set_fallback_port_handler(vfs_connection, NULL);
-
-	/*
 	 * Subscribe to notifications.
 	 */
@@ -140,7 +125,19 @@
 	 * Register at the naming service.
 	 */
-	rc = service_register(SERVICE_VFS);
+	errno_t rc = service_register(SERVICE_VFS, INTERFACE_PAGER, vfs_pager, NULL);
 	if (rc != EOK) {
-		printf("%s: Cannot register VFS service: %s\n", NAME, str_error(rc));
+		printf("%s: Cannot register VFS pager port: %s\n", NAME, str_error(rc));
+		return rc;
+	}
+
+	rc = service_register(SERVICE_VFS, INTERFACE_VFS, vfs_connection, NULL);
+	if (rc != EOK) {
+		printf("%s: Cannot register VFS file system port: %s\n", NAME, str_error(rc));
+		return rc;
+	}
+
+	rc = service_register(SERVICE_VFS, INTERFACE_VFS_DRIVER, vfs_connection, NULL);
+	if (rc != EOK) {
+		printf("%s: Cannot register VFS driver port: %s\n", NAME, str_error(rc));
 		return rc;
 	}
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision edc64c03b91257aecae0d60886bd274aea300bf9)
+++ uspace/srv/vfs/vfs_register.c	(revision 9b1baac695a63afb1850cd44050a52e06635cbd2)
@@ -187,4 +187,7 @@
 	}
 
+	/* FIXME: Work around problem with callback sessions */
+	async_sess_args_set(fs_info->sess, INTERFACE_VFS_DRIVER_CB, 0, 0);
+
 	dprintf("Callback connection to FS created.\n");
 
