diff --git a/Knot.files b/Knot.files
index e5a0c40456815bd616505c48b0841f03d4ed0968..cf9458506f8e7731d63a2e70e7541ee3dba8e53a 100644
--- a/Knot.files
+++ b/Knot.files
@@ -168,6 +168,12 @@ src/libknot/nameserver/chaos.c
 src/libknot/nameserver/chaos.h
 src/libknot/nameserver/internet.c
 src/libknot/nameserver/internet.h
+src/libknot/nameserver/axfr.c
+src/libknot/nameserver/axfr.h
+src/libknot/nameserver/ixfr.c
+src/libknot/nameserver/ixfr.h
+src/libknot/nameserver/update.c
+src/libknot/nameserver/update.h
 src/libknot/nameserver/name-server.c
 src/libknot/nameserver/name-server.h
 src/libknot/nameserver/ns_proc_query.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 48f1b177a6412ab60a6afdc3bc53554ed654a581..b78e3c0c1c38a90f48b0329e43c76b962252dd6a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -124,6 +124,12 @@ libknot_la_SOURCES =				\
 	libknot/nameserver/chaos.c		\
 	libknot/nameserver/internet.h	\
 	libknot/nameserver/internet.c	\
+	libknot/nameserver/axfr.h	\
+	libknot/nameserver/axfr.c	\
+	libknot/nameserver/ixfr.h	\
+	libknot/nameserver/ixfr.c	\
+	libknot/nameserver/update.h	\
+	libknot/nameserver/update.c	\
 	libknot/nameserver/ns_proc_query.h	\
 	libknot/nameserver/ns_proc_query.c	\
 	libknot/updates/changesets.h		\
