Index: uspace/srv/net/dnsrsrv/dnsrsrv.c
===================================================================
--- uspace/srv/net/dnsrsrv/dnsrsrv.c	(revision fff7ef4b73612f7e181f2ba2f74883b9de53f46f)
+++ uspace/srv/net/dnsrsrv/dnsrsrv.c	(revision 48171fc4f90f30adbbe6e443e48ddd9fb7ffdcf4)
@@ -47,4 +47,5 @@
 #include "dns_std.h"
 #include "query.h"
+#include "transport.h"
 
 #define NAME  "dnsres"
@@ -54,11 +55,19 @@
 static int dnsr_init(void)
 {
+	int rc;
 	log_msg(LOG_DEFAULT, LVL_DEBUG, "dnsr_init()");
 
+	rc = transport_init();
+	if (rc != EOK) {
+		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing tarnsport.");
+		return EIO;
+	}
+
 	async_set_client_connection(dnsr_client_conn);
 
-	int rc = loc_server_register(NAME);
+	rc = loc_server_register(NAME);
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering server (%d).", rc);
+		transport_fini();
 		return EEXIST;
 	}
@@ -68,4 +77,5 @@
 	if (rc != EOK) {
 		log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
+		transport_fini();
 		return EEXIST;
 	}
Index: uspace/srv/net/dnsrsrv/query.c
===================================================================
--- uspace/srv/net/dnsrsrv/query.c	(revision fff7ef4b73612f7e181f2ba2f74883b9de53f46f)
+++ uspace/srv/net/dnsrsrv/query.c	(revision 48171fc4f90f30adbbe6e443e48ddd9fb7ffdcf4)
@@ -35,4 +35,5 @@
 
 #include <errno.h>
+#include <io/log.h>
 #include <mem.h>
 #include <stdlib.h>
@@ -47,8 +48,7 @@
 static uint16_t msg_id;
 
