diff --git a/.gitignore b/.gitignore
index c6cb5692c43ae14dea5ddbb73be0f7e7f158817d..1b897e7f53499b827acbc00e93bb38ed91bbf067 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,5 +50,6 @@ m4/ltversion.m4
 m4/lt~obsolete.m4
 src/unittests-xfr
 INSTALL
+kdig
 khost
 knsupdate
diff --git a/Knot.files b/Knot.files
index f5ff754baf23abb4e2e1bd8b34d22ad0b7a77d33..e33b84e4084772c993f08577288cf9594ee36ac4 100644
--- a/Knot.files
+++ b/Knot.files
@@ -283,6 +283,11 @@ src/utils/common/netio.c
 src/utils/common/netio.h
 src/utils/common/rr-serialize.c
 src/utils/common/rr-serialize.h
+src/utils/dig/dig_exec.c
+src/utils/dig/dig_exec.h
+src/utils/dig/dig_main.c
+src/utils/dig/dig_params.c
+src/utils/dig/dig_params.h
 src/utils/host/host_exec.c
 src/utils/host/host_exec.h
 src/utils/host/host_main.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 13acc648a5c8e81d820b1bc5932664c97193a720..1d9f2633aad2e8555810d3944decf5516d377080 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
 ACLOCAL_AMFLAGS = -I ../m4
-libexec_PROGRAMS = knot-zcompile unittests unittests-zcompile unittests-xfr unittests-zscanner khost knsupdate
+libexec_PROGRAMS = knot-zcompile unittests unittests-zcompile unittests-xfr unittests-zscanner kdig khost knsupdate
 sbin_PROGRAMS = knotc knotd
 dist_man_MANS = knot.conf.5 knotc.8 knotd.8
 
@@ -30,6 +30,25 @@ CLEANFILES =					\
 knotc_SOURCES =					\
 	knot/ctl/knotc_main.c
 
+kdig_SOURCES =					\
+	utils/common/msg.h			\
+	utils/common/msg.c			\
+	utils/common/exec.c			\
+	utils/common/exec.h			\
+	utils/common/params.c			\
+	utils/common/params.h			\
+	utils/common/resolv.c			\
+	utils/common/resolv.h			\
+	utils/common/netio.c			\
+	utils/common/netio.h			\
+	utils/common/rr-serialize.h		\
+	utils/common/rr-serialize.c		\
+	utils/dig/dig_main.c			\
+	utils/dig/dig_params.c			\
+	utils/dig/dig_params.h			\
+	utils/dig/dig_exec.c			\
+	utils/dig/dig_exec.h
+
 khost_SOURCES =					\
 	utils/common/msg.h			\
 	utils/common/msg.c			\
@@ -317,6 +336,7 @@ libknots_la_LIBADD = @LIBOBJS@
 libzscanner_la_LIBADD = libknots.la
 knotd_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
 knotc_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
+kdig_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
 khost_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
 knsupdate_LDADD = libknotd.la libknot.la libknots.la libzscanner.la @LIBOBJS@
 knot_zcompile_LDADD = libknots.la libknot.la libknotd.la @LIBOBJS@