diff --git a/src/libknot/nameserver/axfr.c b/src/libknot/nameserver/axfr.c
new file mode 100644
index 0000000000000000000000000000000000000000..61dcdcfe96e54449bdf31c68b8802e074c5caaa2
--- /dev/null
+++ b/src/libknot/nameserver/axfr.c
@@ -0,0 +1,10 @@
+#include <config.h>
+
+#include "libknot/nameserver/axfr.h"
+#include "libknot/nameserver/ns_proc_query.h"
+
+int axfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata)
+{
+	qdata->rcode = KNOT_RCODE_NOTIMPL;
+	return NS_PROC_FAIL;
+}
diff --git a/src/libknot/nameserver/axfr.h b/src/libknot/nameserver/axfr.h
new file mode 100644
index 0000000000000000000000000000000000000000..e4b4729c5f4c164708a69f11e6d7a5683b62059e
--- /dev/null
+++ b/src/libknot/nameserver/axfr.h
@@ -0,0 +1,40 @@
+/*!
+ * \file axfr.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief AXFR processing.
+ *
+ * \addtogroup query_processing
+ * @{
+ */
+/*  Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _KNOT_AXFR_H_
+#define _KNOT_AXFR_H_
+
+#include "libknot/packet/pkt.h"
+#include "libknot/zone/zonedb.h"
+#include "libknot/nameserver/name-server.h"
+
+struct query_data;
+
+int axfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata);
+
+#endif /* _KNOT_AXFR_H_ */
+
+/*! @} */
diff --git a/src/libknot/nameserver/internet.h b/src/libknot/nameserver/internet.h
new file mode 100644
index 0000000000000000000000000000000000000000..d073bcd2fcd2f236b9a5c1caad2f25435f6b96a2
--- /dev/null
+++ b/src/libknot/nameserver/internet.h
@@ -0,0 +1,53 @@
+/*!
+ * \file internet.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief IN zone lookup.
+ *
+ * \addtogroup query_processing
+ * @{
+ */
+/*  Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _KNOT_INTERNET_H_
+#define _KNOT_INTERNET_H_
+
+#include "libknot/packet/pkt.h"
+#include "libknot/zone/zonedb.h"
+#include "libknot/nameserver/name-server.h"
+
+/* Query data (from query processing). */
+struct query_data;
+
+/*!
+ * \brief Answer query from IN class zone.
+ */
+int internet_answer(knot_pkt_t *resp, struct query_data *qdata);
+
+/*!
+ * \brief Answer IN class zone NOTIFY message (RFC1996).
+ * \param response
+ * \param ns
+ * \param qdata
+ * \return
+ */
+int internet_notify(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata);
+
+#endif /* _KNOT_INTERNET_H_ */
+
+/*! @} */
diff --git a/src/libknot/nameserver/ixfr.c b/src/libknot/nameserver/ixfr.c
new file mode 100644
index 0000000000000000000000000000000000000000..560f867a600449a0b1ace314c15c6c0c2250351b
--- /dev/null
+++ b/src/libknot/nameserver/ixfr.c
@@ -0,0 +1,42 @@
+#include <config.h>
+
+#include "libknot/nameserver/ixfr.h"
+#include "libknot/nameserver/ns_proc_query.h"
+#include "common/descriptor.h"
+
+int ixfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata)
+{
+	qdata->rcode = KNOT_RCODE_NOTIMPL;
+	return NS_PROC_FAIL;
+}
+
+int ixfr_answer_soa(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata)
+{
+	if (pkt == NULL || ns == NULL || qdata == NULL) {
+		return NS_PROC_FAIL;
+	}
+
+	/* Check zone state. */
+	const knot_zone_t *zone = pkt->zone;
+	switch(knot_zone_state(zone)) {
+	case KNOT_EOK:
+		break;
+	case KNOT_ENOENT:
+		qdata->rcode = KNOT_RCODE_NOTAUTH;
+		return NS_PROC_FAIL;
+	default:
+		qdata->rcode = KNOT_RCODE_SERVFAIL;
+		return NS_PROC_FAIL;
+	}
+
+	/* Guaranteed to have zone contents. */
+	const knot_node_t *apex = zone->contents->apex;
+	const knot_rrset_t *soa_rr = knot_node_rrset(apex, KNOT_RRTYPE_SOA);
+	int ret = knot_pkt_put(pkt, 0, soa_rr, 0);
+	if (ret != KNOT_EOK) {
+		qdata->rcode = KNOT_RCODE_SERVFAIL;
+		return NS_PROC_FAIL;
+	}
+
+	return NS_PROC_FINISH;
+}
diff --git a/src/libknot/nameserver/ixfr.h b/src/libknot/nameserver/ixfr.h
new file mode 100644
index 0000000000000000000000000000000000000000..c65db7258874645ce4c32e24e56e4f4a3e3897bb
--- /dev/null
+++ b/src/libknot/nameserver/ixfr.h
@@ -0,0 +1,42 @@
+/*!
+ * \file ixfr.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief IXFR processing.
+ *
+ * \addtogroup query_processing
+ * @{
+ */
+/*  Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _KNOT_IXFR_H_
+#define _KNOT_IXFR_H_
+
+#include "libknot/packet/pkt.h"
+#include "libknot/zone/zonedb.h"
+#include "libknot/nameserver/name-server.h"
+
+struct query_data;
+
+int ixfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata);
+
+int ixfr_answer_soa(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata);
+
+#endif /* _KNOT_IXFR_H_ */
+
+/*! @} */
diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c
index 219f37a62cabc17e13f387e4595ee2796aab09a4..3006c5b84c784706db1cabe2435a98d420b62428 100644
--- a/src/libknot/nameserver/name-server.c
+++ b/src/libknot/nameserver/name-server.c
@@ -4110,6 +4110,8 @@ int ns_proc_begin(ns_proc_context_t *ctx, const ns_proc_module_t *module)
 	/* #10 implement */
 	ctx->module = module;
 	ctx->state = module->begin(ctx);
+
+	dbg_ns("%s -> %d\n", __func__, ctx->state);
 	return ctx->state;
 }
 
@@ -4117,6 +4119,8 @@ int ns_proc_reset(ns_proc_context_t *ctx)
 {
 	/* #10 implement */
 	ctx->state = ctx->module->reset(ctx);
+
+	dbg_ns("%s -> %d\n", __func__, ctx->state);
 	return ctx->state;
 }
 