-#include <stdio.h>
 int dns_name2host(const char *name, dns_host_info_t **rinfo)
 {
-	dns_message_t msg;
+	dns_message_t *msg;
 	dns_message_t *amsg;
 	dns_question_t question;
@@ -60,25 +60,28 @@
 	question.qclass = DC_IN;
 
-	memset(&msg, 0, sizeof(msg));
+	msg = calloc(1, sizeof(dns_message_t));
+	if (msg == NULL)
+		return ENOMEM;
 
-	list_initialize(&msg.question);
-	list_append(&question.msg, &msg.question);
+	list_initialize(&msg->question);
+	list_append(&question.msg, &msg->question);
 
-	msg.id = msg_id++;
-	msg.qr = QR_QUERY;
-	msg.opcode = OPC_QUERY;
-	msg.aa = false;
-	msg.tc = false;
-	msg.rd = true;
-	msg.ra = false;
+	msg->id = msg_id++;
+	msg->qr = QR_QUERY;
+	msg->opcode = OPC_QUERY;
+	msg->aa = false;
+	msg->tc = false;
+	msg->rd = true;
+	msg->ra = false;
 
-	rc = dns_request(&msg, &amsg);
-	if (rc != EOK)
+	rc = dns_request(msg, &amsg);
+	if (rc != EOK) {
 		return rc;
+	}
 
 	list_foreach(amsg->answer, link) {
 		dns_rr_t *rr = list_get_instance(link, dns_rr_t, msg);
 
-		printf(" - '%s' %u/%u, dsize %u\n",
+		log_msg(LOG_DEFAULT, LVL_DEBUG, " - '%s' %u/%u, dsize %u\n",
 			rr->name, rr->rtype, rr->rclass, rr->rdata_size);
 
@@ -94,5 +97,6 @@
 			info->name = str_dup(rr->name);
 			info->addr.ipv4 = dns_uint32_t_decode(rr->rdata, rr->rdata_size);
-			printf("info->addr = %x\n", info->addr.ipv4);
+			log_msg(LOG_DEFAULT, LVL_DEBUG, "info->addr = %x\n",
+			    info->addr.ipv4);
 
 			dns_message_destroy(amsg);
@@ -102,6 +106,7 @@
 	}
 
+	dns_message_destroy(msg);
 	dns_message_destroy(amsg);
-	printf("no A/IN found, fail\n");
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "No A/IN found, fail\n");
 
 	return EIO;
Index: uspace/srv/net/dnsrsrv/transport.c
===================================================================
--- uspace/srv/net/dnsrsrv/transport.c	(revision fff7ef4b73612f7e181f2ba2f74883b9de53f46f)
+++ uspace/srv/net/dnsrsrv/transport.c	(revision 48171fc4f90f30adbbe6e443e48ddd9fb7ffdcf4)
@@ -34,8 +34,12 @@
  */
 
+#include <adt/list.h>
 #include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
 #include <net/in.h>
 #include <net/inet.h>
 #include <net/socket.h>
+#include <stdbool.h>
 #include <stdlib.h>
 
@@ -44,78 +48,207 @@
 #include "transport.h"
 
-#include <stdio.h>
-
 #define RECV_BUF_SIZE 4096
 
+/** Request timeout (microseconds) */
+#define REQ_TIMEOUT (5*1000*1000)
+
+typedef struct {
+	link_t lreq;
+	dns_message_t *req;
+	dns_message_t *resp;
+
+	bool done;
+	fibril_condvar_t done_cv;
+	fibril_mutex_t done_lock;
+
+	int status;
+} trans_req_t;
+
 static uint8_t recv_buf[RECV_BUF_SIZE];
+static fid_t recv_fid;
+static int transport_fd = -1;
+
+/** Outstanding requests */
+static LIST_INITIALIZE(treq_list);
+static FIBRIL_MUTEX_INITIALIZE(treq_lock);
+
+static int transport_recv_fibril(void *arg);
+
+int transport_init(void)
+{
+	struct sockaddr_in laddr;
+	int fd;
+	fid_t fid;
+	int rc;
+
+	laddr.sin_family = AF_INET;
+	laddr.sin_port = htons(12345);
+	laddr.sin_addr.s_addr = INADDR_ANY;
+
+	fd = -1;
+
+	fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (fd < 0) {
+		rc = EIO;
+		goto error;
+	}
+
+	rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
+	if (rc != EOK)
+		goto error;
+
+	transport_fd = fd;
+
+	fid = fibril_create(transport_recv_fibril, NULL);
+	if (fid == 0)
+		goto error;
+
+	fibril_add_ready(fid);
+	recv_fid = fid;
+	return EOK;
+error:
+	log_msg(LOG_DEFAULT, LVL_ERROR, "Failed initializing network socket.\n");
+	if (fd >= 0)
+		closesocket(fd);
+	return rc;
+}
+
+void transport_fini(void)
+{
+	if (transport_fd >= 0)
+		closesocket(transport_fd);
+}
+
+static trans_req_t *treq_create(dns_message_t *req)
+{
+	trans_req_t *treq;
+
+	treq = calloc(1, sizeof(trans_req_t));
+	if (treq == NULL)
+		return NULL;
+
+	treq->req = req;
+	treq->resp = NULL;
+	treq->done = false;
+	fibril_condvar_initialize(&treq->done_cv);
+	fibril_mutex_initialize(&treq->done_lock);
+
+	fibril_mutex_lock(&treq_lock);
+	list_append(&treq->lreq, &treq_list);
+	fibril_mutex_unlock(&treq_lock);
+
+	return treq;
+}
+
+static void treq_destroy(trans_req_t *treq)
+{
+	if (link_in_use(&treq->lreq))
+		list_remove(&treq->lreq);
+	free(treq);
+}
+
+static trans_req_t *treq_match_resp(dns_message_t *resp)
+{
+	assert(fibril_mutex_is_locked(&treq_lock));
+
+	list_foreach(treq_list, link) {
+		trans_req_t *treq = list_get_instance(link, trans_req_t, lreq);
+
+		if (treq->req->id == resp->id) {
+			/* Match */
+			return treq;
+		}
+	}
+
+	return NULL;
+}
+
+static void treq_complete(trans_req_t *treq, dns_message_t *resp)
+{
+	fibril_mutex_lock(&treq->done_lock);
+	treq->done = true;
+	treq->status = EOK;
+	treq->resp = resp;
+	fibril_mutex_unlock(&treq->done_lock);
+
+	fibril_condvar_broadcast(&treq->done_cv);
+}
 
 int dns_request(dns_message_t *req, dns_message_t **rresp)
 {
-	dns_message_t *resp;
 	int rc;
 	void *req_data;
 	size_t req_size;
 	struct sockaddr_in addr;
-	struct sockaddr_in laddr;
+	trans_req_t *treq;
+
+	req_data = NULL;
+	treq = NULL;
+
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(53);
+	addr.sin_addr.s_addr = htonl((10 << 24) | (0 << 16) | (0 << 8) | 138);
+
+	rc = dns_message_encode(req, &req_data, &req_size);
+	if (rc != EOK)
+		goto error;
+
+	rc = sendto(transport_fd, req_data, req_size, 0,
+	    (struct sockaddr *)&addr, sizeof(addr));
+	if (rc != EOK)
+		goto error;
+
+	treq = treq_create(req);
+	if (treq == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	fibril_mutex_lock(&treq->done_lock);
+	while (treq->done != true) {
+		rc = fibril_condvar_wait_timeout(&treq->done_cv, &treq->done_lock,
+		    REQ_TIMEOUT);
+		if (rc == ETIMEOUT) {
+			fibril_mutex_unlock(&treq->done_lock);
+			rc = EIO;
+			goto error;
+		}
+	}
+
+	fibril_mutex_unlock(&treq->done_lock);
+
+	if (treq->status != EOK) {
+		rc = treq->status;
+		goto error;
+	}
+
+	*rresp = treq->resp;
+	treq_destroy(treq);
+	free(req_data);
+	return EOK;
+error:
+	if (treq != NULL)
+		treq_destroy(treq);
+	free(req_data);
+	return rc;
+}
+
+static int transport_recv_msg(dns_message_t **rresp)
+{
 	struct sockaddr_in src_addr;
 	socklen_t src_addr_size;
 	size_t recv_size;
-	int fd;
-	int i;
-
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(53);
-	addr.sin_addr.s_addr = htonl((10 << 24) | (0 << 16) | (0 << 8) | 138);
-
-	laddr.sin_family = AF_INET;
-	laddr.sin_port = htons(12345);
-	laddr.sin_addr.s_addr = INADDR_ANY;
-
-	req_data = NULL;
-	fd = -1;
-
-	rc = dns_message_encode(req, &req_data, &req_size);
-	if (rc != EOK)
-		goto error;
-
-	fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (fd < 0) {
-		rc = EIO;
-		goto error;
-	}
-
-	rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
-	if (rc != EOK)
-		goto error;
-
-	printf("fd=%d req_data=%p, req_size=%zu\n", fd, req_data, req_size);
-	rc = sendto(fd, req_data, req_size, 0, (struct sockaddr *)&addr,
-	    sizeof(addr));
-	if (rc != EOK)
-		goto error;
+	dns_message_t *resp;
+	int rc;
 
 	src_addr_size = sizeof(src_addr);
-	rc = recvfrom(fd, recv_buf, RECV_BUF_SIZE, 0,
+	rc = recvfrom(transport_fd, recv_buf, RECV_BUF_SIZE, 0,
 	    (struct sockaddr *)&src_addr, &src_addr_size);
 	if (rc < 0) {
-		printf("recvfrom returns error - %d\n", rc);
+		log_msg(LOG_DEFAULT, LVL_ERROR, "recvfrom returns error - %d\n", rc);
 		goto error;
 	}
 
 	recv_size = (size_t)rc;
-
-	printf("received %d bytes\n", (int)recv_size);
-	for (i = 0; i < (int)recv_size; i++) {
-		if (recv_buf[i] >= 32 && recv_buf[i] < 127)
-			printf("%c", recv_buf[i]);
-		else
-			printf("?");
-	}
-	printf("\n");
-
-	printf("close socket\n");
-	closesocket(fd);
-	printf("free req_data\n");
-	free(req_data);
 
 	rc = dns_message_decode(recv_buf, recv_size, &resp);
@@ -129,11 +262,34 @@
 
 error:
-	if (req_data != NULL)
-		free(req_data);
-	if (fd >= 0)
-		closesocket(fd);
 	return rc;
 }
 
+static int transport_recv_fibril(void *arg)
+{
+	dns_message_t *resp;
+	trans_req_t *treq;
+	int rc;
+
+	while (true) {
+		rc = transport_recv_msg(&resp);
+		if (rc != EOK)
+			continue;
+
+		fibril_mutex_lock(&treq_lock);
+		treq = treq_match_resp(resp);
+		if (treq == NULL) {
+			fibril_mutex_unlock(&treq_lock);
+			continue;
+		}
+
+		list_remove(&treq->lreq);
+		fibril_mutex_unlock(&treq_lock);
+
+		treq_complete(treq, resp);
+	}
+
+	return 0;
+}
+
 /** @}
  */
Index: uspace/srv/net/dnsrsrv/transport.h
===================================================================
--- uspace/srv/net/dnsrsrv/transport.h	(revision fff7ef4b73612f7e181f2ba2f74883b9de53f46f)
+++ uspace/srv/net/dnsrsrv/transport.h	(revision 48171fc4f90f30adbbe6e443e48ddd9fb7ffdcf4)
@@ -39,4 +39,6 @@
 #include "dns_type.h"
 
+extern int transport_init(void);
+extern void transport_fini(void);
 extern int dns_request(dns_message_t *, dns_message_t **);
 