diff --git a/src/utils/dig/dig_exec.c b/src/utils/dig/dig_exec.c
new file mode 100644
index 0000000000000000000000000000000000000000..905027ae8913d6e4ec43fea8efd906bff650aaa5
--- /dev/null
+++ b/src/utils/dig/dig_exec.c
@@ -0,0 +1,50 @@
+/*  Copyright (C) 2011 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/>.
+*/
+
+#include "utils/dig/dig_exec.h"
+
+#include "common/lists.h"		// list
+#include "common/errcode.h"		// KNOT_EOK
+
+#include "utils/common/msg.h"		// WARN
+#include "utils/common/params.h"	// params_t
+#include "utils/common/exec.h"		// process_query
+
+int dig_exec(const params_t *params)
+{
+	node *query = NULL;
+
+	if (params == NULL) {
+		return KNOT_EINVAL;
+	}
+
+	switch (params->operation) {
+	case OPERATION_QUERY:
+		// Loop over query list.
+		WALK_LIST(query, params->queries) {
+			process_query(params, (query_t *)query);
+		}
+
+		break;
+	case OPERATION_LIST_SOA:
+		break;
+	default:
+		ERR("unsupported operation\n");
+		break;
+	}
+
+	return KNOT_EOK;
+}
diff --git a/src/utils/dig/dig_exec.h b/src/utils/dig/dig_exec.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bae9fe03cbf0c4d40e6046640380d31d75a3411
--- /dev/null
+++ b/src/utils/dig/dig_exec.h
@@ -0,0 +1,36 @@
+/*  Copyright (C) 2011 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/>.
+ */
+/*!
+ * \file dig_exec.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief dig executives.
+ *
+ * \addtogroup utils
+ * @{
+ */
+
+#ifndef _DIG__DIG_EXEC_H_
+#define _DIG__DIG_EXEC_H_
+
+#include "utils/common/params.h"	// params_t
+
+int dig_exec(const params_t *params);
+
+#endif // _DIG__DIG_EXEC_H_
+
+/*! @} */
diff --git a/src/utils/dig/dig_main.c b/src/utils/dig/dig_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a600126ee821f71709945e9a02553d6b1ad5c43
--- /dev/null
+++ b/src/utils/dig/dig_main.c
@@ -0,0 +1,37 @@
+/*  Copyright (C) 2011 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/>.
+*/
+
+#include <stdlib.h>			// EXIT_FAILURE
+
+#include "common/errcode.h"		// KNOT_EOK
+#include "utils/dig/dig_params.h"	// dig_params_parse
+#include "utils/dig/dig_exec.h"		// dig_exec
+
+int main(int argc, char *argv[])
+{
+	params_t params;
+
+	if (dig_params_parse(&params, argc, argv) != KNOT_EOK) {
+		return EXIT_FAILURE;
+	}
+
+	dig_exec(&params);
+
+	dig_params_clean(&params);
+
+	return EXIT_SUCCESS;
+}
+
diff --git a/src/utils/dig/dig_params.c b/src/utils/dig/dig_params.c
new file mode 100644
index 0000000000000000000000000000000000000000..363a09774103251021233136ee4598f5f434a245
--- /dev/null
+++ b/src/utils/dig/dig_params.c
@@ -0,0 +1,332 @@
+/*  Copyright (C) 2011 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/>.
+*/
+
+#include "utils/dig/dig_params.h"
+
+#include <string.h>			// strncmp
+#include <stdio.h>			// printf
+#include <getopt.h>			// getopt
+#include <stdlib.h>			// free
+
+#include "common/lists.h"		// list
+#include "common/errcode.h"		// KNOT_EOK
+#include "libknot/util/descriptor.h"	// KNOT_CLASS_IN
+#include "utils/common/msg.h"		// WARN
+#include "utils/common/params.h"	// parse_class
+#include "utils/common/resolv.h"	// get_nameservers
+#include "utils/common/netio.h"
+
+static void dig_params_init(params_t *params)
+{
+	memset(params, 0, sizeof(*params));
+
+	// Read default nameservers.
+	if (get_nameservers(&params->servers) <= 0) {
+		WARN("can't read any default nameservers\n");
+	}
+
+	// Initialize list of queries.
+	init_list(&params->queries);
+
+	// Default values.
+	params->operation = OPERATION_QUERY;
+	params->ip = IP_ALL;
+	params->protocol = PROTO_ALL;
+	params->udp_size = DEFAULT_UDP_SIZE;
+	params->class_num = KNOT_CLASS_IN;
+	params->type_num = -1;
+	params->xfr_serial = -1;
+	params->recursion = true;
+	params->retries = 1;
+	params->wait = DEFAULT_WAIT_INTERVAL;
+	params->servfail_stop = false;
+	params->format = FORMAT_VERBOSE;
+}
+
+void dig_params_clean(params_t *params)
+{
+	node *n = NULL, *nxt = NULL;
+
+	if (params == NULL) {
+		return;
+	}
+
+	// Clean up server list.
+	WALK_LIST_DELSAFE(n, nxt, params->servers) {
+		server_free((server_t *)n);
+	}
+
+	// Clean up query list.
+	WALK_LIST_DELSAFE(n, nxt, params->queries) {
+		query_free((query_t *)n);
+	}
+
+	// Clean up the structure.
+	memset(params, 0, sizeof(*params));
+}
+
+static void dig_params_flag_all(params_t *params)
+{
+	params->type_num = KNOT_RRTYPE_ANY;
+	params->format = FORMAT_VERBOSE;
+}
+
+static void dig_params_flag_soa(params_t *params)
+{
+	params->type_num = KNOT_RRTYPE_SOA;
+	params->operation = OPERATION_LIST_SOA;
+}
+
+static void dig_params_flag_axfr(params_t *params)
+{
+	params->type_num = KNOT_RRTYPE_AXFR;
+}
+
+static void dig_params_flag_nonrecursive(params_t *params)
+{
+	params->recursion = false;
+}
+
+static void dig_params_flag_ipv4(params_t *params)
+{
+	params->ip = IP_4;
+}
+
+static void dig_params_flag_ipv6(params_t *params)
+{
+	params->ip = IP_6;
+}
+
+static void dig_params_flag_servfail(params_t *params)
+{
+	params->servfail_stop = true;
+}
+
+static void dig_params_flag_nowait(params_t *params)
+{
+	params->wait = -1;
+}
+
+static int dig_params_parse_name(params_t *params, const char *name)
+{
+	char	*reverse = get_reverse_name(name);
+	char	*fqd_name = NULL;
+	query_t	*query;
+
+	// If name is not FQDN, append trailing dot.
+	fqd_name = get_fqd_name(name);
+
+	// RR type is known.
+	if (params->type_num >= 0) {
+		if (params->type_num == KNOT_RRTYPE_PTR) {
+			// Check for correct address.
+			if (reverse == NULL) {
+				ERR("invalid IPv4 or IPv6 address\n");
+				free(fqd_name);
+				return KNOT_EINVAL;
+			}
+
+			// Add reverse query for address.
+			query = query_create(reverse, params->type_num);
+			if (query == NULL) {
+				free(reverse);
+				free(fqd_name);
+				return KNOT_ENOMEM;
+			}
+			add_tail(&params->queries, (node *)query);
+		} else {
+			// Add query for name and specified type.
+			query = query_create(fqd_name, params->type_num);
+			if (query == NULL) {
+				free(reverse);
+				free(fqd_name);
+				return KNOT_ENOMEM;
+			}
+			// Set SOA serial for IXFR query.
+			if (params->type_num == KNOT_RRTYPE_IXFR) {
+				query_set_serial(query, params->xfr_serial);
+			}
+			add_tail(&params->queries, (node *)query);
+		}
+	// RR type is unknown, use defaults.
+	} else {
+		if (reverse == NULL) {
+			// Add query for name and type A.
+			query = query_create(fqd_name, KNOT_RRTYPE_A);
+			if (query == NULL) {
+				free(fqd_name);
+				return KNOT_ENOMEM;
+			}
+			add_tail(&params->queries, (node *)query);
+
+			// Add query for name and type AAAA.
+			query = query_create(fqd_name, KNOT_RRTYPE_AAAA);
+			if (query == NULL) {
+				free(fqd_name);
+				return KNOT_ENOMEM;
+			}
+			add_tail(&params->queries, (node *)query);
+
+			// Add query for name and type MX.
+			query = query_create(fqd_name, KNOT_RRTYPE_MX);
+			if (query == NULL) {
+				free(fqd_name);
+				return KNOT_ENOMEM;
+			}
+			add_tail(&params->queries, (node *)query);
+		} else {
+			// Add reverse query for address.
+			query = query_create(reverse, KNOT_RRTYPE_PTR);
+			if (query == NULL) {
+				free(reverse);
+				free(fqd_name);
+				return KNOT_ENOMEM;
+			}
+			add_tail(&params->queries, (node *)query);
+		}
+	}
+
+	free(reverse);
+	free(fqd_name);
+
+	return KNOT_EOK;
+}
+
+static int dig_params_parse_server(params_t *params, const char *name)
+{
+	node *n = NULL, *nxt = NULL;
+
+	// Remove default nameservers.
+        WALK_LIST_DELSAFE(n, nxt, params->servers) {
+                server_free((server_t *)n);
+        }
+
+	// Initialize blank server list.
+	init_list(&params->servers);
+
+	// Add specified nameserver.
+	server_t *server = parse_nameserver(name);
+	if (server == NULL) {
+		return KNOT_ENOMEM;
+	}
+	add_tail(&params->servers, (node *)server);
+
+	return KNOT_EOK;
+}
+
+static void dig_params_help(int argc, char *argv[])
+{
+	printf("Usage: %s [-aCdlrsTvw] [-4] [-6] [-c class] [-R retries]\n"
+	       "       %*c [-t type] [-W time] name [server]\n",
+	       argv[0], (int)strlen(argv[0]), ' ');
+}
+
+int dig_params_parse(params_t *params, int argc, char *argv[])
+{
+	int opt = 0;
+
+	if (params == NULL || argv == NULL) {
+		return KNOT_EINVAL;
+	}
+
+	dig_params_init(params);
+
+	// Command line options processing.
+	while ((opt = getopt(argc, argv, "46aCdlrsTvwc:R:t:W:")) != -1) {
+		switch (opt) {
+		case '4':
+			dig_params_flag_ipv4(params);
+			break;
+		case '6':
+			dig_params_flag_ipv6(params);
+			break;
+		case 'a':
+			dig_params_flag_all(params);
+			break;
+		case 'C':
+			dig_params_flag_soa(params);
+			break;
+		case 'd':
+		case 'v': // Fall through.
+			params_flag_verbose(params);
+			break;
+		case 'l':
+			dig_params_flag_axfr(params);
+			break;
+		case 'r':
+			dig_params_flag_nonrecursive(params);
+			break;
+		case 's':
+			dig_params_flag_servfail(params);
+			break;
+		case 'T':
+			params_flag_tcp(params);
+			break;
+		case 'w':
+			dig_params_flag_nowait(params);
+			break;
+		case 'c':
+			if (parse_class(optarg, &(params->class_num))
+			    != KNOT_EOK) {
+				return KNOT_EINVAL;
+			}
+			break;
+		case 'R':
+			if (params_parse_num(optarg, &(params->retries))
+			    != KNOT_EOK) {
+				return KNOT_EINVAL;
+			}
+			break;
+		case 't':
+			if (parse_type(optarg, &(params->type_num),
+			               &(params->xfr_serial))
+			    != KNOT_EOK) {
+				return KNOT_EINVAL;
+			}
+			break;
+		case 'W':
+			if (params_parse_interval(optarg, &(params->wait))
+			    != KNOT_EOK) {
+				return KNOT_EINVAL;
+			}
+			break;
+		default:
+			dig_params_help(argc, argv);
+			return KNOT_ENOTSUP;
+		}
+	}
+
+	// Process non-option parameters.
+	switch (argc - optind) {
+	case 2:
+		if (dig_params_parse_server(params, argv[optind + 1])
+		    != KNOT_EOK) {
+			return KNOT_EINVAL;
+		}
+	case 1: // Fall through.
+		if (dig_params_parse_name(params, argv[optind])
+		    != KNOT_EOK) {
+			return KNOT_EINVAL;
+		}
+		break;
+	default:
+		dig_params_help(argc, argv);
+		return KNOT_ENOTSUP;
+	}
+
+	return KNOT_EOK;
+}
+
diff --git a/src/utils/dig/dig_params.h b/src/utils/dig/dig_params.h
new file mode 100644
index 0000000000000000000000000000000000000000..37f9e84305d806f0cdc26d2fabccd906aec358ef
--- /dev/null
+++ b/src/utils/dig/dig_params.h
@@ -0,0 +1,39 @@
+/*  Copyright (C) 2011 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/>.
+ */
+/*!
+ * \file dig_params.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Dig command line parameters.
+ *
+ * \addtogroup knot
+ * @{
+ */
+
+#ifndef _DIG__DIG_PARAMS_H_
+#define _DIG__DIG_PARAMS_H_
+
+#include "utils/common/params.h"	// params_t
+
+
+
+int host_params_parse(params_t *params, int argc, char *argv[]);
+void host_params_clean(params_t *params);
+
+#endif // _DIG__DIG_PARAMS_H_
+
+/*! @} */
diff --git a/src/utils/host/host_params.h b/src/utils/host/host_params.h
index 2f1f4a43a472309d39d468dce22dd9ea5d45f9a4..0e5335b04b039c209a11f29af55bdbedc0270748 100644
--- a/src/utils/host/host_params.h
+++ b/src/utils/host/host_params.h
@@ -18,9 +18,9 @@
  *
  * \author Daniel Salzman <daniel.salzman@nic.cz>
  *
- * \brief Host command line parameters.
+ * \brief host command line parameters.
  *
- * \addtogroup knot_utils
+ * \addtogroup utils
  * @{
  */