@@ -4124,13 +4128,25 @@ int ns_proc_finish(ns_proc_context_t *ctx)
 {
 	/* #10 implement */
 	ctx->state = ctx->module->finish(ctx);
+
+	/* Free packet buffers. */
+	knot_pkt_free(&ctx->in);
+	knot_pkt_free(&ctx->out);
+
+	dbg_ns("%s -> %d\n", __func__, ctx->state);
 	return ctx->state;
 }
 
 int ns_proc_in(const uint8_t *wire, uint16_t wire_len, ns_proc_context_t *ctx)
 {
 	/* #10 implement */
-	knot_pkt_t *pkt = knot_pkt_new((uint8_t *)wire, wire_len, &ctx->mm);
+	if (ctx->in == NULL) {
+		ctx->in = knot_pkt_new((uint8_t *)wire, wire_len, &ctx->mm);
+	} else {
+		knot_pkt_reset(ctx->in, (uint8_t *)wire, wire_len);
+	}
+
+	knot_pkt_t *pkt = ctx->in;
 	knot_pkt_parse(pkt, 0);
 
 	switch(ctx->state) {
@@ -4140,13 +4156,20 @@ int ns_proc_in(const uint8_t *wire, uint16_t wire_len, ns_proc_context_t *ctx)
 		return NS_PROC_NOOP;
 	}
 
+	dbg_ns("%s -> %d\n", __func__, ctx->state);
 	return ctx->state;
 }
 
 int ns_proc_out(uint8_t *wire, uint16_t *wire_len, ns_proc_context_t *ctx)
 {
 	/* #10 implement */
-	knot_pkt_t *pkt = knot_pkt_new(wire, *wire_len, &ctx->mm);
+	if (ctx->out == NULL) {
+		ctx->out = knot_pkt_new(wire, *wire_len, &ctx->mm);
+	} else {
+		knot_pkt_reset(ctx->out, wire, *wire_len);
+	}
+
+	knot_pkt_t *pkt = ctx->out;
 
 	switch(ctx->state) {
 	case NS_PROC_FULL: ctx->state = ctx->module->out(pkt, ctx); break;
@@ -4158,9 +4181,7 @@ int ns_proc_out(uint8_t *wire, uint16_t *wire_len, ns_proc_context_t *ctx)
 
 	*wire_len = pkt->size;
 
-	/* Free packet. */
-	knot_pkt_free(&pkt);
-
+	dbg_ns("%s -> %d\n", __func__, ctx->state);
 	return ctx->state;
 }
 
diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h
index db498369330afe840743e035aa6a45f465a4b8f1..a64e007bf70447efbb520d539d35f754b7017b62 100644
--- a/src/libknot/nameserver/name-server.h
+++ b/src/libknot/nameserver/name-server.h
@@ -448,8 +448,10 @@ enum ns_proc_state {
 };
 
 enum ns_proc_flag {
-	NS_NOFLAG          = 0,
+	/* Common flags. */
 	NS_PKTSIZE_NOLIMIT = 1 << 0, /* Don't limit packet size (for TCP). */
+	/* Module-specific flags. */
+	NS_PROCFLAG        = 1 << 8
 };
 
 struct ns_proc_module;
@@ -460,6 +462,7 @@ typedef struct ns_proc_context
 	uint16_t type;
 	uint16_t flags;
 	void *data;
+	knot_pkt_t *in, *out;
 
 	int state;
 	knot_nameserver_t *ns;
diff --git a/src/libknot/nameserver/ns_proc_query.c b/src/libknot/nameserver/ns_proc_query.c
index 493c8a5d1154827b2b4de5688762682871b678e9..4efe042a282adbaa865054148bfa461798746ba1 100644
--- a/src/libknot/nameserver/ns_proc_query.c
+++ b/src/libknot/nameserver/ns_proc_query.c
@@ -5,11 +5,16 @@
 #include "libknot/nameserver/ns_proc_query.h"
 #include "libknot/consts.h"
 #include "libknot/util/debug.h"
-#include "libknot/nameserver/chaos.h"
-#include "libknot/nameserver/internet.h"
 #include "libknot/common.h"
 #include "common/descriptor.h"
 
+/*! \todo Move close to server when done. */
+#include "libknot/nameserver/chaos.h"
+#include "libknot/nameserver/internet.h"
+#include "libknot/nameserver/axfr.h"
+#include "libknot/nameserver/ixfr.h"
+#include "libknot/nameserver/update.h"
+
 /* Forward decls. */
 static int tsig_check(knot_pkt_t *pkt);
 static const knot_zone_t *answer_zone_find(knot_pkt_t *pkt, knot_zonedb_t *zonedb);
@@ -52,7 +57,7 @@ int ns_proc_query_reset(ns_proc_context_t *ctx)
 	/* Clear */
 	assert(ctx);
 	struct query_data *data = QUERY_DATA(ctx);
-	knot_pkt_free(&data->pkt);
+	data->pkt = NULL;
 	data->rcode = KNOT_RCODE_NOERROR;
 	data->rcode_tsig = 0;
 	data->node = data->encloser = data->previous = NULL;
@@ -81,9 +86,12 @@ int ns_proc_query_in(knot_pkt_t *pkt, ns_proc_context_t *ctx)
 	switch(query_type) {
 	case KNOT_QUERY_NORMAL:
 	case KNOT_QUERY_NOTIFY:
+	case KNOT_QUERY_AXFR:
+	case KNOT_QUERY_IXFR:
+	case KNOT_QUERY_UPDATE:
 		break; /* Supported. */
 	default:
-		dbg_ns("%s: query_type(%hu) NOT SUPPORTED", __func__, query_type);
+		dbg_ns("%s: query_type(%hu) NOT SUPPORTED\n", __func__, query_type);
 		return NS_PROC_NOOP; /* Refuse to process. */
 	}
 
@@ -187,6 +195,26 @@ int query_internet(knot_pkt_t *pkt, ns_proc_context_t *ctx)
 	case KNOT_QUERY_NOTIFY:
 		next_state = internet_notify(pkt, ctx->ns, data);
 		break;
+	case KNOT_QUERY_AXFR:
+		if (ctx->flags & NS_QUERY_NO_AXFR) {
+			/* AXFR disabled, respond with NOTIMPL. */
+			data->rcode = KNOT_RCODE_NOTIMPL;
+			next_state = NS_PROC_FAIL;
+		} else {
+			next_state = axfr_answer(pkt, ctx->ns, data);
+		}
+		break;
+	case KNOT_QUERY_IXFR:
+		if (ctx->flags & NS_QUERY_NO_IXFR) {
+			/* IXFR disabled, respond with SOA. */
+			next_state = ixfr_answer_soa(pkt, ctx->ns, data);
+		} else {
+			next_state = ixfr_answer(pkt, ctx->ns, data);
+		}
+		break;
+	case KNOT_QUERY_UPDATE:
+		next_state = update_answer(pkt, ctx->ns, data);
+		break;
 	default:
 		assert(0); /* Should be caught earlier. */
 		data->rcode = KNOT_RCODE_SERVFAIL;
@@ -271,7 +299,7 @@ static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, ns_proc_context_t
 	/* Copy DO bit if set (DNSSEC requested). */
 	if (knot_pkt_have_dnssec(query)) {
 		dbg_ns("%s: setting DO=1 in OPT RR\n", __func__);
-		knot_edns_set_do(&(resp)->opt_rr);
+		knot_edns_set_do(&resp->opt_rr);
 	}
 	/* Set minimal supported size from EDNS(0). */
 	if (!(ctx->flags & NS_PKTSIZE_NOLIMIT)) {
diff --git a/src/libknot/nameserver/ns_proc_query.h b/src/libknot/nameserver/ns_proc_query.h
index b03185815876e3afd414d46d15fb1bf01c39d3a8..a1c3de4beabda0834bbba2d1c7ead98b57082c7e 100644
--- a/src/libknot/nameserver/ns_proc_query.h
+++ b/src/libknot/nameserver/ns_proc_query.h
@@ -29,10 +29,17 @@
 
 #include "libknot/nameserver/name-server.h"
 
+/* Query processing module implementation. */
 extern const ns_proc_module_t _ns_proc_query;
 #define NS_PROC_QUERY (&_ns_proc_query)
 #define NS_PROC_QUERY_ID 1
 
+/* Query processing flags. */
+enum ns_proc_query_flag {
+	NS_QUERY_NO_AXFR = NS_PROCFLAG << 1, /* Don't process AXFR */
+	NS_QUERY_NO_IXFR = NS_PROCFLAG << 2  /* Don't process IXFR */
+};
+
 struct query_data {
 	uint16_t rcode;
 	uint16_t rcode_tsig;
diff --git a/src/libknot/nameserver/update.c b/src/libknot/nameserver/update.c
new file mode 100644
index 0000000000000000000000000000000000000000..bc8be46d20b23525c6aa58d7966259538ef6f323
--- /dev/null
+++ b/src/libknot/nameserver/update.c
@@ -0,0 +1,10 @@
+#include <config.h>
+
+#include "libknot/nameserver/update.h"
+#include "libknot/nameserver/ns_proc_query.h"
+
+int update_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata)
+{
+	qdata->rcode = KNOT_RCODE_NOTIMPL;
+	return NS_PROC_FAIL;
+}
diff --git a/src/libknot/nameserver/update.h b/src/libknot/nameserver/update.h
new file mode 100644
index 0000000000000000000000000000000000000000..01788261f901e8198fd93236cd273cb80d43b5b5
--- /dev/null
+++ b/src/libknot/nameserver/update.h
@@ -0,0 +1,40 @@
+/*!
+ * \file update.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief DDNS UPDATE processing.
+ *
+ * \addtogroup query_processing
+ * @{
+ */
+/*  Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _KNOT_UPDATE_H_
+#define _KNOT_UPDATE_H_
+
+#include "libknot/packet/pkt.h"
+#include "libknot/zone/zonedb.h"
+#include "libknot/nameserver/name-server.h"
+
+struct query_data;
+
+int update_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata);
+
+#endif /* _KNOT_UPDATE_H_ */
+
+/*! @} */